運用你所掌握的資料結構,設計和實現乙個 lru (最近最少使用) 快取機制。它應該支援以下操作: 獲取資料 get 和 寫入資料 put 。
獲取資料 get(key) - 如果關鍵字 (key) 存在於快取中,則獲取關鍵字的值(總是正數),否則返回 -1。
寫入資料 put(key, value) - 如果關鍵字已經存在,則變更其資料值;如果關鍵字不存在,則插入該組「關鍵字/值」。當快取容量達到上限時,它應該在寫入新資料之前刪除最久未使用的資料值,從而為新的資料值留出空間。
示例:lrucache cache = new lrucache( 2 /* 快取容量 */ );
cache.put(1, 1);
cache.put(2, 2);
cache.get(1); // 返回 1
cache.put(3, 3); // 該操作會使得關鍵字 2 作廢
cache.get(2); // 返回 -1 (未找到)
cache.put(4, 4); // 該操作會使得關鍵字 1 作廢
cache.get(1); // 返回 -1 (未找到)
cache.get(3); // 返回 3
cache.get(4); // 返回 4
設計的必要條件:
1.快取中的元素必須有時序,以區分最近使用的和久未使用的資料,當容量滿了之後要刪除最久未使用的那個元素,騰出位置。
2.要在快取中快速找某個key是否已存在並得到對應的value;
3.每次訪問快取中的某個key,需要將這個元素變為最近使用的,也就是說快取要支援在任意位置快速插入和刪除元素。
設計:
雜湊表查詢快,但是資料無固定順序;雙向鍊錶有順序之分,插入刪除快,但是查詢慢。所以結合形成一種新的資料結構:雜湊鍊錶。lru快取演算法的核心資料結構就是雜湊鍊錶,雙向鍊錶和雜湊表的結合體。
每次預設從鍊錶頭部新增元素,那麼越靠頭部的元素就是最近使用的,越靠尾部的元素就是最久未使用的。
對於某乙個key,可以通過雜湊表快速定位到鍊錶中的節點,從而取得對應value。
雙向鍊錶可以獲得前驅指標,支援在任意位置快速插入和刪除,但是鍊錶無法按照索引快速訪問某乙個位置的元素,而借助雜湊表,可以通過key快速對映到任意乙個鍊錶節點,然後進行插入和刪除。
雜湊表中已經儲存key,鍊錶中還要儲存key的原因:當快取已滿,不僅要刪除鍊錶節點,還要把雜湊表中對映到該節點的key同時刪除,而這個key只能由鍊錶節點得到,如果鍊錶節點中只儲存value,那麼就無法得知key,就無法刪除雜湊表中的key。
1class
lrucache:23
def__init__
(self, capacity: int):
4 self.dict = collections.ordereddict() #
有序字典
5 self.remain =capacity67
def get(self, key: int) ->int:
8if key not
in self.dict: return -1
9 v = self.dict.pop(key) #
取出該值並刪除它
10 self.dict[key] = v #
將其重新放回快取,且處於頂部(由於是有序字典)
11returnv12
13def put(self, key: int, value: int) ->none:
14if key in self.dict: #
如果key存在,則應先將其value刪除再更新為新值
15self.dict.pop(key)
16else: #
如果key不存在17#
快取未滿,放入新數值,容量減一
18if self.remain > 0: self.remain -= 1 19#
快取已滿,放入新數值,popitem返回並刪除字典中的最後一對鍵和值20#
last=false,以佇列方式彈出鍵值對,last=true,以堆疊方式彈出鍵值對
21else: self.dict.popitem(last =false)
22 self.dict[key] = value #
寫入新資料
2324
#your lrucache object will be instantiated and called as such:25#
obj = lrucache(capacity)26#
param_1 = obj.get(key)27#
obj.put(key,value)
1struct
dlinkednode //
預設初始化
10 dlinkednode(int _key, int
_value): key(_key),value(_value),prev(null),next(null) {}
11};
1213
class
lrucache
28void addtohead(dlinkednode *node)
34void removenode(dlinkednode *node)
38void movetohead(dlinkednode *node)
42 dlinkednode *removetail()
4748
49int
get(int
key) 57}
5859
void put(int key, int
value)
69 cache[key] = newnode; //
新節點新增進雜湊表中
70 addtohead(newnode); //
新增至鍊錶頭部,由於同一key,故可通過雜湊表定位該節點 71}
72else77}
78};
7980/**
81* your lrucache object will be instantiated and called as such:
82* lrucache* obj = new lrucache(capacity);
83* int param_1 = obj->get(key);
84* obj->put(key,value);
85*/
LRU快取機制
運用你所掌握的資料結構,設計和實現乙個 lru 最近最少使用 快取機制。它應該支援以下操作 獲取資料 get 和 寫入資料 put 獲取資料 get key 如果金鑰 key 存在於快取中,則獲取金鑰的值 總是正數 否則返回 1。寫入資料 put key,value 如果金鑰不存在,則寫入其資料值。...
LRU快取機制
運用你所掌握的資料結構,設計和實現乙個 lru 最近最少使用 快取機制。它應該支援以下操作 獲取資料 get 和 寫入資料 put 獲取資料 get key 如果金鑰 key 存在於快取中,則獲取金鑰的值 總是正數 否則返回 1。寫入資料 put key,value 如果金鑰不存在,則寫入其資料值。...
LRU快取機制
lru快取機制 最近最少使用 雙向鍊錶 雜湊表 不使用自帶 linkedhashmap 雙向鍊錶按照被使用的順序儲存了這些鍵值對,靠近頭部的鍵值對是最近使用的,而靠近尾部的鍵值對是最久未使用的。雜湊錶即為普通的雜湊對映 hashmap 通過快取資料的鍵對映到其在雙向鍊錶中的位置。首先使用雜湊表進行定...