LRU算法 C++实现

整体思路:一个循环队列同时使用节点的计数来标记节点的新旧信息,如果有新节点加入时,就把最旧的节点清空,将新节点加入。具体画一下图比较好理解。

#include <iostream>
#include <vector>
#include <map>
#include <queue>
using namespace std;

static const int LEN = 5;

int main(){
    vector<int> vires(LEN,-1);//保存结果
    vector<int> vi(LEN,-1);//循环数组
    deque<int> empty;//上层为空的结点在结果数组中的下标
    map<int,int> mii,miires;//mii记录vi里的点的计数,miires记录的是点在vires里的下标
    for(int i=0;i<LEN;++i){
        empty.push_back(i);
    }
    int itp,ict=0;
    while(cin>>itp){
        if(mii.count(vi[ict])){//如果存在,删除循环队列中原来的数
            --mii[vi[ict]];
            if(mii[vi[ict]]==0){
                empty.push_back(miires[vi[ict]]);
                mii.erase(mii.find(vi[ict]));
            }
        }
        vi[ict]=itp;//给循环队列中当前位置赋新值
        mii[itp]+=1;
        ++ict;
        ict%=LEN;
        if(miires.count(itp)){
            auto atp = empty.begin();
            for(;atp!=empty.end();++atp){
                if(*atp==miires[itp]) break;
            }
            if(*atp == miires[itp]) empty.erase(atp);
        }
        else{//真实存储中没有这个数,需要存进去
            if(vires[empty.front()]!=-1) miires.erase(miires.find(vires[empty.front()]));
            vires[empty.front()]=itp;
            miires[itp]=empty.front();
            empty.pop_front();
            //print
            for(auto ieh:vires){
                if(ieh!=-1)
                    cout<<ieh<<" ";
            }
            cout<<endl;
        }
    }
    return 0;
}
//1 2 3 4 5 6 5 4 3 1 7 9 1 2 3 5 6 9 4 2 1

结果如下:

1 2 3 4 5 6 5 4 3 1 7 9 1 2 3 5 6 9 4 2 1
1 
1 2 
1 2 3 
1 2 3 4 
1 2 3 4 5 
6 2 3 4 5 
6 1 3 4 5 
7 1 3 4 5 
7 1 3 4 9 
7 1 3 2 9 
5 1 3 2 9 
5 1 3 2 6 
5 9 3 2 6 
5 9 3 4 6 
5 9 2 4 6 
1 9 2 4 6 

这个实现中有些地方需要在数组中查找元素,效率差就差在这里,如果需要时间复杂度为O(1)的插入与删除,还是得用hashMap+双向链表。



猜你喜欢

转载自blog.csdn.net/o1101574955/article/details/77763482