LRU缓存机制
LRU 緩存淘汰算法就是一種常用策略。LRU 的全稱是 Least Recently Used,也就是說我們認為最近使用過的數據應該是是「有用的」,很久都沒用過的數據應該是無用的,內存滿了就優先刪那些很久沒用過的數據。
這里用c++來實現。
知識鋪墊:
c++迭代器
(1)正向迭代器形式:容器類名::iterator? 迭代器名
(2)常量正向迭代器:容器類名::const_iterator? 迭代器名
(3)反向迭代器:容器類名::reverse_iterator? 迭代器名
?? (4) 常量反向迭代器:容器類名::const_reverse_iterator? 迭代器名
#include <iostream> #include <vector> using namespace std; int main() {vector<int> v; //v是存放int類型變量的可變長數組,開始時沒有元素for (int n = 0; n<5; ++n)v.push_back(n); //push_back成員函數在vector容器尾部添加一個元素vector<int>::iterator i; //定義正向迭代器for (i = v.begin(); i != v.end(); ++i) { //用迭代器遍歷容器cout << *i << " "; //*i 就是迭代器i指向的元素*i *= 2; //每個元素變為原來的2倍}cout << endl;//用反向迭代器遍歷容器for (vector<int>::reverse_iterator j = v.rbegin(); j != v.rend(); ++j)cout << *j << " ";return 0; }程序的輸出結果是:
0 1 2 3 4
8 6 4 2 0
第 6 行,vector 容器有多個構造函數,如果用無參構造函數初始化,則容器一開始是空的。
第 10 行,begin 成員函數返回指向容器中第一個元素的迭代器。++i 使得 i 指向容器中的下一個元素。end 成員函數返回的不是指向最后一個元素的迭代器,而是指向最后一個元素后面的位置的迭代器,因此循環的終止條件是i != v.end()。
第 16 行定義了反向迭代器用以遍歷容器。反向迭代器進行++操作后,會指向容器中的上一個元素。rbegin 成員函數返回指向容器中最后一個元素的迭代器,rend 成員函數返回指向容器中第一個元素前面的位置的迭代器,因此本循環實際上是從后往前遍歷整個數組。
如果迭代器指向了容器中最后一個元素的后面或第一個元素的前面,再通過該迭代器訪問元素,就有可能導致程序崩潰,這和訪問 NULL 或未初始化的指針指向的地方類似。
第 10 行和第 16 行,寫++i、++j相比于寫i++、j++,程序的執行速度更快。
最關鍵的地方哈希查找和鏈表的結合。
結合的原因:(1)鏈表插入和刪除比較快(2)哈希表查找比較快
方法,將哈希表的key映射到雙向鏈表的key。
class LRUCache { private:int cap;// 雙鏈表:裝著 (key, value) 元組list<pair<int, int>> cache;// 哈希表:key 映射到 (key, value) 在 cache 中的位置unordered_map<int, list<pair<int, int>>::iterator> map; public:LRUCache(int capacity) {this->cap = capacity; }int get(int key) {auto it = map.find(key);// 訪問的 key 不存在if (it == map.end()) return -1;// key 存在,把 (k, v) 換到隊頭pair<int, int> kv = *map[key];cache.erase(map[key]);cache.push_front(kv);// 更新 (key, value) 在 cache 中的位置map[key] = cache.begin();return kv.second; // value}void put(int key, int value) {/* 要先判斷 key 是否已經存在 */ auto it = map.find(key);if (it == map.end()) {/* key 不存在,判斷 cache 是否已滿 */ if (cache.size() == cap) {// cache 已滿,刪除尾部的鍵值對騰位置// cache 和 map 中的數據都要刪除auto lastPair = cache.back();int lastKey = lastPair.first;map.erase(lastKey);cache.pop_back();}// cache 沒滿,可以直接添加cache.push_front(make_pair(key, value));map[key] = cache.begin();} else {/* key 存在,更改 value 并換到隊頭 */cache.erase(map[key]);cache.push_front(make_pair(key, value));map[key] = cache.begin();}} };
作者:labuladong
鏈接:https://leetcode-cn.com/problems/lru-cache/solution/lru-ce-lue-xiang-jie-he-shi-xian-by-labuladong/
來源:力扣(LeetCode)
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
總結
- 上一篇: C语言获取某个分割符之前的内容
- 下一篇: 【OPTEE开发】从TA到安全驱动的功能