版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/HQ1356466973/article/details/54581213
LRU是Least Recently Used的缩写,即最近最少使用页面置换算法,是为虚拟页式存储管理服务的,是根据页面调入内存后的使用情况进行决策了。由于无法预测各页面将来的使用情况,只能利用“最近的过去”作为“最近的将来”的近似,因此,LRU算法就是将最近最久未使用的页面予以淘汰。本博文使用双线循环链表实现LRU。
实现LRU原则:
- 越靠近链表头部,表示节点上次访问距离现在时间最短,尾部的节点表示最近访问最少;
- 查询或者访问节点时,如果节点存在,把该节点交换到链表头部;
- 插入节点时,如果cache的size达到了上限,则删除尾部节点,新节点都插入链表头部。
代码如下:
#ifndef LRULISTNODE_H_INCLUDED
#define LRULISTNODE_H_INCLUDED
#include <iostream>
using namespace std;
template <typename T,typename E>
struct CacheNode //链表中的节点
{
T key; //键
E value; //值
CacheNode(T k,E val):key(k),value(val){};
CacheNode<T,E>* pre; //指向前驱节点
CacheNode<T,E>* next; //指向后续节点
};
template <typename T,typename E>
class LRUChacheList //LRU类
{
public:
//构造函数
LRUChacheList(int sz,T key,E val):mSize(sz)
{
mHead = new CacheNode<T,E>(key,val);
mHead->next = nullptr;
mHead->pre = nullptr;
mCurrentSize = 0;
}
//虚析构函数
virtual ~LRUChacheList()
{
if (nullptr == mHead->next) //只有头结点
{
delete mHead;
}else //有多个节点
{
CacheNode<T,E>* p = mHead->next;
CacheNode<T,E>* q = nullptr;
while (p != mHead)
{
q = p;
p = p->next;
delete q;
}
delete mHead;
}
}
//设置新值
void setKey(T key,E value)
{
CacheNode<T,E>* ret=nullptr;
if (findKey(key,ret) == false) //当前cache没有对应键的值
{
if (mCurrentSize == mSize) //cache已经满 则删除链表尾部的节点
{
CacheNode<T,E>* p = mHead->pre;
CacheNode<T,E>* q = p->pre;
mHead->pre = q;
q->next = mHead;
delete p;
--mCurrentSize;
}
//新建节点 并插入到链表头部
CacheNode<T,E>* s = new CacheNode<T,E>(key,value);
++mCurrentSize;
if (mHead->next == nullptr) //第一次插入节点时
{
mHead->next = s;
s->pre = mHead;
s->next = mHead;
mHead->pre = s;
return;
}
//第二次以后插入节点
mHead->next->pre = s;
s->next = mHead->next;
mHead->next = s;
s->pre = mHead;
}else //如果找到对应的键值 则更新它的值
{
if(nullptr != ret)
{
ret->pre->next = ret->next;
ret->next->pre = ret->pre;
mHead->next->pre = ret;
ret->next = mHead->next;
mHead->next = ret;
ret->pre = mHead;
ret->value = value;
}
}
}
//获取对应键的值
bool getValue(T& key,E& val)
{
CacheNode<T,E>* ret=nullptr;
if(true == findKey(key,ret)) //找到
{
if(nullptr != ret)
{
CacheNode<T,E>* tmp;
ret->pre->next = ret->next;
ret->next->pre = ret->pre;
mHead->next->pre = ret;
ret->next = mHead->next;
mHead->next = ret;
ret->pre = mHead;
val = ret->value;
}
return true;
}
//没找到
return false;
}
//打印cache中的节点的值
void print()
{
if (nullptr == mHead)
return ;
CacheNode<T,E>* p = mHead->next;
while (p != mHead)
{
cout << p->value << " ";
p = p->next;
}
cout << endl;
}
//重载<<
ostream& operator<< (CacheNode<T,E>& s)
{
return cout<<s.value;
}
protected:
//找cache中是否存在对应的键 若存在将节点通过参数s返回 函数返回true
bool findKey(T key,CacheNode<T,E>*& s)
{
if (nullptr == mHead->next)
return false;
CacheNode<T,E>* p = mHead->next;
while (p != mHead)
{
if (key == p->key)
{
s = p;
return true;
}
p = p->next;
}
return false;
}
//找值 并通过参数s返回改节点
bool findValue(E val,CacheNode<T,E>*& s)
{
if (mHead->next == nullptr)
return false;
CacheNode<T,E>* p = mHead->next;
while (p != mHead)
{
if (p->value == val)
{
s = p;
return true;
}
p = p->next;
}
return false;
}
private:
int mSize; //cache的总容量
int mCurrentSize; //cache的当前容量
CacheNode<T,E>* mHead; //链表的头结点 用于管理链表
};
#endif // LRULISTNODE_H_INCLUDED
请各位大神批评指正!蟹蟹!!!