文章目录
- 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;
};                










