下面我将用C++实现一个高效的LRU缓存,使用哈希表(unordered_map)和双向链表(list)的组合来实现O(1)时间复杂度的操作。
完整实现代码
#include <iostream>
#include <list>
#include <unordered_map>
using namespace std;
template <typename K, typename V>
class LRUCache {
public:
// 构造函数,初始化缓存容量
LRUCache(size_t size) : capacity(size) {}
// 获取键对应的值
V get(K key) {
auto it = cacheMap.find(key);
if (it == cacheMap.end()) {
// 键不存在,根据实际需求可以返回默认值或抛出异常
// 这里返回V类型的默认构造值
return V();
}
// 将访问的键值对移到链表头部
cacheList.splice(cacheList.begin(), cacheList, it->second);
return it->second->second;
}
// 插入或更新键值对
void put(K key, V value) {
auto it = cacheMap.find(key);
if (it != cacheMap.end()) {
// 键已存在,更新值并移到链表头部
it->second->second = value;
cacheList.splice(cacheList.begin(), cacheList, it->second);
return;
}
// 检查是否达到容量限制
if (cacheMap.size() == capacity) {
// 删除链表尾部的元素(最久未使用)
auto last = cacheList.back();
cacheMap.erase(last.first);
cacheList.pop_back();
}
// 插入新元素到链表头部
cacheList.emplace_front(key, value);
cacheMap[key] = cacheList.begin();
}
// 打印缓存内容(用于调试)
void printCache() {
cout << "LRU Cache (capacity=" << capacity << ", size=" << cacheMap.size() << "):" << endl;
for (const auto& item : cacheList) {
cout << item.first << ":" << item.second << " ";
}
cout << endl;
}
private:
// 缓存容量
size_t capacity;
// 双向链表存储键值对,最近使用的在链表头,最久未使用的在链表尾
list<pair<K, V>> cacheList;
// 哈希表存储键到链表迭代器的映射
unordered_map<K, typename list<pair<K, V>>::iterator> cacheMap;
};
// 测试用例
int main() {
LRUCache<int, string> cache(3);
cache.put(1, "One");
cache.put(2, "Two");
cache.put(3, "Three");
cache.printCache(); // 输出: 3:Three 2:Two 1:One
cout << "Get 2: " << cache.get(2) << endl; // 输出: Two
cache.printCache(); // 输出: 2:Two 3:Three 1:One
cache.put(4, "Four"); // 淘汰1:One
cache.printCache(); // 输出: 4:Four 2:Two 3:Three
cout << "Get 1: " << cache.get(1) << endl; // 输出空字符串(默认构造值)
return 0;
}
实现说明
-
数据结构选择:
list<pair<K, V>>:双向链表,维护键值对的访问顺序unordered_map<K, list>:哈希表,实现O(1)的键查找
-
关键操作:
get(key):查找键,若存在则将其移到链表头部put(key, value):更新或插入键值对,必要时淘汰最久未使用的项
-
性能分析:
- 时间复杂度:get和put操作都是O(1)
- 空间复杂度:O(capacity)
-
线程安全:
- 此实现不是线程安全的,多线程环境下需要加锁
扩展功能
如果需要更完整的实现,可以考虑添加以下功能:
// 添加元素数量查询
size_t size() const {
return cacheMap.size();
}
// 判断是否包含键
bool contains(K key) const {
return cacheMap.find(key) != cacheMap.end();
}
// 删除指定键
void erase(K key) {
auto it = cacheMap.find(key);
if (it != cacheMap.end()) {
cacheList.erase(it->second);
cacheMap.erase(it);
}
}
// 清空缓存
void clear() {
cacheList.clear();
cacheMap.clear();
}
4250

被折叠的 条评论
为什么被折叠?



