LRU算法介绍
LRU(Least Recently Used)算法是一种常用的页面置换算法,常用于缓存管理。其基本思想是将最近最少使用的页面淘汰,以便为新页面腾出空间。
工作原理
- 缓存访问:当访问一个缓存中的页面时,若该页面存在于缓存中,则将其标记为最新使用;若不存在,则需要将其加入缓存中。
- 缓存更新:加入新页面时,如果缓存已满,则淘汰最近最少使用的页面,并将新页面插入缓存中。
- 数据结构:通常使用双向链表(维护访问顺序)和哈希表(提供O(1)时间复杂度的查找)。
主要操作
- 获取页面(Get):从缓存中获取页面数据。如果页面存在,返回数据并将页面标记为最新使用;否则返回-1。
- 插入页面(Put):将新页面插入缓存。如果缓存已满,则先淘汰最近最少使用的页面,再插入新页面。
C++实现
使用unordered_map
和list
实现LRU缓存。unordered_map
用于快速查找页面,list
用于维护访问顺序。
#include <iostream>
#include <list>
#include <unordered_map>
class LRUCache {
private:
int capacity;
std::list<int> cache;
std::unordered_map<int, std::pair<int, std::list<int>::iterator>> map;
void moveToHead(int key) {
cache.erase(map[key].second);
cache.push_front(key);
map[key].second = cache.begin();
}
public:
LRUCache(int capacity) : capacity(capacity) {}
int get(int key) {
if (map.find(key) == map.end()) {
return -1;
} else {
moveToHead(key);
return map[key].first;
}
}
void put(int key, int value) {
if (map.find(key) == map.end()) {
if (cache.size() == capacity) {
int oldKey = cache.back();
cache.pop_back();
map.erase(oldKey);
}
cache.push_front(key);
map[key] = {value, cache.begin()};
} else {
map[key].first = value;
moveToHead(key);
}
}
void display() {
for (auto it = cache.begin(); it != cache.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
}
};
int main() {
LRUCache lruCache(3);
lruCache.put(1, 10);
lruCache.put(2, 20);
lruCache.put(3, 30);
lruCache.display(); // 3 2 1
lruCache.get(1);
lruCache.display(); // 1 3 2
lruCache.put(4, 40);
lruCache.display(); // 4 1 3
lruCache.get(2); // returns -1 (not found)
lruCache.display(); // 4 1 3
lruCache.put(5, 50);
lruCache.display(); // 5 4 1
return 0;
}
说明
cache
是一个双向链表,用于维护页面的访问顺序,最前面的元素是最近使用的,最后面的元素是最久未使用的。map
是一个哈希表,用于存储键到值和链表迭代器的映射,支持O(1)时间复杂度的查找。moveToHead
函数用于将访问的页面移动到链表的头部,表示最近使用。get
函数用于获取页面值,如果页面存在则返回值并将页面移动到头部,否则返回-1。put
函数用于插入新页面,如果页面不存在且缓存已满,则移除最久未使用的页面,再插入新页面。如果页面已存在,则更新值并将页面移动到头部。
这个C++实现的LRU缓存具备了O(1)时间复杂度的插入和查找操作,适合用于需要高效缓存管理的场景。