什麼是lfu?
當記憶體不足時,優先刪除被操作次數最少的元素。
雜湊表 + 二維雙向鍊錶
二維鍊錶維護不同訪問次數和相同訪問次數結點集合之間的關係。每一列的雙向鍊錶是所有出現操作次數相同的節點的集合,次數鍊錶的頭節點之間也相互連線的,同樣構成雙向鍊錶。
二維鍊錶的結構:
鍊錶中node結點的設計:
public
static
class
node
}
每一列的雙向鍊錶單獨維護,每列之間也使用雙向指標進行連線:
/**
* 相當於乙個二維的雙向鍊錶,上下鍊錶的是相同次數的結點,左右連線的是不同次數的結點
*/public
static
class
nodelist
//新增乙個節點,放到nodelist的頭部
public
void
addfromhead
(node node)
public
boolean
isempty()
//刪除指定的結點
public
void
deletenode
(node node)
else
else
if(tail == node)
else
}//釋放該結點的所有引用
node.up = null;
node.down = null;
}}
lru設計思路當元素被操作(新增、訪問…)後,將對應的node的times++,然後被操作的結點從原來的列中刪除,移到現在times所在的列。這樣快取中操作次數最少的元素就總是在第一列的第乙個node,當面臨記憶體淘汰時就優先從頭開始刪除。
public
class
lfucache
}/**
* 相當於乙個二維的雙向鍊錶,上下鍊錶的是相同次數的結點,左右連線的是不同次數的結點
*/public
static
class
nodelist
//新增乙個節點,放到nodelist的頭部
public
void
addfromhead
(node node)
public
boolean
isempty()
//刪除指定的結點
public
void
deletenode
(node node)
else
else
if(tail == node)
else
}//釋放該結點的所有引用
node.up = null;
node.down = null;}}
int capacity;
//快取的容量
int size;
//快取中目前的容量大小
hashmap
records;
//記錄key對應的node
hashmap
heads;
//記錄每個node在哪個列中
nodelist headlist;
//記錄第一列,當面臨擴容問題時,刪除第一列的第乙個結點
public
lfucache
(int capacity)
//新增元素
public
void
set(integer key, integer value)
else
node node =
newnode
(key, value,1)
;if(headlist == null)
else
else
} records.
put(key, node)
; heads.
put(node,headlist)
; size++;}
}public
intget
(integer key)
node node = records.
get(key)
; node.times++
; nodelist nodelist = heads.
get(node)
;move
(node, nodelist)
;return node.value;
}//將node從原來的nodelist中刪除,移到++times的nodelist的頭節點
private
void
move
(node node, nodelist oldnodelist)
newlist.last = prenodelist;
if(headlist == null)
heads.
put(node, newlist);}
else
else
else
newlist.last = prenodelist;
newlist.next = nextlist;
nextlist.last = newlist;
heads.
put(node,newlist);}
}}//判斷指定的nodelist中是否還有結點,如果沒有則刪除並且返回true,否則返回false
private
boolean
modifyheadlist
(nodelist nodelist)
}else
}return
true;}
return
false;}
public
static
void
main
(string[
] args)
}
需要對鍊錶的操作的比較熟悉,細節比較繁瑣。寫完不放心的同學可以到lintcode中跑一下哦。 LFU快取策略
example lfucache cache new lfucache 2 capacity cache.put 1,1 cache.put 2,2 cache.get 1 returns 1 cache.put 3,3 evicts key 2 cache.get 2 returns 1 not ...
LFU演算法實現(460 LFU快取)
今天位元組客戶端三面問了這道題,沒做出來。第一,之前沒見過lfu,第二,要求o 1 時間,條件苛刻一點。只能說無緣位元組。言歸正傳,lfu演算法 least frequently used,最近最不經常使用演算法。什麼意思呢 對於每個條目,維護其使用次數cnt 最近使用時間time。cache容量為...
演算法題 LFU快取
題目 設計並實現最不經常使用 lfu 快取的資料結構。它應該支援以下操作 get 和 put。get key 如果鍵存在於快取中,則獲取鍵的值 總是正數 否則返回 1。put key,value 如果鍵不存在,請設定或插入值。當快取達到其容量時,它應該在插入新專案之前,使最不經常使用的專案無效。在此...