# [Leetcode] LRU Cache. 哈希表+双向链表之实现

## 题目

Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get and set.

get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.
set(key, value) - Set or insert the value if the key is not already present. When the cache reached its capacity, it should invalidate the least recently used item before inserting a new item.

## 思路

get()相当于set()即是。一次读或写意味着对缓存块使用了一次，该缓存的优先级就提高。

## 实现

• std::list，相当于双向链表。splice()push_front()pop_back()的复杂度为O(1)$O(1)$
• std::unordered_map，相当于哈希表。find()insert()erase()的复杂度为O(1)$O(1)$（单个element）。

1. 由于这里用了std::list，所以就不能用指针指向list中的element，要用iterator。值得注意的是，std::list的iterator是不会因为插入删除而改变所指向的element的，而std::vector的iterator是会改变所指向的element的（例如erase了之后）。

unordered_map<int, list<T>::iterator> cacheMap;
2. std::list中，element的移动可以用splice()来实现：

std::list<int> list = {1,2,3};
auto it = list.begin();
it = std::next(it); //it指向第二个element，2
if (it != list.begin())
{
// 将list.begin()置于it之后
list.splice(list.begin(), list, it, std::next(it)); // 2,1,3
}

## My Solution

/*
* LRUCache
*
* Using double linked list (stl list) and hash map(stl unordered_map)
*/

#include <iostream>
#include <unordered_map>
#include <memory>
#include <list>

using namespace std;

struct KeyVal
{
int key;
int value;
};

class LRUCache{
private:
int capacity;           // cache capacity
list<KeyVal> cache;     // cache, implement in Double-Linked-List

public:
LRUCache(int capacity):
capacity(capacity)
{ }

int get(int key) {
auto it = cacheMap.find(key);
// Find by key
if (it != cacheMap.end()) {
//Find it! Get the value.
auto kv = it->second;
// Move to front
if (kv != cache.begin())
cache.splice(cache.begin(), cache, kv, next(kv));

return kv->value;
}

return -1;
}

void set(int key, int value) {
auto it = cacheMap.find(key);
// Find by key
if (it != cacheMap.end() ){
// find and set new value
auto kv = it->second;
kv->value = value;
// move front
if (kv != cache.begin())
cache.splice(cache.begin(), cache, kv, next(kv));
}
else {
if (cacheMap.size() < capacity) {
KeyVal newKv = {key, value};
// set in cache
cache.push_front(newKv);
cacheMap.insert(make_pair(key, cache.begin()));
}else {
// Capacity is not enough
// Delete the least used value
int oldKey = cache.back().key;
cache.pop_back();
cacheMap.erase(oldKey);

KeyVal newKv = {key, value};
cache.push_front(newKv);
cacheMap.insert(make_pair(key, cache.begin()));
}
}
}
};

• 广告
• 抄袭
• 版权
• 政治
• 色情
• 无意义
• 其他

120