leetcode/notes/src/lru_cache.md

129 lines
2.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# LRU
[Leetcode 146. LRU Cache](https://leetcode.cn/problems/lru-cache/description/)
Header:
```cpp
#ifndef S0146_LRU_CACHE_HPP
#define S0146_LRU_CACHE_HPP
#include <cstdlib>
#include <unordered_map>
class LRUCache {
public:
/**
* @brief Least Recently Used Cache
*
* 这是一种常用的页面置换算法,选择最近最久未使用的页面予以淘汰
*
* @param capacity 容量,这是一个正整数
*/
LRUCache(int capacity);
/**
* @brief 读取数据
*
* @param key 数据对应的键值
* @return 数据的值
*/
int get(int key);
/**
* @brief 放入对应的数据
*
* @param key 数据对应的键值
* @param value 数据对应的值
*/
void put(int key, int value);
private:
struct CacheNode {
int key;
int value;
CacheNode *next;
CacheNode *prev;
CacheNode(int key, int value)
: key(key), value(value), next(nullptr), prev(nullptr){};
CacheNode(int key, int value, CacheNode *next, CacheNode *prev)
: key(key), value(value), next(next), prev(prev){};
};
CacheNode *head;
CacheNode *tail;
int capacity;
std::unordered_map<int, CacheNode *> map; // 键值是 key值是该节点的指针
void moveToHead(CacheNode *node); // 将节点移动到头部
};
#endif
```
Source:
```cpp
#include "s0146_lru_cache.hpp"
void LRUCache::moveToHead(CacheNode *node) {
// 如果是头部节点
if (node == head) return;
// 如果不是头部节点,但是是尾部节点
if (node == tail) tail = node->prev;
// 处理该节点的前后两个节点的指针
if (node->prev) node->prev->next = node->next;
if (node->next) node->next->prev = node->prev;
// 将该节点移动到头部
node->prev = nullptr;
node->next = head;
// 处理头部节点
head->prev = node;
head = node;
}
LRUCache::LRUCache(int capacity) {
this->capacity = capacity;
head = nullptr;
tail = nullptr;
map = std::unordered_map<int, CacheNode *>();
}
int LRUCache::get(int key) {
if (map.size() == 0) return -1;
if (map.count(key) == 0) return -1;
moveToHead(map[key]);
return map[key]->value;
}
void LRUCache::put(int key, int value) {
// 如果 key 已存在,则更新 value ,并将这个节点移动到头部
if (map.count(key) == 1) {
map[key]->value = value;
moveToHead(map[key]);
return;
}
// 否则创建该节点
CacheNode *newNode = (CacheNode *)malloc(sizeof(CacheNode));
newNode->value = value;
newNode->key = key;
newNode->next = head;
newNode->prev = nullptr;
// 处理头部节点
if (head) head->prev = newNode;
head = newNode;
// 处理尾部节点
if (map.size() == 0) tail = newNode;
// 更新哈希表
map[key] = newNode;
// 如果容量已满
if (map.size() > capacity) {
// 更新尾部节点
CacheNode *node = tail;
if (tail->prev) {
tail->prev->next = nullptr;
tail = tail->prev;
}
// 移除该节点
map.erase(node->key);
free(node);
}
}
```