1、题目描述
设计LRU缓存结构,该结构在构造时确定大小,假设大小为K,并有如下两个功能
- set(key, value):将记录(key, value)插入该结构
- get(key):返回key对应的value值
要求:
- 1、set和get方法的时间复杂度为O(1)
- 2、某个key的set或get操作一旦发生,认为这个key的记录成了最常使用的。
- 3、当缓存的大小超过K时,移除最不经常使用的记录,即set或get最久远的。
2、代码实现
使用STL中的map和list可以实现一个LRU缓存,定义结构体为:
struct LruCache
{
/* LRU的容量大小 */
unsigned int capacity = 3;
/* content中保存(key,<key-pointer, value>)的键值对 */
map<string, pair<list<string>::iterator, string> > content;
/* list中保存键值key */
list<string> keyList;
};
具体实现如下:
#include <iostream>
#include <fstream>
#include <unordered_map>
#include <map>
#include <vector>
#include <list>
#include <bitset>
#include <stack>
#include <queue>
#include <string>
#include <stdlib.h>
#include <algorithm>
#include <limits>
using namespace std;
LruCache lruCache;
/* 设置某个键值对的值 */
void Set(string key, string value)
{
/* 如果map中有这个元素,则更新字典和链表 */
if (lruCache.content.find(key) != lruCache.content.end())
{
list<string>::iterator temp = lruCache.content[key].first;
if (temp == lruCache.keyList.begin()) // 如果是头节点,直接更新
{
lruCache.content[key].second = value;
return;
}
lruCache.keyList.erase(temp);
lruCache.keyList.push_front(key); // 插入更新的元素
lruCache.content[key].first = lruCache.keyList.begin(); // 更新字典
}
else // map中没有这个元素则需要插入
{
lruCache.keyList.push_front(key); // 更新链表
lruCache.content[key] = std::make_pair(lruCache.keyList.begin(), value); // 更新字典
if (lruCache.content.size() > lruCache.capacity) // 超出容量大小需要删除最后一个key
{
string lastKey = lruCache.keyList.back();
lruCache.keyList.pop_back(); // 删除最后一个元素
lruCache.content.erase(lastKey); // 删除map中的pair
}
}
}
/* 获取某个键对应的值 */
string Get(string key)
{
/* 如果map中没有这个元素,直接返回空 */
if (lruCache.content.find(key) == lruCache.content.end())
{
return "-1";
}
else
{
list<string>::iterator temp = lruCache.content[key].first;
/* 如果是头节点,直接返回 */
if (temp == lruCache.keyList.begin())
{
return lruCache.content[key].second;
}
/* 不是头节点则要进行更新 */
lruCache.keyList.erase(temp); // 更新键值链表
lruCache.keyList.push_front(key);
lruCache.content[key].first = lruCache.keyList.begin(); // 更新字典map
return lruCache.content[key].second;
}
}
int main()
{
Set("1", "1");
Set("2", "2");
Set("3", "2");
std::cout << Get("1") << std::endl;
Set("4", "4");
std::cout << Get("2") << std::endl;
}