LRU Cache 双向链表以及STL list实现----面试常考

embedded/2024/10/9 15:18:21/
双向链表版本:
#include <bits/stdc++.h>
using namespace std;
struct Node{int key, value;Node* prev;Node* next;Node():key(0), value(0), prev(nullptr), next(nullptr){}Node(int k, int v):key(k), value(v), prev(nullptr), next(nullptr){}
};
class LRUCache{
private:int capacity_;int size_;Node* head;Node* tail;unordered_map<int, Node*> cache_;
public:LRUCache(int capacity): capacity_(capacity), size_(0){head = new Node();tail = new Node();head->next = tail;tail->prev = head;}void removeNode(Node* node){node->prev->next = node->next;node->next->prev = node->prev;}void addToHead(Node* node){node->next = head->next;node->prev = head;head->next->prev = node;head->next = node;}void moveToHead(Node* node){removeNode(node);addToHead(node);}Node* removeTail(){auto node = tail->prev;removeNode(node);return node;}int get(int key){if(cache_.find(key) != cache_.end()){moveToHead(cache_[key]);return cache_[key]->value;}return -1;}void put(int key, int value){if(cache_.find(key) != cache_.end()){moveToHead(cache_[key]);cache_[key]->value = value;}else{if(size_ == capacity_){auto node = removeTail();cache_.erase(node->key);delete node;--size_;}auto node = new Node(key, value);addToHead(node);cache_.insert({key, node});++size_;}}~LRUCache(){while(head){auto node = head;head = head->next;delete node;}}void print(){cout << "=================" << endl;auto node = head->next;while(node != tail){cout << "[" << node->key << " " << node->value << "]" << endl;node = node->next;}}
};
int main(){auto lru = new LRUCache(2);lru->put(1, 1);lru->put(2, 2);lru->print();lru->put(3, 3);lru->print();cout << lru->get(2) << endl;lru->print();lru->put(4, 4);lru->print();cout << lru->get(1) << endl;lru->print();cout << lru->get(3) << endl;return 0;
}

手写双向链表版本比较简单,在纸上画一画就能想通!

list_107">STL的list版本:
using pi = pair<int, int>;
class LRUCache {
public:LRUCache(int capacity):capacity_(capacity){}/*** 根据给定的键获取缓存中的值。* 如果键存在于缓存中,则将该键值对移动到缓存的前端,并返回对应的值。* 如果键不存在于缓存中,则返回-1。* * @param key 要查询的键。* @return 存储在缓存中的键对应的值,如果键不存在则返回-1。*/int get(int key) {// 检查键是否存在于缓存中if(key_table_.count(key)){// 获取键对应的节点auto node = key_table_[key];// 从节点中提取值int value = node->second;// 从缓存中删除节点,因为它即将被移动到前端cache_.erase(node);// 将键值对移动到缓存的前端cache_.push_front({key, value});// 更新键在映射表中的指针,指向移动到前端的新节点key_table_[key] = cache_.begin();// 返回键对应的值return value;}// 如果键不存在,返回-1return -1;}/*** 将键值对(key, value)放入缓存。* 如果键已经存在,则更新对应的值,并从缓存中移除该键值对,以便重新插入以维护LRU顺序。* 如果缓存已满,则移除最不常访问的键值对,为新键值对腾出空间。* * @param key 要放入缓存的键。* @param value 要放入缓存的值。*/void put(int key, int value) {// 如果键已经存在,则获取对应的节点if(key_table_.count(key)){auto node = key_table_[key];int value = node->second;// 从缓存中移除该节点,因为待会要重新插入以维护LRU顺序cache_.erase(node);}else{// 如果缓存已满,则移除最不常访问的键值对if(cache_.size() == capacity_){auto kv = cache_.back();int k = kv.first, v = kv.second;cache_.pop_back();key_table_.erase(k);}}// 将新的键值对插入到缓存的前端,并更新键映射表cache_.push_front({key, value});key_table_[key] = cache_.begin();}
private:unordered_map<int, list<pi>::iterator> key_table_; list<pi> cache_;   // 缓存int capacity_;   
};

主要用了迭代器,对于初学者可能难以理解。可以看我的下一篇博客,详细阐述了迭代器设计思想!


http://www.ppmy.cn/embedded/56410.html

相关文章

Unreal Engine@Jetson Orin Nano尚不支持

Unreal EngineJetson Orin Nano尚不支持 1. 源由2. Unreal Engine介绍3. 问题4. 编译方法5. 补充6. 其他 1. 源由 最近在看SC-Explorer方面的内容&#xff0c;在模拟方面采用了Unreal Engine。 本打算跑下模拟&#xff0c;因此打算在JetsonOrin的板子上试试看。 2. Unreal En…

【进阶篇-Day6:JAVA中Arrays工具类、排序算法、正则表达式的介绍】

目录 1、Arrays工具类2、排序算法2.1 冒泡排序2.2 选择排序2.3 二分查找&#xff08;折半查找&#xff09;&#xff08;1&#xff09;概念&#xff1a;&#xff08;2&#xff09;步骤&#xff1a; 3、正则表达式3.1 正则表达式的概念&#xff1a;3.2 正则表达式的格式&#xff…

项目实战--Spring Boot与PageHelper的集成及线程污染解决

一、PageHelper使用背景 公司要做个简单管理系统&#xff0c;要我搭建Spring BootMyBatisPageHelperRedis的项目框架然后交i给实习生来开发。这个其实很简单&#xff0c;但是遇到搭建和使用过程中PageHelper有好多小坑&#xff0c;就记录一下&#xff0c;避免再踩。 版本选择&…

iOS 真机打包,证书报错No signing certificate “iOS Distribution” found

之前将APP从旧账号转移到了新账号&#xff0c;在新账号打包的时候遇到的证书问题。 因为新账号还没有导出“本地签名证书”&#xff0c;也还没有创建新的“发布证书”。当我创建好这两者之后&#xff0c;在xcode打包的时候就报错了。 报错信息&#xff1a; No signing certifi…

springai+pgvector+ollama实现rag

首先在ollama中安装mofanke/dmeta-embedding-zh:latest。执行ollama run mofanke/dmeta-embedding-zh 。实现将文本转化为向量数据 接着安装pgvector&#xff08;建议使用pgadmin4作为可视化工具&#xff0c;用navicate会出现表不显示的问题&#xff09; 安装好需要的软件后我们…

ceph-volume inventory KeyError: ‘TYPE‘ 处理

是否有人跟我一样碰到这样的情况 执行ceph-volume inventory报错 还好有错误日志可以看 [2024-07-05 11:40:40,540][ceph_volume.process][INFO ] Running command: /usr/sbin/blkid -c /dev/null -p /dev/ceph-c5fd6684-3851-49ab-bd44-f6743a79e24f/osd-block-42d41cd1-82…

密码学原理精解【5】

这里写目录标题 移位密码概述代码 希尔密码( Z 256 Z_{256} Z256​)待加密长度被3整除待加密长度不一定被3整除加解密文件 移位密码 概述 以 z 26 运算为例 , k 为密钥 加密&#xff1a; e k ( x ) ( x k ) m o d 26 解密&#xff1a; d k ( x ) ( x − k ) m o d 26 以z_{…

你真的会ELISA加样吗?

在ELISA实验中&#xff0c;研究人员需要进行多次加样步骤完成实验操作。对于常规双抗体夹心法ELISA&#xff0c;一般有如下加样步聚&#xff0c;即加样本、加检测抗体、加酶结合物、加底物&#xff08;最后加终止液停止反应&#xff09;。 加样步骤基础知识 加样步骤中一般使用…