題目大意:設計一個用於LRU cache算法的數據結構。 題目鏈接。關於LRU的基本知識可參考here
分析:為了保持cache的性能,使查找,插入,刪除都有較高的性能,我們使用雙向鏈表(std::list)和哈希表(std::unordered_map)作為cache的數據結構,因為:
- 雙向鏈表插入刪除效率高(單向鏈表插入和刪除時,還要查找節點的前節點)
- 哈希表保存每個節點的地址,可以基本保證在O(1)時間內查找節點
具體實現細節:
- 越靠近鏈表頭部,表示節點上次訪問距離現在時間最短,尾部的節點表示最近訪問最少
- 查詢或者訪問節點時,如果節點存在,把該節點交換到鏈表頭部,同時更新hash表中該節點的地址
- 插入節點時,如果cache的size達到了上限,則刪除尾部節點,同時要在hash表中刪除對應的項。新節點都插入鏈表頭部。 本文地址
代碼如下:
1 struct CacheNode 2 { 3 int key; 4 int value; 5 CacheNode(int k, int v):key(k), value(v){} 6 }; 7 8 class LRUCache{ 9 public: 10 LRUCache(int capacity) { 11 size = capacity; 12 } 13 14 int get(int key) { 15 if(cacheMap.find(key) == cacheMap.end()) 16 return -1; 17 else 18 { 19 //把當前訪問的節點移到鏈表頭部,並且更新map中該節點的地址 20 cacheList.splice(cacheList.begin(), cacheList, cacheMap[key]); 21 cacheMap[key] = cacheList.begin(); 22 return cacheMap[key]->value; 23 } 24 25 } 26 27 void set(int key, int value) { 28 if(cacheMap.find(key) == cacheMap.end()) 29 { 30 if(cacheList.size() == size) 31 {//刪除鏈表尾部節點(最少訪問的節點) 32 cacheMap.erase(cacheList.back().key); 33 cacheList.pop_back(); 34 } 35 //插入新節點到鏈表頭部,並且更新map中增加該節點 36 cacheList.push_front(CacheNode(key, value)); 37 cacheMap[key] = cacheList.begin(); 38 } 39 else 40 {//更新節點的值,把當前訪問的節點移到鏈表頭部,並且更新map中該節點的地址 41 cacheMap[key]->value = value; 42 cacheList.splice(cacheList.begin(), cacheList, cacheMap[key]); 43 cacheMap[key] = cacheList.begin(); 44 } 45 46 } 47 private: 48 list<CacheNode> cacheList; 49 unordered_map<int, list<CacheNode>::iterator>cacheMap; 50 int size; 51 };
【版權聲明】轉載請注明出處:http://www.cnblogs.com/TenosDoIt/p/3417157.html