手寫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節點
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章