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