lintcode LRU缓存策略
来源:互联网 发布:查看淘宝店铺在线人数 编辑:程序博客网 时间:2024/04/30 08:49
LRU缓存策略
为最近最少使用(LRU)缓存策略设计一个数据结构,它应该支持以下操作:获取数据(get)和写入数据(set)。
获取数据get(key):如果缓存中存在key,则获取其数据值(通常是正数),否则返回-1。
写入数据set(key, value):如果key还没有在缓存中,则写入其数据值。当缓存达到上限,它应该在写入新数据之前删除最近最少使用的数据用来腾出空闲位置。
样例
标签
相关题目
分析:为了保持cache的性能,使查找,插入,删除都有较高的性能,我们使用双向链表(std::list)和哈希表(std::unordered_map)作为cache的数据结构,因为:
- 双向链表插入删除效率高(单向链表插入和删除时,还要查找节点的前节点)
- 哈希表保存每个节点的地址,可以基本保证在O(1)时间内查找节点
具体实现细节:
- 越靠近链表头部,表示节点上次访问距离现在时间最短,尾部的节点表示最近访问最少
- 查询或者访问节点时,如果节点存在,把该节点交换到链表头部,同时更新hash表中该节点的地址
- 插入节点时,如果cache的size达到了上限,则删除尾部节点,同时要在hash表中删除对应的项。新节点都插入链表头部。
方法一:
class LRUCache{public: // @param capacity, an integer LRUCache(int capacity) { // write your code here cap=capacity; } // @return an integer int get(int key) { // write your code here if(m.find(key)==m.end()) return -1; else l.splice(l.begin(), l, m.find(key)->second);//将此元素在双链表中位置挪到顶部 return m.find(key)->second->second; } // @param key, an integer // @param value, an integer // @return nothing void set(int key, int value) { // write your code here auto it = m.find(key); if (it != m.end()) l.erase(it->second);//如果存在则删掉当前位置 l.push_front(make_pair(key, value));//在顶部添加 m[key] = l.begin();//更新哈希表中此元素在链表中的位置 if (m.size() > cap) {//缓存达到上限 int k = l.rbegin()->first;//获得最后元素的key l.pop_back(); m.erase(k); } }private: int cap;//容器容量 list<pair<int,int>> l;//用双链表表示这个数据结构,pair两个分别表示key 和value unordered_map<int,list<pair<int,int>>::iterator> m;//用哈希表辅助以便在O(1)时间找到目标项 };方法二:
struct CacheNode{ int key; int value; CacheNode(int k, int v):key(k), value(v){}};class LRUCache{public: LRUCache(int capacity) { size = capacity; } int get(int key) { if(cacheMap.find(key) == cacheMap.end()) return -1; else { //把当前访问的节点移到链表头部,并且更新map中该节点的地址 cacheList.splice(cacheList.begin(), cacheList, cacheMap[key]); cacheMap[key] = cacheList.begin(); return cacheMap[key]->value; } } void set(int key, int value) { if(cacheMap.find(key) == cacheMap.end()) { if(cacheList.size() == size) {//删除链表尾部节点(最少访问的节点) cacheMap.erase(cacheList.back().key); cacheList.pop_back(); } //插入新节点到链表头部,并且更新map中增加该节点 cacheList.push_front(CacheNode(key, value)); cacheMap[key] = cacheList.begin(); } else {//更新节点的值,把当前访问的节点移到链表头部,并且更新map中该节点的地址 cacheMap[key]->value = value; cacheList.splice(cacheList.begin(), cacheList, cacheMap[key]); cacheMap[key] = cacheList.begin(); } }private: list<CacheNode> cacheList; unordered_map<int, list<CacheNode>::iterator>cacheMap; int size;};方法三:自己实现一个双向链表
struct Node { Node(int _key,int _value){key = _key;value = _value;pre = next = NULL;} int key; int value; Node*pre; Node*next; }; class LRUCache{ public: // @param capacity, an integer LRUCache(int capacity) { // write your code here this->capacity = capacity; size = 0; head = NULL; tail = NULL; } // @return an integer int get(int key) { // write your code here if(m.find(key)==m.end()) { return -1; } else { Node* n = m[key]; int ret = n->value; if(head!=n) { if(n==tail) tail = tail->pre; Node*pre = n->pre; if(n->next!=NULL) n->next->pre = pre; pre->next = n->next; n->next = head; head->pre = n; head = n; } return ret; } } // @param key, an integer // @param value, an integer // @return nothing void set(int key, int value) { // write your code here if(head==NULL) { head = new Node(key,value); tail = head; size++; m[key] = head; return; } if(m.find(key)==m.end()) { Node*n = new Node(key,value); n->next = head; head->pre = n; head = n; m[key] = n; size++; } else { Node*n = m[key]; if(head!=n) { if(n==tail) tail = tail->pre; Node*pre = n->pre; pre->next = n->next; if(n->next!=NULL) n->next->pre = pre; n->next = head; head->pre = n; head = n; //m[key] = n; n本身的地址并不变,不需要重新记录 } head->value = value; //这个一定需要,因为set可能会相同的KEY 而value不同 } if(size>capacity) { Node*todel = tail; int keyToDel = todel->key; tail = tail->pre; tail->next = NULL; delete todel; m.erase(m.find(keyToDel)); size--; } } private: int capacity; int size; Node*head; Node*tail; unordered_map<int,Node*> m; };参考资料:
http://www.cnblogs.com/grandyang/p/4587511.html
http://blog.csdn.net/wangyuquanliuli/article/details/47357805
http://www.cnblogs.com/TenosDoIt/p/3417157.html
阅读全文
0 0
- LintCode-LRU缓存策略
- lintcode,LRU缓存策略
- LRU缓存策略-LintCode
- lintcode LRU缓存策略
- leetcode-lintcode-LRU缓存
- LRU 缓存策略
- LRU 缓存策略
- LRU缓存策略
- LRU缓存策略
- LRU缓存策略
- LRU缓存策略设计
- LRU缓存策略设计
- LRU缓存策略
- 【链表】实现LRU缓存策略LRU Cache
- 缓存失效策略(fifo lru lfu)
- LRU策略
- 利用LinkedHashMap简单实现基于LRU策略的缓存
- 简单LRU算法实现缓存大小的限制策略
- 非父子组件的数据传递
- css html的三列弹性布局
- 1.计算机硬件组成
- 数据结构-线段树详解(含java源代码)
- HashMap基础
- lintcode LRU缓存策略
- Windows Python环境变量配置
- 如何进行网页优化?
- 反射机制(一)
- 使用TinyXML读写xml文件
- 排序列表转换为二分查找树-LintCode
- Spring Boot与Spring Security
- Spring Boot(Web)初探三( 数据访问)
- 关于改变