题目大意:设计一个用于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