LRU缓存策略
2015-09-14 17:26
337 查看
题目:为最近最少使用(LRU)缓存策略设计一个数据结构,它应该支持以下操作:获取数据(get)和写入数据(set)。获取数据get(key):如果缓存中存在key,则获取其数据值(通常是正数),否则返回-1。写入数据set(key, value):如果key还没有在缓存中,则写入其数据值。当缓存达到上限,它应该在写入新数据之前删除最近最少使用的数据用来腾出空闲位置。
方法:为了保持cache的性能,使查找,插入,删除都有较高的性能,我们使用双向链表(std::list)和哈希表(std::unordered_map)作为cache的数据结构,因为:
双向链表插入删除效率高(单向链表插入和删除时,还要查找节点的前节点)
哈希表保存每个节点的地址,可以基本保证在O(1)时间内查找节点
具体实现细节:
越靠近链表头部,表示节点上次访问距离现在时间最短,尾部的节点表示最近访问最少
查询或者访问节点时,如果节点存在,把该节点交换到链表头部,同时更新hash表中该节点的地址
插入节点时,如果cache的size达到了上限,则删除尾部节点,同时要在hash表中删除对应的项。新节点都插入链表头部。
在下面的实现中,使用的是单链表:
方法:为了保持cache的性能,使查找,插入,删除都有较高的性能,我们使用双向链表(std::list)和哈希表(std::unordered_map)作为cache的数据结构,因为:
双向链表插入删除效率高(单向链表插入和删除时,还要查找节点的前节点)
哈希表保存每个节点的地址,可以基本保证在O(1)时间内查找节点
具体实现细节:
越靠近链表头部,表示节点上次访问距离现在时间最短,尾部的节点表示最近访问最少
查询或者访问节点时,如果节点存在,把该节点交换到链表头部,同时更新hash表中该节点的地址
插入节点时,如果cache的size达到了上限,则删除尾部节点,同时要在hash表中删除对应的项。新节点都插入链表头部。
在下面的实现中,使用的是单链表:
class KeyValue { public: int key, value; KeyValue *next; KeyValue(int key, int value) { next = NULL; this->key = key; this->value = value; } KeyValue() { this->next = NULL; this->key = 0; this->value = 0; } }; class LRUCache{ private: void moveToTail(KeyValue *prev) { if (prev->next == tail) { return; } KeyValue *node = prev->next; prev->next = node->next; if (node->next != NULL) { hash[node->next->key] = prev; } tail->next = node; node->next = NULL; hash[node->key] = tail; tail = node; } public: unordered_map<int, KeyValue *> hash; KeyValue *head, *tail; int capacity, size; LRUCache(int capacity) { this->head = new KeyValue(0, 0); this->tail = head; this->capacity = capacity; this->size = 0; hash.clear(); } int get(int key) { if (hash.find(key) == hash.end()) { return -1; } moveToTail(hash[key]); return hash[key]->next->value; } void set(int key, int value) { if (hash.find(key) != hash.end()) { hash[key]->next->value = value; moveToTail(hash[key]); } else { KeyValue *node = new KeyValue(key, value); tail->next = node; hash[key] = tail; tail = node; size++; if (size > capacity) { hash.erase(head->next->key); head->next = head->next->next; if (head->next != NULL) { hash[head->next->key] = head; } size--; } } } };
相关文章推荐
- c语言实现hashmap(转载)
- 选定虚拟主机 性能凸显优势
- 修改一行代码提升 Postgres 性能 100 倍
- Flex字符串比较 还有Flex字符串操作
- 推荐Sql server一些常见性能问题的解决方法
- Lua教程(七):数据结构详解
- ASP Cookies操作的详细介绍与实例代码
- perl数据库添加、删除、更新、查询操作例子
- Ruby中Hash的11个问题解答
- 总结的5个C#字符串操作方法分享
- SQL Server误区30日谈 第9天 数据库文件收缩不会影响性能
- 和表值函数连接引发的性能问题分析
- SQLServer 2000 升级到 SQLServer 2008 性能之需要注意的地方之一
- 解析从源码分析常见的基于Array的数据结构动态扩容机制的详解
- 数据库性能优化三:程序操作优化提升性能
- C#操作XML文件实例汇总
- C#数据结构揭秘一
- VBS中的字符串连接的性能问题
- C#中父窗口和子窗口之间控件互操作实例
- C#操作PowerPoint的方法