運用你所掌握的資料結構,設計和實現乙個 lru (最近最少使用) 快取機制 。實現 lrucache 類:
lrucache(int capacity) 以正整數作為容量 capacity 初始化 lru 快取
int get(int key) 如果關鍵字 key 存在於快取中,則返回關鍵字的值,否則返回 -1 。
void put(int key, int value) 如果關鍵字已經存在,則變更其資料值;如果關鍵字不存在,則插入該組「關鍵字-值」。當快取容量達到上限時,它應該在寫入新資料之前刪除最久未使用的資料值,從而為新的資料值留出空間。
高階:你是否可以在 o(1) 時間複雜度內完成這兩種操作?
雜湊表 + 雙向鍊錶
演算法lru 快取機制可以通過雜湊表輔以雙向鍊錶實現,我們用乙個雜湊表和乙個雙向鍊錶維護所有在快取中的鍵值對。
雙向鍊錶按照被使用的順序儲存了這些鍵值對,靠近頭部的鍵值對是最近使用的,而靠近尾部的鍵值對是最久未使用的。
雜湊錶即為普通的雜湊對映(hashmap),通過快取資料的鍵對映到其在雙向鍊錶中的位置。
這樣以來,我們首先使用雜湊表進行定位,找出快取項在雙向鍊錶中的位置,隨後將其移動到雙向鍊錶的頭部,即可在 o(1)o(1) 的時間內完成 get 或者 put 操作。具體的方法如下:
1.對於 get 操作,首先判斷 key 是否存在:
如果 key 不存在,則返回 -1−1;
如果 key 存在,則 key 對應的節點是最近被使用的節點。通過雜湊表定位到該節點在雙向鍊錶中的位置,並將其移動到雙向鍊錶的頭部,最後返回該節點的值。
2.對於 put 操作,首先判斷 key 是否存在:
如果 key 不存在,使用 key 和 value 建立乙個新的節點,在雙向鍊錶的頭部新增該節點,並將 key 和該節點新增進雜湊表中。然後判斷雙向鍊錶的節點數是否超出容量,如果超出容量,則刪除雙向鍊錶的尾部節點,並刪除雜湊表中對應的項;
如果 key 存在,則與 get 操作類似,先通過雜湊表定位,再將對應的節點的值更新為 value,並將該節點移到雙向鍊錶的頭部。
上述各項操作中,訪問雜湊表的時間複雜度為 o(1)o(1),在雙向鍊錶的頭部新增節點、在雙向鍊錶的尾部刪除節點的複雜度也為 o(1)o(1)。而將乙個節點移到雙向鍊錶的頭部,可以分成「刪除該節點」和「在雙向鍊錶的頭部新增節點」兩步操作,都可以在 o(1)o(1) 時間內完成。
type lrucache structtype link struct
func initlink(key, value int) *link
}func constructor(cap int) lrucache
l.head.next = l.tail
l.tail.pre = l.head
return l
}func (l *lrucache) get (key int) int
node := l.cache[key]
l.movetohead(node)
return node.value
}func (l *lrucache) put(key, value int)
} else
}func (l *lrucache) addtohead(node *link)
func (l *lrucache) removenode(node *link)
func (l *lrucache) movetohead(node *link)
func (l *lrucache) removetail() *link
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 通過快取資料的鍵對映到其在雙向鍊錶中的位置。首先使用雜湊表進行定...