快取策略之LRU和LFU

2021-09-11 14:49:14 字數 2877 閱讀 4117

快取,就是把資料儲存在本地,簡單實用key-value做乙個對映就好了。但為什麼還要快取策略,因為快取的大小需要限制,否則儲存的東西只增不減,時間一長就有很多記憶體浪費。

因為資源總是有限,所以優化,因為優化所以複雜

這個是least recently used的縮寫,即最近最少使用。它的邏輯很簡單:一串資料,a->b->c->d->....->head,新的資料來就壓到頭部,哪個資料用到了也拉到頭部,然後記憶體到了限制額,就丟掉最後的那個。

也就是最近被用到得越多,不管是存還是取,就更能活下來

class lrucache ;

};//頭和尾各設了乙個哨兵指標,方便處理,不用做頭尾的判空

cachenode *head = new cachenode();

cachenode *tail = new cachenode();

int capacity;

int size = 0;

unordered_mapstore;

/** 在頭部插入乙個資料 */

inline void inserthead(cachenode *node)

inline void unbind(cachenode *node)

/** 把節點拉到最前面 */

inline void forword(cachenode *node)

unbind(node);

inserthead(node);

}/** 扔掉最後乙個 */

inline void droptail

()

friend ostream& operator<<(ostream& os, lrucache &cache)

return os;

}public:

lrucache(int capacity)

int get(int key) else

}void set(int key, int value)

auto node = new cachenode(key, value);

store[key] = node;

inserthead(node);

size++;

}else

}};複製**

這是我用雙鏈表實現的乙個lru演算法,快取有兩個關係維護資料:乙個是key-value之間的對映關係,用map字典之類的;另乙個是要維持資料的先後關係,這個先後關係決定了哪些資料會被丟棄,就要類似陣列子類的結構,可以直接使用系統庫提供的陣列,也可以自己用雙鏈表來做。

如果要讓這個演算法更使用,還需要:

這個是least frequently used的縮寫,表示最近最不常用。意思上跟lru好像是一樣的,最大的區別是:lru是使用一次就被提到最前面,而lfu是用一次標記一下,然後按照這個使用次數來排序。換言之,lfu有更精確的統計。

同樣是乙個資料佇列,模擬一下操作過程:

下面是乙個演算法實現,為了提高效率,使用分層結構:把time相同的節點放在乙個佇列裡,然後用乙個大佇列把這些佇列串起來。因為在資料往前提都是直接越過了time相同的那一層,去到上一層的第乙個。如果time相同的資料過多,時間消耗倍增。

class lfucache ;

bool operator==(const keynode &other) const

};struct rownode;

rownode *next = nullptr;

rownode *pre = nullptr;

keynode *keyhead = nullptr;

keynode *keytail = nullptr;

};rownode *lastrow = nullptr;

int capacity = 0;

int storedsize = 0;

unordered_mapstore;

void bringforward(keynode *node)

removekeynode(node);

if (node->row->keyhead == nullptr && node->row == lastrow)

insertnodetofront(node, prerow);

}inline void insertnodetofront(keynode *node, rownode *row)

node->next = row->keyhead;

node->pre = nullptr;

if (row->keyhead) else

row->keyhead = node;

node->row = row;

}inline void removekeynode(keynode *node)else

}else

if (node->row->keytail == node)

}public:

lfucache(int capacity)

void set(int key, int value)

keynode *newnode = nullptr;

if (storedsize == capacity)

}else

if (lastrow->time != 1)

store[key] = newnode;

insertnodetofront(newnode, lastrow);

}int get(int key)

keynode *find = store[key];

bringforward(find);

return find->value;

}};複製**

最後這裡是我的演算法練習庫

快取淘汰演算法 LRU 和 LFU

lru least recently used 即最近最少使用演算法,是一種常見的 cache 頁面置換演算法,有利於提高 cache 命中率。lru 的演算法思想 對於每個頁面,記錄該頁面自上一次被訪問以來所經歷的時間 t 當淘汰乙個頁面時,應選擇所有頁面中其 t 值最大的頁面,即記憶體中最近一段...

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 ...

C 實現快取演算法LRU和LFU

運用你所掌握的資料結構,設計和實現乙個lru 最近最少使用 快取機制 它應該支援以下操作 獲取資料get和 寫入資料put。獲取資料get key 如果金鑰 key 存在於快取中,則獲取金鑰的值 總是正數 否則返回 1。寫入資料put key,value 如果金鑰不存在,則寫入其資料值。當快取容量達...