新闻中心

c++怎么实现一个LRU缓存算法_c++中LRU缓存的设计与实现

2025-11-11
浏览次数:
返回列表
LRU缓存通过哈希表和双向链表结合实现,get和put操作均O(1):哈希表映射key到链表节点,链表维护访问顺序,最近使用置头,满时删尾。

c++怎么实现一个lru缓存算法_c++中lru缓存的设计与实现

实现一个LRU(Least Recently Used)缓存的核心思路是:当缓存满时,优先淘汰最久未使用的数据。为了高效地完成插入、查找和更新操作,C++中通常结合哈希表(unordered_map)和双向链表(list)来实现。

1. LRU缓存的基本要求

一个LRU缓存需要支持以下两个核心操作:

  • get(key):如果键存在,返回对应的值,并将该键移到最近使用位置;否则返回 -1。
  • put(key, value):插入或更新键值对。如果超出容量,删除最久未使用的条目。

这两个操作的时间复杂度都应为 O(1)。

2. 数据结构选择

要达到 O(1) 的时间复杂度,可以这样设计:

Perplexity Perplexity

Perplexity是一个ChatGPT和谷歌结合的超级工具,可以让你在浏览互联网时提出问题或获得即时摘要

Perplexity 302 查看详情 Perplexity
  • unordered_mapair>::iterator>:用于快速定位某个 key 是否存在及其在链表中的位置。
  • list>:双向链表存储键值对,最近使用的放在链表头部,最久未使用的在尾部。

这种组合既能快速查找,又能高效地移动和删除节点。

3. 实现代码示例

#include <iostream>
#include <unordered_map>
#include <list>

class LRUCache {
private:
    int capacity;
    std::unordered_map<int, std::list<std::pair<int, int>>::iterator> cache;
    std::list<std::pair<int, int>> used;

public:
    LRUCache(int cap) : capacity(cap) {}

    int get(int key) {
        auto it = cache.find(key);
        if (it == cache.end()) {
            return -1;
        }
        // 将当前访问的节点移到链表头部
        used.splice(used.begin(), used, it->second);
        return it->second->second;
    }

    void put(int key, int value) {
        auto it = cache.find(key);
        if (it != cache.end()) {
            // 更新值并移到头部
            it->second->second = value;
            used.splice(used.begin(), used, it->second);
            return;
        }

        // 插入新元素到链表头部
        used.emplace_front(key, value);
        cache[key] = used.begin();

        // 如果超过容量,删除尾部元素
        if (cache.size() > capacity) {
            int lastKey = used.back().first;
            cache.erase(lastKey);
            used.pop_back();
        }
    }
};

4. 关键点说明

splice 是关键操作:它可以把链表中的某个迭代器指向的节点“剪切”并粘贴到另一个位置,不会导致迭代器失效,且时间复杂度为 O(1)。

  • 每次 get 或 put 已存在的 key 时,都要调用 splice 将其移到链表头部。
  • 新插入的元素直接加到头部,淘汰时从尾部移除。
  • 哈希表保存的是 list 的 iterator,可以直接访问对应节点。

基本上就这些。这个实现简洁、高效,适合面试和实际项目中使用。注意边界情况处理,比如容量为 0 或重复插入等情况即可。不复杂但容易忽略细节。

以上就是c++++怎么实现一个LRU缓存算法_c++中LRU缓存的设计与实现的详细内容,更多请关注其它相关文章!


# 是一个  # 响应式网站建设报价多少  # 机械网站推广哪家信誉好  # 郑州优惠seo推荐  # 四川关键词排名提升案列  # 岳麓区靠谱营销推广方式  # seo骗人的  # 成都网站推广运营  # 优良的房产问答营销推广  # 做网站建设方面  # 学校怎么优化网站  # 迭代  # 边缘  # ai  # 的是  # 最久  # 游戏开发  # 数据结构  # 键值  # 移到  # 链表  # red  # 键值对  # stream  # ios  # c++ 


