LRU的实现(使用list)

首先是LRU的定义,LRU表示最近最少使用,如果数据最近被访问过,那么将来被访问的几率也更高。

所以逻辑应该是每次都要将新被访问的页放到列表头部,如果超过了list长度限制,就将列表尾部的元素踢出去。

 

主要结构,STL中的双向链表结构list。

主要操作有get,表示访问key对应的value,此时要查询双链表,找到key对应value,再将其从list中删除,插入到list的头部。

     set,  表示设置对应的key值为value,此时先找到key对应的元素,将其从list中删除,再插入到list的头部。

这里设置了两个辅助函数remove和setHead,分别负责删除元素和将元素加入到list头部。

 

代码实现如下:

复制代码
#include <iostream>
#include <list>
#include <iterator>
#include <algorithm>

using namespace std;

class LRUNode
{
    public:
        int key,value;
        LRUNode(int _key,int _value):key(_key),value(_value)
        {
        }
        bool operator==(LRUNode * p)
        {
            return key==p->key;
        }
};

class LRU
{
    public:
        int get(int key);
        void set(int key,int val);
        LRU(int _cap):cap(_cap)
        {
        }
        int cap;//代表存放的最大页数
        void remove(int key);
        void setHead(int key,int val);
        void printLis();
        list<LRUNode *> lis;
};

void LRU::printLis()
{
    list<LRUNode *>::iterator it;
    for(it=lis.begin();it!=lis.end();it++)
    {
        cout<<(*it)->key<<" "<<(*it)->value<<endl;
    }
    cout<<endl;
}

void LRU::remove(int key)
{
    LRUNode * searchNode=new LRUNode(key,0);
    list<LRUNode *>::iterator it=find(lis.begin(),lis.end(),searchNode);
    if(it!=lis.end())
    {
        lis.remove(*it);
    }
}

void LRU::setHead(int key,int val)
{
    lis.push_front(new LRUNode(key,val));
}

int LRU::get(int key)
{
    LRUNode * searchNode=new LRUNode(key,0);
    list<LRUNode *>::iterator it=find(lis.begin(),lis.end(),searchNode);
    if(it!=lis.end())
    {
        remove((*it)->key);
        setHead((*it)->key,(*it)->value);
        return (*it)->value;
    }
    return -1;//表示没有找到
}

void LRU::set(int key,int value)
{
    if(lis.size()>=cap)
    {
        lis.pop_back();
    }
    LRUNode * searchNode=new LRUNode(key,0);
    list<LRUNode *>::iterator it=find(lis.begin(),lis.end(),searchNode);
    if(it!=lis.end())
    {
        remove(key);
        setHead(key,value);
    }
    else
    {
        setHead(key,value);
    }
}



int main()
{
    LRU * lru=new LRU(5);
    lru->set(1,1);
    lru->printLis();
    lru->set(2,2);
    lru->printLis();
    lru->set(3,3);
    lru->printLis();
    lru->set(4,4);
    lru->printLis();
    lru->set(5,5);
    lru->printLis();
    lru->set(6,6);
    lru->printLis();
    lru->set(7,7);
    lru->printLis();
    return 0;
}
复制代码

运行结果:

复制代码
1 1

2 2
1 1

3 3
2 2
1 1

4 4
3 3
2 2
1 1

5 5
4 4
3 3
2 2
1 1

6 6
5 5
4 4
3 3
2 2

7 7
6 6
5 5
4 4
3 3
复制代码

 

posted @   张杨  阅读(1639)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示