摘要:如果每一個(gè)頻率放在一個(gè)里面,每個(gè)也有頭尾兩個(gè)指針,指向相鄰的。實(shí)際上相鄰的可以由的第一可以由的最后一個(gè)唯一確認(rèn)。也就是說,在的設(shè)計(jì)基礎(chǔ)上。也就是說頻率為的點(diǎn),指向的下一個(gè)是頻率為的點(diǎn)移除和一樣。里存在的點(diǎn),加到尾部的后一個(gè)。
只個(gè)代碼由LRU改進(jìn)得到。
如果每一個(gè)頻率放在一個(gè)LRU里面,每個(gè)LRU也有頭尾兩個(gè)指針,指向相鄰的LRU。
實(shí)際上相鄰的LRU可以由frequency = t+1的第一node,可以由frequency = t的最后一個(gè)唯一確認(rèn)。
也就是說,在LRU的設(shè)計(jì)基礎(chǔ)上。我們再多記錄一個(gè)finalNodes,記錄每種頻率的尾部就好了。
代碼因?yàn)榍闆r較多,所以要分析好了,才能歸并。
頻率可以不連續(xù),最小頻率也不一定為1. 我們put(1,1), get(1) LFU里現(xiàn)在只有這個(gè)點(diǎn),頻率為2,最小頻率不是1.
我們在put(2,2), get(2),get(2), get(2). 2出現(xiàn)了4次。 也就是說頻率為2的點(diǎn)1, 指向的下一個(gè)是頻率為4的點(diǎn)2.
移除node和LRU一樣。
添加node,
map里不存在的要加到頭部。
2.1 map里存在的點(diǎn),加到freq + 1尾部的后一個(gè)。
2.2 如果剛好freq+1這個(gè)頻率不存在(也就是freq+1在finalNodes里沒有,我們就不需要移動(dòng)。)
public class LFUCache { private int capacity; private int count; private HashMapmap1; // whether appeared private HashMap finalNodes; // value : the final node of key times private Tuple dummyHead; private Tuple dummyEnd; public LFUCache(int capacity) { this.capacity = capacity; count = 0; map1 = new HashMap (); finalNodes = new HashMap<>(); dummyHead = new Tuple(0, 0, 0); dummyEnd = new Tuple(0, 0, 0); dummyHead.next = dummyEnd; dummyEnd.prev = dummyHead; } public int get(int key) { if (capacity == 0 || !map1.containsKey(key)) { return -1; } Tuple old = map1.get(key); put(key, old.value); return old.value; } public void put(int key, int value) { if (capacity == 0) { return; } if (map1.containsKey(key)) { // this key has appeared Tuple cur = map1.get(key); if (finalNodes.get(cur.times) == cur && finalNodes.get(cur.times + 1) == null) { // the position should not change finalNodes.put(cur.times, cur.prev.times == cur.times ? cur.prev : null); cur.times++; cur.value = value; finalNodes.put(cur.times, cur); return; } removeNode(cur); // remove node cur if (finalNodes.get(cur.times) == cur) { finalNodes.put(cur.times, cur.prev.times == cur.times ? cur.prev : null); } cur.times++; cur.value = value; Tuple finalNode = finalNodes.get(cur.times) == null ? finalNodes.get(cur.times - 1) : finalNodes.get(cur.times); insertNode(finalNode, cur); finalNodes.put(cur.times, cur); } else { if (count == capacity) { // reach limt of the cache Tuple head = dummyHead.next; removeNode(head); //remove the first which appeared least times and is the least Used map1.remove(head.key); if (finalNodes.get(head.times) == head) { finalNodes.remove(head.times); } } else { count++; } insertHead(key, value); } } public void insertHead(int key, int value) { Tuple cur = new Tuple(key, value, 1); if (finalNodes.get(1) == null) { insertNode(dummyHead, cur); } else { Tuple finalNode = finalNodes.get(1); insertNode(finalNode, cur); } finalNodes.put(1, cur); map1.put(key, cur); } public void insertNode(Tuple t1, Tuple t2) { t2.next = t1.next; t1.next.prev = t2; t1.next = t2; t2.prev = t1; } public void removeNode(Tuple node) { node.next.prev = node.prev; node.prev.next = node.next; } class Tuple { int key; int value; int times; Tuple prev; Tuple next; public Tuple(int key, int value, int times) { this.key = key; this.value = value; this.times = times; } } } /** * Your LFUCache object will be instantiated and called as such: * LFUCache obj = new LFUCache(capacity); * int param_1 = obj.get(key); * obj.put(key,value); */
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/66584.html
摘要:在靜態(tài)的頻率分布下,性能也落后于因?yàn)槠洳辉贋椴辉诰彺嬷械臄?shù)據(jù)維護(hù)任何頻率數(shù)據(jù)??梢栽斠姷臏?zhǔn)入淘汰策略是新增一個(gè)新的元素時(shí),判斷使用該元素替換一個(gè)舊元素,是否可以提升緩存命中率。 1. Introduction LFU的局限: LFU實(shí)現(xiàn)需要維護(hù)大而復(fù)雜的元數(shù)據(jù)(頻次統(tǒng)計(jì)數(shù)據(jù)等) 大多數(shù)實(shí)際工作負(fù)載中,訪問頻率隨著時(shí)間的推移而發(fā)生根本變化(這是外賣業(yè)務(wù)不適合樸素LFU的根本原因) 針...
摘要:在靜態(tài)的頻率分布下,性能也落后于因?yàn)槠洳辉贋椴辉诰彺嬷械臄?shù)據(jù)維護(hù)任何頻率數(shù)據(jù)。可以詳見的準(zhǔn)入淘汰策略是新增一個(gè)新的元素時(shí),判斷使用該元素替換一個(gè)舊元素,是否可以提升緩存命中率。 1. Introduction LFU的局限: LFU實(shí)現(xiàn)需要維護(hù)大而復(fù)雜的元數(shù)據(jù)(頻次統(tǒng)計(jì)數(shù)據(jù)等) 大多數(shù)實(shí)際工作負(fù)載中,訪問頻率隨著時(shí)間的推移而發(fā)生根本變化(這是外賣業(yè)務(wù)不適合樸素LFU的根本原因) 針...
摘要:但是內(nèi)存空間畢竟有限,隨著我們存儲(chǔ)數(shù)據(jù)的不斷增長,要緩存的數(shù)據(jù)量越來越大,當(dāng)超過了我們的內(nèi)存大小時(shí),該怎么辦呢解決方法有兩種增加物理內(nèi)存搭建集群和緩存數(shù)據(jù)的淘汰機(jī)制。增加物理內(nèi)存簡單粗暴,價(jià)格十分昂貴,內(nèi)存的價(jià)格大約是萬元左右。redis 使用的時(shí)內(nèi)存空間來存儲(chǔ)數(shù)據(jù)的,避免業(yè)務(wù)應(yīng)用從后端數(shù)據(jù)庫中讀取數(shù)據(jù),可以提升應(yīng)用的響應(yīng)速度。但是內(nèi)存空間畢竟有限,隨著我們存儲(chǔ)數(shù)據(jù)的不斷增長,要緩存的數(shù)據(jù)量...
摘要:如果處理不得當(dāng),就會(huì)造成緩存污染問題。解決緩存污染的算法算法,英文名,字面意思就是最不經(jīng)常使用的淘汰掉算法,是通過數(shù)據(jù)被訪問的頻率來判斷一個(gè)數(shù)據(jù)的熱點(diǎn)情況。分析降低了緩存污染帶來的問題,命中率比要高。 微信公眾號(hào):IT一刻鐘大型現(xiàn)實(shí)非嚴(yán)肅主義現(xiàn)場一刻鐘與你分享優(yōu)質(zhì)技術(shù)架構(gòu)與見聞,做一個(gè)有劇情的程序員關(guān)注可第一時(shí)間了解更多精彩內(nèi)容,定期有福利相送喲。 showImg(https://s...
閱讀 2066·2021-11-22 13:52
閱讀 993·2021-11-17 09:33
閱讀 2719·2021-09-01 10:49
閱讀 2853·2019-08-30 15:53
閱讀 2665·2019-08-29 16:10
閱讀 2438·2019-08-29 11:31
閱讀 1364·2019-08-26 11:40
閱讀 1878·2019-08-26 10:59