Оглавление
Алгоритм LRU
Основываясь на принципе локальности, память, к которой недавно обращались, скорее всего, будет снова доступна в будущем.
Поэтому, когда мы удаляем данные, мы отдаем приоритет удалению данных, которые не использовались в течение длительного времени.
Идеи реализации
Используйте двусвязный список, чтобы монтировать самые последние использованные данные в начало цепочки, чтобы самые длинные неиспользуемые данные находились в конце очереди, и удаляйте элементы в конце очереди при удалении данных.
Чтобы быстро найти ключевой ключПоложение ключа в связанном списке, вы можете использовать хэш-таблицу для записи ключа — Node key-Nodeк е й−Сопоставление узлов . _ _
тема
Код
class LRUCache
{
public:
struct DListNode
{
int key, value; //事实上key值没有使用
DListNode *pre;
DListNode *next;
DListNode() {
}
DListNode(int a, int b) {
key = a, value = b; }
};
unordered_map<int, DListNode *> mp; // key-Node 映射
int MAX_SIZE;
DListNode *HEAD;
DListNode *TAIL;
LRUCache(int capacity) //初始化双向链表
{
MAX_SIZE = capacity;
HEAD = new DListNode;
TAIL = new DListNode;
HEAD->next = TAIL;
TAIL->pre = HEAD;
}
int get(int key)
{
if (!mp.count(key)) //如果该key不存在,返回-1
return -1;
DListNode *tmp = mp[key]; //将这个结点调整到链表头部
tmp->pre->next = tmp->next;
tmp->next->pre = tmp->pre;
tmp->next = HEAD->next;
tmp->pre = HEAD;
HEAD->next = tmp;
tmp->next->pre = tmp;
return mp[key]->value;
}
void put(int key, int value)
{
if (!mp.count(key)) //如果之前不在缓存,创建并放到链头
{
DListNode *tmp = new DListNode(key, value); //将这个结点放到链表头部
mp[key] = tmp;
tmp->pre = HEAD;
tmp->next = HEAD->next;
HEAD->next->pre = tmp;
HEAD->next = tmp;
if (mp.size() > MAX_SIZE) //超过容量,需要删除链表尾部结点
{
mp.erase(TAIL->pre->key);
TAIL->pre->pre->next = TAIL;
TAIL->pre = TAIL->pre->pre;
}
}
else //已经存在,调整到链表头部
{
DListNode *tmp = mp[key];
tmp->value = value;
tmp->pre->next = tmp->next;
tmp->next->pre = tmp->pre;
tmp->next = HEAD->next;
tmp->pre = HEAD;
HEAD->next->pre = tmp;
HEAD->next = tmp;
}
}
};