C++如何实现最近最少使用算法LRU缓存逻辑

来源:站长站作者:小白龙头衔:草根站长
导读:本期聚焦于小伙伴创作的《C++如何实现最近最少使用算法LRU缓存逻辑》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《C++如何实现最近最少使用算法LRU缓存逻辑》有用,将其分享出去将是对创作者最好的鼓励。

最近最少使用算法(LRU)是操作系统中内存页面调度和分布式系统中缓存淘汰的常用策略,核心逻辑是当缓存空间不足时,优先淘汰最久没有被访问过的缓存数据。在C++中实现LRU缓存,需要同时维护数据的访问顺序和快速的查询、插入、删除能力。

C++如何实现最近最少使用算法LRU缓存逻辑

LRU算法核心设计思路

要实现高效的LRU缓存,需要满足以下操作的时间复杂度尽可能低:

  • 查询缓存数据:O(1)时间复杂度
  • 插入新的缓存数据:O(1)时间复杂度
  • 淘汰最久未访问的数据:O(1)时间复杂度

单独使用哈希表可以实现O(1)的查询,但无法维护访问顺序;单独使用链表可以维护顺序,但查询需要O(n)时间。因此最优的组合是使用哈希表+双向链表

  • 哈希表存储键到双向链表节点的映射,实现快速查询
  • 双向链表按访问时间排序,头部是最新访问的节点,尾部是最久未访问的节点

数据结构定义

首先定义双向链表的节点结构,每个节点存储缓存的键、值,以及前驱和后继指针:

// 双向链表节点定义
struct LRU_Node {
    int key;
    int value;
    LRU_Node* prev;
    LRU_Node* next;
    LRU_Node(int k, int v) : key(k), value(v), prev(nullptr), next(nullptr) {}
};

然后定义LRU缓存类,包含缓存容量、哈希表、双向链表的头尾虚拟节点:

#include <unordered_map>
#include <iostream>

class LRU_Cache {
private:
    int capacity;  // 缓存最大容量
    std::unordered_map<int, LRU_Node*> cache_map;  // 键到链表节点的映射
    LRU_Node* head;  // 虚拟头节点,指向最新访问的节点
    LRU_Node* tail;  // 虚拟尾节点,指向最久未访问的节点

    // 将节点移动到链表头部(表示最新访问)
    void move_to_head(LRU_Node* node) {
        if (node == head->next) return;  // 已经是头节点,无需移动
        // 先移除节点原有位置
        remove_node(node);
        // 插入到头节点之后
        add_to_head(node);
    }

    // 移除指定节点
    void remove_node(LRU_Node* node) {
        node->prev->next = node->next;
        node->next->prev = node->prev;
    }

    // 将节点插入到头节点之后
    void add_to_head(LRU_Node* node) {
        node->next = head->next;
        node->prev = head;
        head->next->prev = node;
        head->next = node;
    }

    // 移除链表尾部节点(最久未访问)
    LRU_Node* remove_tail() {
        LRU_Node* node = tail->prev;
        remove_node(node);
        return node;
    }

public:
    // 构造函数,初始化缓存容量和虚拟头尾节点
    LRU_Cache(int cap) : capacity(cap) {
        head = new LRU_Node(-1, -1);
        tail = new LRU_Node(-1, -1);
        head->next = tail;
        tail->prev = head;
    }

    // 析构函数,释放所有节点内存
    ~LRU_Cache() {
        LRU_Node* curr = head;
        while (curr != nullptr) {
            LRU_Node* next = curr->next;
            delete curr;
            curr = next;
        }
    }
};

核心操作实现

查询缓存数据

查询时先通过哈希表判断键是否存在,如果不存在返回-1;如果存在,将对应节点移动到链表头部表示最新访问,再返回值:

int get(int key) {
    // 键不存在,返回-1
    if (cache_map.find(key) == cache_map.end()) {
        return -1;
    }
    // 键存在,将节点移动到头部,返回值
    LRU_Node* node = cache_map[key];
    move_to_head(node);
    return node->value;
}

插入缓存数据

插入时先判断键是否存在:如果已存在,更新值并将节点移动到头部;如果不存在,创建新节点插入头部,同时加入哈希表,如果超过容量则淘汰尾部节点:

void put(int key, int value) {
    if (cache_map.find(key) != cache_map.end()) {
        // 键已存在,更新值并移动到头部
        LRU_Node* node = cache_map[key];
        node->value = value;
        move_to_head(node);
    } else {
        // 键不存在,创建新节点
        LRU_Node* new_node = new LRU_Node(key, value);
        // 加入哈希表
        cache_map[key] = new_node;
        // 插入到链表头部
        add_to_head(new_node);
        // 超过容量,淘汰尾部节点
        if (cache_map.size() > capacity) {
            LRU_Node* tail_node = remove_tail();
            cache_map.erase(tail_node->key);
            delete tail_node;
        }
    }
}

完整测试示例

以下代码测试LRU缓存的基本功能:

int main() {
    LRU_Cache* lru_cache = new LRU_Cache(2);  // 缓存容量为2

    lru_cache->put(1, 1);  // 缓存是 {1=1}
    lru_cache->put(2, 2);  // 缓存是 {1=1, 2=2}
    std::cout << lru_cache->get(1) << std::endl;  // 返回1,缓存变为 {2=2, 1=1}
    lru_cache->put(3, 3);  // 淘汰键2,缓存变为 {1=1, 3=3}
    std::cout << lru_cache->get(2) << std::endl;  // 返回-1,键2不存在
    lru_cache->put(1, 10);  // 更新键1的值,缓存变为 {3=3, 1=10}
    std::cout << lru_cache->get(1) << std::endl;  // 返回10
    std::cout << lru_cache->get(3) << std::endl;  // 返回3

    delete lru_cache;
    return 0;
}

复杂度分析

该实现的各项操作复杂度如下:

操作时间复杂度空间复杂度
get查询O(1)O(1)
put插入/更新O(1)O(1)
整体缓存-O(capacity)

这种实现方式兼顾了查询效率和顺序维护的需求,适合大多数需要LRU缓存的场景,比如数据库查询缓存、接口返回结果缓存等。如果需要对缓存数据做持久化或者分布式同步,可以在此基础上扩展对应的逻辑。

C++LRU_cache内存调度缓存算法修改时间:2026-06-10 03:48:39

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。