美文网首页
Python实现LRU缓存结构

Python实现LRU缓存结构

作者: guoweikuang | 来源:发表于2018-06-24 16:59 被阅读19次

    LRU, Least Recently Used 近期最少使用算法, 常应用于缓存中的数据淘汰。也就是说最近最多使用的元素,出现的几率还是很高的,应该保持这种元素持续存在缓存中。
    那么,应该使用什么数据结构才能满足要求呢?如下图:


    92033a96-da60-11e4-8754-66135bb0d233.png

    这不是双向链表么?表头代表最近使用过的数据,表尾表示最久没有使用过的数据。当需要删除旧数据时,可以通过删除表尾节点,然后在表头接入一个新节点。而更新节点时,可以把原来的节点删除掉,然后重新接入表头。如果插入时没有达到容量的上限的话,可以一直往表头插入节点。

    实现中有一点需要注意,由于链表查找数据,需要从表头一步步查询到表尾,查找速度比较慢,
    所以我们可以使用Python的字典类型来存储数据的键值对。查找时,先判断是否存在于字典中,
    如果在,需要更新节点的使用情况并返回结果,没有就返回-1。
    

    实现

    class LRUCache(object):
        
        class Node(object):
            def __init__(self, key, value):
                self.key = key
                self.value = value
                self.prev = None
                self.next = None
                
        def __init__(self, capacity):
            self.capacity = capacity
            self.size = 0
            self.items = {}   # 存节点的键值对,方便查找某节点是否存在链表中
            self.head = self.Node(-1, -1)   # 双向链表头初始化
            self.tail = self.Node(-1, -1)   # 双向链表尾初始化
            self.head.next = self.tail      # 将头与尾连接起来
            self.tail.prev = self.head
            
        def __remove(self, node):
            """remove node.
            :params node: remove this node
            """
            node.prev.next = node.next  # 当前节点的前节点的next指向当前节点的后节点
            node.next.prev = node.prev  # 当前节点的后节点的prev指向当前节点的前节点
            node.prev = None   #把当前节点的前节点置空
            node.next = None
            
        def __insert(self, node):
            node.prev = self.head
            node.next = self.head.next
            self.head.next.prev = node
            self.head.next = node
            
        def get(self, key):
            if key not in self.items:
                return -1
            node = self.items[key] 
            self.__remove(node)   # 先删除该节点,然后在表头重新接入
            self.__insert(node)
            return node.value
        
        def put(self, key, value):
            if key in self.items:
                node = self.items[key]
                self.__remove(node)
                node.value = value
                self.__insert(node)
            else:
                # 判断LRU缓存中是否已经达到最大容量,是的话就删除表尾节点,然后再执行插入操作
                if self.size == self.capacity:
                    discard = self.tail.prev
                    self.__remove(discard)
                    del self.items[discard.key]
                    self.size -= 1
                    
                node = self.Node(key, value)
                self.items[key] = node
                self.__insert(node)
                self.size += 1
            
    

    相关文章

      网友评论

          本文标题:Python实现LRU缓存结构

          本文链接:https://www.haomeiwen.com/subject/gtksyftx.html