C ++はLRUキャッシュ除去メカニズムを実装します

キャッシングの概要

ユーザーアクセスを高速化するには、キャッシュアルゴリズムを理解する必要があります。一般的なキャッシュアルゴリズムは次のとおりです。

  • LRU :(最近使用されていない):最近使用されることはめったになく、最初に削除されることはありません。
  • LFU(使用頻度が最も低い):使用頻度が最も低く、使用頻度が最も低いものが最初に削除されます。
  • FIFO(先入れ先出し):先入れ先出し、先入れ先出しバッファが最初に削除されます。
    今日は主にLRUアルゴリズムを学びました。

LRUの概要

LRUとは、キャッシュがいっぱいになると、新しいプログラムが追加されると、キャッシュ内で最も長くアクセスされていないプログラムがキャッシュから消去され、新しいプログラムがキャッシュ内の最初の場所に追加されることを意味します。 。このプログラムは現在最も頻繁にアクセスされるプログラムです。

より一般的な例を挙げてください。最初に、現在バックグラウンドで実行されているWeChatを開き、次にQQとWeiboを開きます。
このとき、バックグラウンドで表示されるソフトウェアの順序は、1、Weibo 2、QQ 3、WeChatです。
この携帯電話はバックグラウンドで3つのプログラムしか実行できないと仮定すると、NetEase Cloud Musicをオンにすると、バックグラウンドで自動的にWeChatが閉じられ、NetEaseCloudが最初に配置されます。
現時点でのバックグラウンドソフトウェアの順序は、1、NetEase Cloud 2、QQ 3、WeChatです。

実現原理

要件分析:
1。実装する必要のあるデータ構造は順序付けられています==>リンクリスト
2.高速検索が必要です==>ハッシュテーブル

したがって、これら2つの利点を組み合わせて、2つの構造を一緒に使用する必要があります。
デザインの構造は次のとおりです。

/*
 *双链表结点
 */ 
struct node{
    
    
    int val,key;
    node *prev,*next;
    node():prev(NULL),next(NULL){
    
    }
    node(int k,int v):key(k),val(v),prev(NULL),next(NULL){
    
    }
    
    //重载 == 号
    bool operator == (const node &p) const{
    
    
        return val==p.val&&key==p.key;
    }
 };

/*
 *双链表
 */ 
 class DoubleList{
    
    
     
     public:
        node *first;
        node *end;
        int n;

        DoubleList();
        void addFirst(node*);//在第一个位置插入新元素
        void remove(node*);//移除一个一定存在的节点
        int removeLast();//移除最后一个节点
        int size();
 };

上記の構造は、二重リンクリストを完成させるためのものです。二重リンクリストの構造は、挿入および削除時に非常に効率的です。
次に、クエリの効率を向上させるために、unordered_mapSTLテンプレートがここで使用されます。これは順序付けされていないマップと同等ですが、クエリの効率は安定しており、マップよりも高くなっています。詳細については、STL:unordered_mapを参照してください。

構築されたキャッシュ構造は次のとおりです。

class LRUCache{
    
    
    private:
        unordered_map<int,node> map;
        DoubleList *lru;    
        int maxSize;

    public:
        LRUCache(){
    
    };
        LRUCache(int ms);
        int get(int key);
        void put(int key,int val);
        void show();
 };

完全なコード

/*************************************************************************
	> File Name: lru.cpp
	> Author:Ryan 
	> Mail: 
	> Created Time: Tue Oct 13 20:31:11 2020
    > Function :实现LRU缓存淘汰策略
 ************************************************************************/

#include<iostream>
#include<unordered_map>
using namespace std;

/*
 *双链表结点
 */ 
struct node{
    
    
    int val,key;
    node *prev,*next;
    node():prev(NULL),next(NULL){
    
    }
    node(int k,int v):key(k),val(v),prev(NULL),next(NULL){
    
    }
    
    //重载 == 号
    bool operator == (const node &p) const{
    
    
        return val==p.val&&key==p.key;
    }
 };

/*
 *双链表
 */ 
 class DoubleList{
    
    
     
     public:
        node *first;
        node *end;
        int n;

        DoubleList();
        void addFirst(node*);
        void remove(node*);
        int removeLast();
        int size();
 };
/*
 *构造函数,新建首尾节点,相连
 */ 
DoubleList::DoubleList(){
    
    
    n=0;
    first = new node();
    end = new node();
    first->next = end;
    end->prev = first;
}

/*
 *在第一位添加一个节点
 */ 
void DoubleList::addFirst(node *nd){
    
    
    n++;
    //node *tmp = new node(nd->key,nd>val);
    node *t = first->next;
    nd->next = t;
    first->next = nd;
    nd->prev = first;
    t->prev = nd;
}

/*
 *删除一个肯定存在的节点
 */
void DoubleList::remove(node *nd){
    
    
    n--;

    node *p = first;
    while(p->key!=nd->key){
    
    
        p=p->next;
    }
    node *pt = p->prev;
    node *nt = p->next;
    pt->next = nt;
    nt->prev = pt;
    delete p;
}
/*
 *删除最后一个节点
 */ 
int DoubleList::removeLast(){
    
    
    if(n>=1){
    
    
        node *tmp = end->prev;
        node *pt = tmp->prev;
    
        pt->next = end;
        end->prev = pt;

        int t = tmp->key;
        delete tmp;
        n--;
        return t;
    }
    return -1;
}

int DoubleList::size(){
    
    
    return n;
}

class LRUCache{
    
    
    private:
        unordered_map<int,node> map;
        DoubleList *lru;    
        int maxSize;

    public:
        LRUCache(){
    
    };
        LRUCache(int ms);
        int get(int key);
        void put(int key,int val);
        void show();
 };

LRUCache::LRUCache(int ms){
    
    
    maxSize = ms;
    lru = new DoubleList();
}
/*
 *查找该节点
 */
int LRUCache::get(int key){
    
    
    if(map.count(key)==0){
    
    
        return -1;
    }
    else{
    
    
        int val = map.find(key)->second.val;
        put(key,val);
        return val;
    }
}
/*
*将节点提前
*/
void LRUCache::put(int key,int value){
    
    
    node *nd = new node(key,value);
    
    if(map.count(nd->key)==1){
    
    
        //移到前面
        lru->remove(nd);
        lru->addFirst(nd);
    }
    else{
    
    
        if(lru->n==maxSize){
    
    
            int k = lru->removeLast();
            map.erase(k);
            lru->addFirst(nd);
        }
        else{
    
    
            lru->addFirst(nd);
        }
    }
    map[key] = *nd;
}

void LRUCache::show(){
    
    
    if(lru->n==0) cout<<"empty task"<<endl;
    else{
    
    
        node *p = lru->first->next;
        cout<<"当前一共有"<<lru->n<<"个任务: "<<endl;
        for(int i=0;i<lru->n;i++){
    
    
            cout<<"第"<<i+1<<"个任务: "<<p->val<<endl;
            p=p->next;
        }
    }
}

int main(){
    
    
    LRUCache *l = new LRUCache(3);
    l->put(1,2);
    l->put(2,3);
    l->put(3,4);
    l->put(4,5);
    l->show();
}

list + unordered_mapを使用して、この偉大な神を見てください:LRUキャッシュ

おすすめ

転載: blog.csdn.net/weixin_45146520/article/details/109078174