C ++ implementa mecanismo de eliminação de cache LRU

Introdução ao cache

Para acelerar o acesso do usuário, precisamos entender o algoritmo de cache. Os algoritmos de cache comuns são:

  • LRU: (usado menos recentemente): Raramente é usado recentemente e não será eliminado primeiro.
  • LFU (usado com menos frequência): O menos usado, o menos usado serão eliminados primeiro.
  • FIFO (primeiro a entrar, primeiro a sair): Primeiro a entrar, primeiro a sair, o primeiro a entrar no buffer é eliminado primeiro.
    Hoje aprendi principalmente o algoritmo LRU.

Introdução ao LRU

LRU significa que quando o cache está cheio, se um novo programa for adicionado, aquele que não foi acessado por mais tempo no cache é apagado do cache, e então o novo programa é adicionado ao primeiro lugar no cache Este programa agora é o programa acessado com mais freqüência.

Dê um exemplo mais comum. Primeiro abrimos o WeChat, que agora está sendo executado em segundo plano, e depois abrimos o QQ e o Weibo.
No momento, a ordem do software exibido em segundo plano é: 1, Weibo 2, QQ 3, WeChat.
Assumindo que este celular só pode executar 3 programas em segundo plano, quando ligamos o NetEase Cloud Music, o segundo plano fecha automaticamente o WeChat e coloca o NetEase Cloud primeiro.
A ordem do software em segundo plano neste momento é: 1, NetEase Cloud 2, QQ 3, WeChat.

Princípio de realização

Análise de requisitos:
1. A estrutura de dados necessária para ser implementada é ordenada ==> lista vinculada
2. Pesquisa rápida é necessária ==> tabela de hash

Portanto, é necessário combinar as vantagens dessas duas e usar as duas estruturas juntas.
A estrutura do projeto é a seguinte:

/*
 *双链表结点
 */ 
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();
 };

A estrutura acima é para completar uma lista duplamente encadeada. A estrutura da lista duplamente ligada é muito eficiente ao inserir e excluir.
Então, para melhorar a eficiência da consulta, o modelo STL unordered_map é usado aqui. Isso é equivalente a um mapa não ordenado, mas a eficiência da consulta é estável e superior à de um mapa. Para obter mais detalhes, consulte: STL: unordered_map

A estrutura de cache construída é a seguinte:

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();
 };

Código completo

/*************************************************************************
	> 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();
}

Use list + unordered_map para ver este grande deus: cache LRU

Acho que você gosta

Origin blog.csdn.net/weixin_45146520/article/details/109078174
Recomendado
Clasificación