0
点赞
收藏
分享

微信扫一扫

2.2.14LRU最近最少使用页面置换缓存器


文章目录

  • ​​1.题目​​
  • ​​2.代码​​

1.题目

  • ​​题目要求​​
  • 思路:
    (1)为了使得查找、插入和删除都有较高的性能,使用一个双向链表std::list和哈希表std::unordered_map;
    哈希表保存每个节点的地址,基本可以保证O(1)的时间
    (2)较于单向链表,双向链表插入和删除效率高
    (3)越靠近链表头部,表示节点上次访问距离现在时间越短,尾部的节点说明距离现在时间最长
    (4)访问节点时,若节点存在,则把该节点交换到链表头部,同时更新hash表中该节点的地址
    (5)插入节点时,若cache的size达到了上限capacity,则删除尾部节点,同时要在hash表中删除对应的项;
    (6)新节点插入链表头部
    (7)这里我们使用 C++ STL 中的函数 splice,专门移动链表中的一个或若干个结点到某个特定的位置,这里我们就只移动 key 对应的迭代器到列表的开头
  • eg:

LRUCache cache = new LRUCache( 2 /* capacity */ );

cache.put(1, 1);
cache.put(2, 2);
cache.get(1); // returns 1
cache.put(3, 3); // evicts key 2
cache.get(2); // returns -1 (not found)
cache.put(4, 4); // evicts key 1
cache.get(1); // returns -1 (not found)
cache.get(3); // returns 3
cache.get(4); // returns 4

2.代码

class LRUCache{
public:
LRUCache(int cap)
{
this->cap=cap;
}

int get(int key)
{
if (hashmap_list.find(key) == hashmap_list.end())
return -1;
把当前访问的节点移动到链表头部,且更新map中该节点的地址
Cachelist.splice(Cachelist.begin(),Cachelist,hashmap_list[key]);
hashmap_list[key]=Cachelist.begin();
return hashmap_list[key]->value;
}
void put(int key,int value)
{
if (hashmap_list.find(key) == hashmap_list.end())
{
删除链表尾部的节点
if (Cachelist.capacity() == cap)
{
Cachelist.pop_back(Cachelist.back());
hashmap_list.erase(Cachelist.back()->key);
}
插入新节点到链表头部,且在map中增加该节点
Cachelist.push_front(CacheNode(key,value));
hashmap_list[key]=Cachelist.begin();
}
else
{
更新节点的值,把当前访问的节点移动到链表头部,且更新map中该节点的地址
hashmap_list[key]->value=vaule;
Cachelist.splice(Cachelist.begin(),Cachelist,hashmap_list[key]);
hashmap_list[key]=Cachelist.begin();
}
}
private:
struct CacheNode{
int key;
int value;
CacheNode(int key, int value) : key(key), value(value) {}
}CacheNode;
list<CacheNode> Cachelist;
unordered_map<int,list<CacheNode>::iterator> hashmap_list;
int cap;
};


举报

相关推荐

0 条评论