C++實現LRU快取——LeetCode 146
阿新 • • 發佈:2022-03-06
1.手動實現雙向連結串列
class LRUCache { public: // 雙向連結串列的資料結構 struct Node{ int key,val; Node*left,*right; Node(int _key,int _val):key(_key),val(_val),left(NULL),right(NULL){} }; Node *L,*R; // 最左邊的和最右邊的節點;第一個元素:L->right;最後一個元素:R->left unordered_map<int,Node*> map ; int n; // 當前節點數量 int size ; // 最大容量 // 雙向連結串列的基本操作 void remove(Node *p){ p->left->right = p->right; p->right->left = p->left ; } void insertAtLeft(Node *p){ p->right = L->right; p->left = L ; L->right->left = p; L->right = p; } // LRUCache的基本操作 LRUCache(int capacity) { size = capacity ; n = 0; L = new Node(-1,-1); R = new Node(-1,-1); L->right = R ; R->left = L ; } int get(int key) { if(map.count(key)==0) return -1; // 刪掉原節點 將其插入到最左邊 int val = map[key]->val; remove(map[key]); Node *newNode = new Node(key,val); map[key] = newNode ; insertAtLeft(newNode); return val; } void put(int key, int value) { // 判斷是否存在此節點 if(get(key)!=-1){ // key存在, get函式已經將key移到頭部 map[key]->val = value; // 或 L->right->val } else{ Node *newNode = new Node(key,value); if(n==size){ //滿了 map.erase(R->left->key); remove(R->left); // 從雙向連結串列刪除最右邊節點 insertAtLeft(newNode); }else{ insertAtLeft(newNode); n++ ; } map[key]=newNode; } } }; /** * Your LRUCache object will be instantiated and called as such: * LRUCache* obj = new LRUCache(capacity); * int param_1 = obj->get(key); * obj->put(key,value); */
2.使用STL容器list(省去很多麻煩...)
list的常見方法:
- begin(): 返回第一個元素的迭代器
- end(): 最後一個元素的下一個位置的迭代器
- front(): 第一個元素的引用
- back(): 最後一個元素的引用
- emplace_front(), emplace_back() : 頭部,尾部生成一個元素,比push_back效率高
- push_back(), pop_back(): 尾部插入、刪除一個元素
- splice(): 將一個 list 容器中的元素插入到另一個容器的指定位置
class LRUCache { private: int cap = 0 ; list<pair<int,int>> li; // 儲存Cache資料的 unordered_map<int,list<pair<int,int>>::iterator> mp; // 查詢Cache中是否存在此key的 public: LRUCache(int capacity) { cap = capacity ; } int get(int key) { if(mp.find(key)==mp.end()) // key不存在 return -1; li.splice(li.begin(),li,mp[key]); // li的mp[key],插入到li.begin(),這裡都是迭代器 return li.begin()->second; // return li.front().second; // 或者這麼寫 } void put(int key, int value) { if(get(key)!=-1) // key 存在 ,get函式已經將其移到頭部 li.begin()->second = value ; else{ // key不存在 if(li.size()==cap){ int delKey = li.back().first; li.pop_back(); mp.erase(delKey); } // 滿了 li.emplace_front(key,value); mp[key]=li.begin(); } } }; /** * Your LRUCache object will be instantiated and called as such: * LRUCache* obj = new LRUCache(capacity); * int param_1 = obj->get(key); * obj->put(key,value); */