LRU算法: 最近久未使用,在内存有限的情况下需要淘汰久未使用的数据
常用于页面置换算法,找到久未使用的页面进行淘汰,空出内存给新数据加入
算法思想:利用list和unordere_map实现
双向链表用于存储KEY和VALUE值
哈希表则存储KEY和KEY在list中的位置
定义一个Node类型<K,Y>存储数据,再重命名一个指向list类型的迭代器iter
typedef typename std::list::iterator iter;作为哈希表的value值 同时cap_作为LRUcache中可存储的最大数据量 超过这个值就删除久未使用的数据
get方法:传入K值,如果存在返回-1,未找到;若存在的话就返回他的VALUE值,并且用it指向这个数据,用list中的splice函数将其放在list开头。
set方法: 传入key和value值 , 如果key存在,设置其value并且将其放到list的头部 否则:
如果list.size()已满 ,删除ump和list中最后一个位置的数据,再在list头部插入数据,同时ump中插入key让ump的value值为list.begin()
#include<iostream>
#include<vector>
#include<list>
#include<string>
#include<unordered_map>
#include<algorithm>
using namespace std;
//LRU缓存 久未使用的数据放在最后
template<class KTYPE,class VALUE>
class LRUCache
{
private:
typedef typename std::pair<KTYPE,VALUE> Node;
typedef typename std::list<Node>::iterator iter;
private:
int cap_;//指定可以存的KEY的容量
list<Node>mylist;//key 和 value
unordered_map<KTYPE,iter>ump;//key值对应保存的是key在list中所在的位置
public:
LRUCache(int cap):cap_(cap){}
VALUE Get(KTYPE key)
{
if(ump.count(key) <= 0)
{
return -1;
}
else
{
iter it = ump[key];
VALUE value = it->second;
}
mylist.splice(mylist.begin(),mylist,it);//将it位置元素放到开头位置
return value;
}
void Set(KTYPE key,VALUE value)
{
if(ump.count(key) > 0)//若已存在,对其进行设置调整
{
iter it = ump[key];
it->second = value;
mylist.splice(mylist.begin(),mylist,it);
}
else if(ump.count(key) == 0)
{
if(mylist.size() == cap_)//list已满
{
ump.erase(mylist.back().first);
mylist.pop_back();
}
mylist.push_front(make_pair(key,value));
ump[key] = mylist.begin();
}
}
void show()
{
for(auto it = mylist.begin();it != mylist.end();++it)
{
cout<<it->first<<":"<<it->second<<endl;
}
}
};
int main()
{
LRUCache<string,int>lru(5);
lru.Set("aaa",1);
lru.Set("aa",5);
lru.Set("aaah",6);
lru.Set("aaag",2);
lru.show();
}