LRU算法基础实现

119 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

1、LRU算法含义

LRU算法,全称为least recently used,也即最近最久未使用算法。当LRU缓存达到上限时,该算法会将最久未使用的数据淘汰掉,从而腾出空间给即将添加的数据。

2、LRU算法的设计

由于LRU算法结构要保存顺序结构,又要能快速的查询和删除。我们知道链表可以实现快速的删除和增加元素,但是查询是低效的。 而哈希表的查找是O(1)时间复杂度的。 所以我们可以将这两种数据结构结合起来。

3、LRU算法的基本实现

首先,定义双链表节点。

class ListNode:
    def __init__(self, key, value):
        self.key = key
        self.value = value
        self.next = None
        self.prev = None
class LRUCache:

    def __init__(self, capacity: int):
        self.size = capacity
        # 定义双链表的头和尾结点
        self.head = ListNode(0, 0)
        self.tail = ListNode(0, 0)
        self.head.next = self.tail
        self.tail.prev = self.head
        self.map = dict()

    def get(self, key: int) -> int:
    	# 节点不存在时
        if key not in self.map:
            return -1
        
    	# 通过map找到相关节点
        node = self.map[key]
        # 删除节点,并放在链表最后	
        # 在实现时可以先考虑要实现的逻辑,具体函数内容在来实现。 
        self.removeNode(node)
        self.addLast(node)
        
        return node.value

    def put(self, key: int, value: int) -> None:
        
        if key in self.map:
        	# 同查询,将节点提到最后并同时更新值。 
            node = self.map[key]
            self.removeNode(node)
            # 更新值
            node.value = value
            # 添加到末尾
            self.addLast(node) 
        else:
        	# 判断是否超出容量。 
            if len(self.map) >= self.size:
                self.removeFirst()
                
            node = ListNode(key, value)
            self.addLast(node)
       
    def removeNode(self, node):
        if self.head.next == self.tail:
            return
        
        prev = node.prev
        prev.next = node.next
        node.next.prev = prev
        node.prev = None
        node.next = None


    def removeFirst(self):
        if self.head.next == self.tail:
            # 空链表,不处理
            return
        
        tmp = self.head.next
        self.head.next = tmp.next
        tmp.next.prev = self.head
        
        # 删除map中的元素
        self.map.pop(tmp.key)
        return tmp
        
    def addLast(self, node):
        prev = self.tail.prev
        prev.next = node
        node.prev = prev
        
        node.next = self.tail
        self.tail.prev = node
        
        # 在map中添加
        self.map[node.key] = node

4、总结

每种数据结构有其特定的特征,在实际的编码过程中,根据实际问题,我们可以尝试将不同的数据结构结合起来形成一种“新”的数据结构来解决问题。 这种想法和思想还是很有趣的。 在android中sdk源码使用LinkedHashMap也实现了Lru的算法,可以学习一下。