手写LRU

手写LRU

1.要求

  • put / get 均是 O(1) 时间复杂度
  • 超出容量自动删除最老数据

2.用什么数据结构?

  • 任意查找要求 O(1),必然有哈希
  • 时间需要有序,必然链表或者数组

    • 由于删除需求,也要控制在O(1),数组淘汰
    • 由於单链表删除节点,需要寻找前驱,并非 O(1),所以单链表淘汰

    所以结论,哈希(key-->node) + 双链表,哈希存key维持映射关系,双链表维持时序以及val

3.进一步,链表的Node定义是?

  • 初版

    class Node(object):
      def __init__(self, v):
          self.val = v
          self.pre = None
          self.next = None
    意思是3个字段:前驱、后继、val
    
  • 满足需求嘛?

    咋看是满足需求的。val字段用来存储值即可,前驱后继也都满足O(1)诉求

    • 特例:当node超出容量时,每次新进一个节点,就需要淘汰链尾的节点(链尾的节点时间最久)
    • 问题来了:链尾节点(val)删除了,它对应的key还在哈希表里,哈希表会有脏数据
    • 结论:Node字段不足,还需要存储key
  • Node定义的结论

    class Node(object):
      def __init__(self, k, v):
          self.key = k
          self.val = v
          self.pre = None
          self.next = None
    意思是4个字段:前驱、后继、key, val
    

4.伪代码

def get(key):
    if key in hash:
        将对应的节点提到双链表表头
        return node.val
    else:
        return None


def put(key, val):
   Node x = Node(key, val)
   if key in hash:
       将旧的节点从双链表删除
       x节点插在双链表表头
   else:
       if cache is full:
           删除链尾节点
           将链尾节点的key从hash删除
       x节点插入双链表表头
       hash[key] = x节点
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章