相关栏目: 【 科技资讯46185 】 【 网络学院92790


相关推荐: 如何使用spryker/configurable-bundles-products-resource-relationship模块解决复杂产品捆绑关系难题  顺丰快件物流信息 官方网站查询入口  4399体育竞技小游戏_4399小游戏赛事入口  在哪找SublimeJ远程工具_SFTP插件配置教程  AO3网页版最新入口合集 Archive of Our Own在线访问指南  免费抖音短视频入口_抖音网页版短视频免费通道  AO3最新可访问网址 Archive of Our Own官方在线入口  qq浏览器打开空白页怎么办 qq浏览器启动后显示白屏的解决教程  J*aScript中高效清空DOM列表元素:解决for循环中断与任务管理问题  如何解决电商平台定制报价请求的“黑洞”问题,SprykerQuoteRequest模块助你提升客户体验与销售效率  深入理解Google Cloud Datastore查询:祖先路径与数据一致性  《铁拳8》黑皮辣妹新实机:元气满满的18岁少女!  探索高级语言到原生C/C++的转译:挑战与内存管理策略  消息称三星明年 2 月正式发布 HBM4,与 SK 海力士同台竞技  Lar*el的路由模型绑定怎么用_Lar*el Route Model Binding简化控制器逻辑  三星GalaxyZFold5怎样在相册制作折叠屏分镜_iPhone三星GalaxyZFold5相册制作折叠屏分镜【创意编辑】  护手霜蹭到袖口上了如何清洗? 怎样避免留下一圈油印?  NRF24L01数据传输深度解析:解决大载荷接收异常与分包策略  Yandex搜索引擎官网入口_俄罗斯Yandex免登录一键直达  AO3访问入口汇总 AO3网页版同人作品一键直达  qq游戏网页版直接玩_qq游戏免下载快速入口  css滚动区域卡顿如何改善_css滚动问题用will-change优化渲染  谷歌google账号注册详细步骤 谷歌账号注册官方教程  在J*a中如何开发简易仓库管理与库存统计_仓库管理库存统计项目实战解析  AO3中文官网链接_AO3网页版稳定镜像站  Composer的 "licenses" 命令如何帮助你遵守开源协议_检查项目依赖的许可证合规性  yandex入口引擎手机版 yandex安卓版下载入口  在J*a中如何开发简易电子商务商品管理系统_商品管理系统项目实战解析  c++20的std::jthread是什么_c++可中断线程与RAII式管理  漫蛙2漫画入口 漫蛙正版网页漫画直达网址  Golang如何实现Web文件静态资源服务器_Golang静态资源服务器开发与实践  Web Components中自定义开关组件状态同步的常见陷阱与解决方案  poki免费入口快捷访问 poki人气小游戏直接玩站点  AO3同人作品网入口 AO3搜索引擎官网永久地址  微博网页版直接访问 微博网页版账号管理快速入口  一加手机拍照效果不好怎么办 一加哈苏影像调校与专业模式使用教程【高手篇】  实现全屏滚动与导航点:专业教程  Spring Boot嵌入式服务器与J*a EE:功能支持深度解析  HTML长属性值处理:表单action路径优化与代码规范应对  我的世界官方游戏入口 我的世界官网平台直达链接  如何在CSS中使用浮动制作导航栏_float实现水平菜单  理解Python模块与全局变量的作用域管理  AO3镜像入口大全 AO3网页版内容访问全集  优化MinIO list_objects_v2 操作的性能瓶颈与最佳实践  使用 Pandas 高效处理 .dat 文件:字符清理与数据计算  C++如何实现线程池_C++11手动实现一个简单的固定大小线程池  Django模型中自动计算可用余额的实现方法  漫蛙网页登录入口 漫蛙漫画官方授权网址  在Go开发中优雅管理ListenAndServe进程:GoSublime集成方案  J*aScript map 迭代中检测空数组元素的有效方法 

搜索