簡單實現LRU
阿新 • • 發佈:2020-10-25
要求
設計和實現一個LRU
(最近最少使用) 快取機制。它應該支援以下操作: 獲取資料 get
和 寫入資料save
,這兩種操作的時間複雜度都為O(1)
。
get
: 如果key
存在於快取中,則獲取金鑰的值(總是正數),否則返回 -1。
save(key, value)
:如果key
不存在,則寫入其資料值,如果存在,覆蓋其原來資料值。當快取容量達到上限時,它應該在寫入新資料之前刪除最近最少使用的資料值,從而為新的資料值留出空間。
Example
:
LRUCache cache = new LRUCache(2); cache.save(1, 1); cache.save(2, 2); cache.get(1); // 返回 1 cache.save(3, 3); // 該操作會使得金鑰 2 作廢 cache.get(2); // 返回 -1 (未找到) cache.save(4, 4); // 該操作會使得金鑰 1 作廢 cache.get(1); // 返回 -1 (未找到) cache.get(3); // 返回 3 cache.get(4); // 返回 4
實現
要進行插入和讀取的複雜度都為O(1)
,可以使用雙端連結串列以及字典來實現。因此需要自定義一個雙端連結串列節點,以及雙端連結串列,與字典一起構成個LRU
。
每當插入新值/修改值/獲得值時,都需要將節點插入到連結串列頭。當連結串列超過自定義大小時,將尾端節點刪除。
下面是一個簡單實現(沒有進行異常處理):
# -*- coding: utf-8 -*- # author: May # Time: 2019-05-27 18:01 class Node(object): def __init__(self, key, value): self.key = key self.value = value self.pre = None self.nxt = None class DoubleLinklist(object): def __init__(self): self.head = Node(0, 0) self.tail = Node(0, 0) self.head.nxt = self.tail self.tail.pre = self.head self.size = 0 class LRU(object): def __init__(self, size): self.link = DoubleLinklist() self.hash_map = {} self.size = size def add_to_head(self, node): f_node = self.link.head.nxt # 如果第一個節點是自己,不移動,否則會使自己指向自己 if node != f_node: self.link.head.nxt, node.pre = node, self.link.head node.nxt, f_node.pre = f_node, node def remove_node(self, node): p_node, n_node = node.pre, node.nxt p_node.nxt, n_node.pre = n_node, p_node def save(self, key, value): # 節點存在,則直接更改值,放置於連結串列頭 if key in self.hash_map: node = self.hash_map[key] node.value = value self.add_to_head(node) else: # 否則建立一個新節點,放置於連結串列頭 node = Node(key, value) self.add_to_head(node) self.hash_map[key] = node self.link.size += 1 # 當前連結串列大小大於指定大小時,才需要刪除最久未使用的節點 if self.link.size > self.size: t_node = self.link.tail.pre self.remove_node(t_node) del self.hash_map[t_node.key] del t_node self.link.size -= 1 return 'SUCCESS' def get(self, key): if key in self.hash_map: node = self.hash_map[key] self.add_to_head(node) return node.value else: return -1 def delete(self, key): if key in self.hash_map: node = self.hash_map[key] self.remove_node(node) self.link.size -= 1 del self.hash_map[key] del node return 'SUCCESS' else: return -1 cache = LRU(3) print(cache.save(1, 1)) # SUCCESS print(cache.save(2, 2)) # SUCCESS print(cache.save(1, 3)) # SUCCESS print(cache.get(1)) # 3 print(cache.save(3, 3)) # SUCCESS print(cache.get(2)) # 2 print(cache.save(4, 4)) # SUCCESS print(cache.get(1)) # -1 print(cache.get(3)) # 3 print(cache.get(4)) # 4 print(cache.delete(4)) # SUCCESS print(cache.get(4)) # -1 print(cache.delete(1)) # -1 print(cache.delete(3)) # SUCCESS print(cache.get(3)) # -1
References: