最近使用容量為K的快取結構

2021-10-02 15:27:50 字數 4053 閱讀 7185

【題目】 設計一種快取結構,該結構在構造時確定大小,假設大小為k,並有兩個功能:

get(key):返回key對應的value值;

set(key,value):將**記錄(key,value)**插入該結構。

【要求】

get和set方法的時間複雜度為o(1

)o(1)

o(1)

某個key的get和set操作一旦發生,認為這個key的記錄成了最經常使用的。

當快取的大小超過k時,移除最不經常使用的記錄,即get和set最久遠的。

【舉例】 假設快取結構的例項是cache,大小為3,並依次發生如下行為:

cache.set(「a」,1)。最經常使用的記錄為(「a」,1)。

cache.set(「b」,2)。最經常使用的記錄為(「b」,2),(「a」,1)變為最不經常的。

cache.set(「c」,3)。最經常使用的記錄為(「c」,2),(「a」,1)還是最不經常的。

cache.get(「a」)。最經常使用的記錄為(「a」,1),(「b」,2)變為最不經常的。

cache.set(「d」,4)。大小超過了3,所以移除此時最不經常使用的記錄 (「b」,2),加入記錄(「d」,4)。

此時(「d」,4)為最經常使用的記錄,然後(「c」,2)變為最不經常使用的記錄。

lru(least recently used):最近最少使用演算法

雜湊表本身get和set方法的時間複雜度為o(1

)o(1)

o(1)

,但需要在k容量下維護最近最經常使用的記錄,因此在其基礎上,再增添結構。

注意:快取結構需要更新內部節點(值)位置,因此不可以collections模組中deque實現。

# value儲存在node中

class

node

:def

__init__

(self, value)

: self.value = value

self.last =

none

self.

next

=none

# 雙端佇列

# 注意:快取結構需要更新內部節點位置,因此不可以用collections模組中deque實現

class

nodedoublelinkedlist

:def

__init__

(self)

: self.head =

none

self.tail =

none

# 新增節點至末尾

defaddtail

(self, node)

:if self.tail is

none

: self.head = node

self.tail = node

else

: self.tail.

next

= node

node.last = self.tail

self.tail = node

# 移除頭節點

defremovehead

(self)

:if self.head is

none

:return

res = self.head

if self.head is self.tail:

self.head =

none

self.tail =

none

else

: self.head = res.

next

res.

next

=none

self.head.last =

none

return res

# 將已存在的節點移至末尾

defmovenodetotail

(self, node)

:if node == self.tail:

return

# 至少有兩個節點,處理前後節點鏈結

if node == self.head:

self.head = self.head.

next

self.head.last =

none

else

: node.last.

next

= node.

next

node.

next

.last = node.last

# 移至末尾,並標記為tail

node.last = self.tail

self.tail.

next

= node

self.tail = node

class

mycache

:def

__init__

(self, capacity)

: self.keynodemap =

self.nodekeymap =

self.nodelist = nodedoublelinkedlist(

) self.capacity = capacity

defget(self, key)

:if key not

in self.keynodemap:

return

none

node = self.keynodemap.get(key)

self.nodelist.movenodetotail(node)

return node

# 存在則更新,不存在則新增

defset

(self, key, value)

:if key in self.keynodemap:

node = self.keynodemap[key]

node.value = value

self.nodelist.movenodetotail(node)

else

: node = node(value)

self.keynodemap[key]

= node

self.nodekeymap[node]

= key

self.nodelist.addtail(node)

# 超出容量,移除最不經常使用的節點

iflen

(self.nodekeymap)

== self.capacity +1:

head = self.nodelist.removehead(

) key = self.nodekeymap[head]

del self.keynodemap[key]

del self.nodekeymap[node]

# 簡單測試

if __name__ ==

'__main__'

: cache = mycache(3)

cache.

set(

'a',1)

cache.

set(

'b',2)

cache.

set(

'c',3)

cache.

set(

'd',4)

nodelist = cache.nodelist

cur = nodelist.head

while cur !=

none

:print

(cur.value, end=

' ')

cur = cur.

next

大容量U盤顯示為小容量的解決方法

今天在電腦上開啟好久沒用的u盤一看,發現其容量為5.4g。同時檢視u盤標籤發現是16g的容量,然後就是格式化操作,結果發現沒有任何效果。通過搜尋發現在windows上可以通過如下方式解決 1 win r 開啟cmd 2 diskpart 會又彈出乙個cmd視窗 3 list disk 檢視當前電腦上...

HashMap 容量為2次冪的原因

我們都知道 hashmap 的底層是乙個陣列加鍊表的結構,當向其中新增乙個元素的時候,需要根據key的hash值,去確定其在陣列中的具體位置。看原始碼,我們可以發現,確定陣列位置的實現是i n 1 hash,其中 n 代表陣列的長度,即map的容量。當n為2的冪次方時,n 1 hash 的值是均勻分...

HashMap的初始容量設定為多少合適?

我們知道對於list map這種底層是基於陣列的動態容器,在擴容時會進行陣列複製,因此為了避免這種額外開銷,應該盡量在建立時指定大小。對於沒有負載因子的如list,其擴容策略為滿了後下次插入進行擴容,因此初始化大小為需要大小即可 對於存在負載因子的hashmap hashset等,其擴容策略為本次插...