关键实现要点
- 
数据结构选择 - 双向链表:维护访问顺序
- 哈希表:快速查找节点
 
- 
淘汰策略 - 容量满时删除最久未使用的节点
- 访问时自动检查并删除超时节点
 
- 
时间管理 - 使用steady_clock记录节点时间戳
- 访问时更新节点时间
 
- 使用
完整代码实现
            
            
              cpp
              
              
            
          
          #include <unordered_map>
#include <list>
#include <chrono>
using namespace std;
using namespace std::chrono;
class TimedLRUCache {
private:
    // 节点结构:存储键、值和访问时间
    struct Node {
        int key;
        int value;
        steady_clock::time_point timestamp;
        
        Node(int k, int v) : key(k), value(v), timestamp(steady_clock::now()) {}
    };
    
    int capacity_;                      // 缓存容量
    int timeout_ms_;                    // 超时时间(毫秒)
    list<Node> cache_list_;             // 双向链表,维护访问顺序
    unordered_map<int, decltype(cache_list_.begin())> key_map_;  // 哈希表,快速查找
public:
    // 构造函数:设置容量和超时时间
    TimedLRUCache(int capacity, int timeout_ms = 0) 
        : capacity_(capacity), timeout_ms_(timeout_ms) {}
    
    // 获取值,不存在返回-1
    int get(int key) {
        auto it = key_map_.find(key);
        if (it == key_map_.end()) return -1;
        
        // 检查是否超时
        if (isExpired(it->second)) {
            removeNode(it->second);
            return -1;
        }
        
        // 更新访问时间并移动到链表头部
        it->second->timestamp = steady_clock::now();
        cache_list_.splice(cache_list_.begin(), cache_list_, it->second);
        return it->second->value;
    }
    
    // 插入或更新值
    void put(int key, int value) {
        auto it = key_map_.find(key);
        
        if (it != key_map_.end()) {
            // 键已存在,更新值和访问时间
            it->second->value = value;
            it->second->timestamp = steady_clock::now();
            cache_list_.splice(cache_list_.begin(), cache_list_, it->second);
            return;
        }
        
        // 检查容量,删除最久未使用的节点
        if (cache_list_.size() >= capacity_) {
            removeLRUNode();
        }
        
        // 插入新节点到链表头部
        cache_list_.emplace_front(key, value);
        key_map_[key] = cache_list_.begin();
    }
    
    // 检查键是否存在且未超时
    bool contains(int key) {
        auto it = key_map_.find(key);
        if (it == key_map_.end()) return false;
        
        if (isExpired(it->second)) {
            removeNode(it->second);
            return false;
        }
        return true;
    }
    
    // 获取当前缓存大小
    int size() const {
        return cache_list_.size();
    }
    
    // 获取缓存容量
    int capacity() const {
        return capacity_;
    }
private:
    // 检查节点是否超时
    bool isExpired(decltype(cache_list_.begin()) iter) {
        if (timeout_ms_ == 0) return false; // 0表示永不过期
        
        auto now = steady_clock::now();
        auto elapsed = duration_cast<milliseconds>(now - iter->timestamp);
        return elapsed.count() > timeout_ms_;
    }
    
    // 删除指定节点
    void removeNode(decltype(cache_list_.begin()) iter) {
        key_map_.erase(iter->key);
        cache_list_.erase(iter);
    }
    
    // 删除最久未使用的节点
    void removeLRUNode() {
        if (cache_list_.empty()) return;
        
        // 从尾部开始查找未超时的节点删除
        for (auto it = cache_list_.rbegin(); it != cache_list_.rend(); ++it) {
            auto list_it = prev(it.base()); // 反向迭代器转正向迭代器
            if (!isExpired(list_it)) {
                removeNode(list_it);
                return;
            }
        }
        
        // 如果所有节点都超时,删除最后一个
        if (!cache_list_.empty()) {
            removeNode(prev(cache_list_.end()));
        }
    }
};使用示例
            
            
              cpp
              
              
            
          
          #include <iostream>
#include <thread>
int main() {
    // 创建缓存:容量3,超时时间1000ms
    TimedLRUCache cache(3, 1000);
    
    // 测试基本功能
    cache.put(1, 100);
    cache.put(2, 200);
    cache.put(3, 300);
    
    cout << "初始状态 - 大小: " << cache.size() << endl; // 3
    cout << "获取键2: " << cache.get(2) << endl;         // 200
    
    // 测试超时功能
    this_thread::sleep_for(milliseconds(1500));
    cout << "超时后获取键1: " << cache.get(1) << endl;   // -1 (已超时)
    cout << "超时后大小: " << cache.size() << endl;      // 2 (自动清理)
    
    // 测试LRU淘汰
    cache.put(4, 400);
    cache.put(5, 500);
    cout << "插入新键后大小: " << cache.size() << endl;  // 3
    
    return 0;
}关键点梳理
1. 数据结构设计
- 双向链表:维护节点的访问顺序,最近访问的在头部
- 哈希表:提供O(1)时间复杂度的节点查找
- 节点结构:包含键、值和时间戳三要素
2. 淘汰策略实现
            
            
              cpp
              
              
            
          
          // 关键代码:删除最久未使用节点
void removeLRUNode() {
    // 从尾部开始查找(最久未使用)
    for (auto it = cache_list_.rbegin(); it != cache_list_.rend(); ++it) {
        auto list_it = prev(it.base());
        if (!isExpired(list_it)) {  // 找到第一个未超时的节点
            removeNode(list_it);
            return;
        }
    }
    // 所有节点都超时,删除最后一个
    if (!cache_list_.empty()) {
        removeNode(prev(cache_list_.end()));
    }
}3. 时间管理机制
            
            
              cpp
              
              
            
          
          // 关键代码:超时检查
bool isExpired(decltype(cache_list_.begin()) iter) {
    if (timeout_ms_ == 0) return false; // 永不过期
    
    auto now = steady_clock::now();
    auto elapsed = duration_cast<milliseconds>(now - iter->timestamp);
    return elapsed.count() > timeout_ms_;
}4. 访问顺序维护
            
            
              cpp
              
              
            
          
          // 关键代码:节点访问时的处理
it->second->timestamp = steady_clock::now();  // 更新时间
cache_list_.splice(cache_list_.begin(), cache_list_, it->second); // 移动到头部核心优势
- 时间复杂度:get和put操作都是O(1)
- 空间复杂度:O(capacity),只存储有限节点
- 自动清理:访问时自动检查并删除超时节点
- 线程安全:单线程环境下安全使用
这个实现平衡了功能完整性和代码简洁性,适合需要基础缓存功能的场景。