實現一個 LRUCache
類:使得 put 和 get 操做都達到 O(1)node
哈希表 + 雙向隊列緩存
雙向隊列 中存儲 緩存(頁面)信息,使用哈希表能夠實現O(1) 找到 緩存的位置,使用雙向隊列能夠 實現O(1)函數
時間的從頭部插入(更新剛用過的頁爲最新狀態)和從尾部刪除(淘汰最近最久未使用的頁)。spa
直接上代碼:code
1 struct Node 2 { 3 int key; 4 int value; 5 Node(int k,int v):key(k),value(v){} 6 }; 7 class LRUCache { 8 public: 9 LRUCache(int capacity):buff_size(capacity) {} 10 11 int get(int key) 12 { 13 // get 操做 缺頁,直接返回 -1 14 if(hash_table.find(key) == hash_table.end()) 15 { 16 return -1; 17 } 18 // 藉助哈希表O(1)實現 get操做 19 int value = hash_table[key]->value; 20 // 刷新當前頁爲最新 21 put( key, value); 22 // Cache.splice(Cache.begin(), Cache,hash_table[key]); 23 return value; 24 } 25 26 void put(int key, int value) 27 { 28 //未命中且Cache已滿,淘汰最近最久未使用頁, 29 if(hash_table.find(key) == hash_table.end() && Cache.size() == buff_size) 30 { 31 int key = Cache.back().key; 32 Cache.pop_back();//淘汰最近最久未使用頁 33 hash_table.erase(key);//同時刪除hash表中對應的記錄 34 } 35 //命中 刪除掉Cache中目標記錄,此時hash表可不更新,由於該頁立刻就要再插入Cache 36 if(hash_table.find(key) != hash_table.end()) 37 { 38 Cache.erase(hash_table[key]); 39 } 40 //將當前頁面從新插入到Cache 頭部,同時更新hash表記錄當前頁最新位置 41 Node node(key,value); 42 Cache.push_front(node); 43 hash_table[key] = Cache.begin(); 44 return; 45 } 46 private: 47 int buff_size; 48 list<Node> Cache; 49 unordered_map<int,list<Node>::iterator> hash_table; 50 }; 51 52 /** 53 * Your LRUCache object will be instantiated and called as such: 54 * LRUCache* obj = new LRUCache(capacity); 55 * int param_1 = obj->get(key); 56 * obj->put(key,value); 57 */
使用 list 的splice 函數 ,能夠提升效率 ,代碼以下:blog
1 struct Node 2 { 3 int key; 4 int value; 5 Node(int k,int v):key(k),value(v){} 6 }; 7 class LRUCache { 8 public: 9 LRUCache(int capacity):buff_size(capacity) {} 10 11 int get(int key) 12 { 13 // get 操做 缺頁,直接返回 -1 14 if(hash_table.find(key) == hash_table.end()) 15 { 16 return -1; 17 } 18 // 藉助哈希表O(1)實現 get操做 19 int value = hash_table[key]->value; 20 // 刷新當前頁爲最新 21 //put( key, value); 22 Cache.splice(Cache.begin(), Cache,hash_table[key]); 23 return value; 24 } 25 26 void put(int key, int value) 27 { 28 //命中 刪除掉Cache中目標記錄,此時hash表可不更新,由於該頁立刻就要再插入Cache 29 if(hash_table.find(key) != hash_table.end()) 30 { 31 hash_table[key]->value = value; 32 return Cache.splice(Cache.begin(), Cache,hash_table[key]); 33 } 34 //將當前頁面從新插入到Cache 頭部,同時更新hash表記錄當前頁最新位置 35 Node node(key,value); 36 Cache.push_front(node); 37 hash_table[key] = Cache.begin(); 38 if(Cache.size() > buff_size) 39 { 40 hash_table.erase(Cache.back().key); 41 Cache.pop_back(); 42 } 43 return; 44 } 45 private: 46 int buff_size; 47 list<Node> Cache; 48 unordered_map<int,list<Node>::iterator> hash_table; 49 }; 50 51 /** 52 * Your LRUCache object will be instantiated and called as such: 53 * LRUCache* obj = new LRUCache(capacity); 54 * int param_1 = obj->get(key); 55 * obj->put(key,value); 56 */