LRU缓存机制(C/C++实现)
2020-04-19 22:43
645 查看
在操作系统中,段式存储、页式存储与段页式存储是文件存储的重要方式。其中,在页式存储中,CPU为了快速获取页的内容,会在内存中缓存一些出现频率较高的页面,如果需要访问未存储在内存中的页面,需要去外设中进行访问,并将其导入到内存;但是,由于内存中不可能承载过量的页面,所以,随着页面数量的增多,系统会覆盖掉一些不常用的页面,这个过程也就是常说的页面置换算法。
其中,最为经典的即为LRU(Least Recently Used)算法,该算法的思路是:如果一个数据在最近一段时间没有被访问到,那么在将来它被访问的可能性也很小,也就是说,当限定的空间已存满数据时,应当把最久没有被访问到的数据淘汰。
实现LRU缓存机制也是Leetcode上一道经典的算法题,在JAVA中,采用linkedhashmap可以非常方便的实现LRU的缓存,这是因为linkedhashmap的底层数据结构与LRU可实现的数据结构非常类似,都是采用双向链表+hashmap来进行实现。
对LRU缓存的操作,不考虑从外设中读取页面的话,主要包括get和put操作,其中get操作的操作过程为:
- 通过hashmap查找是否存在所要查询的内容,如果存在则继续;
- 获取带查询的内容;
- 从双向链表中删除该节点;
- 将该节点插入到链表头部。
而put操作的过程要区分原链表中包含和不包含待插入的节点的key:
- 通过hashmap查询链表中是否存在待插入节点的key,如果存在,则进入步骤2,不存在则进入步骤3;
- 修改已有节点内的值,从双向链表中删除该节点,并将该节点插入到链表头部;
- 新建一个节点,如果页面存储数量已到达极限,则删除双向链表尾端节点并在hashmap中删除该节点的信息,并将新节点插入到链表头部,同时在hashmap中维护该节点信息。
这里面还主要用到了两个操作,一个是在链表中删除原节点,一个是将节点设置为链表头部。
基于上述思想对LRU机制进行了模拟实现,也是leetcode的第146题,由于网上用java版本实现的较多,而笔者刷题时习惯用C++来写题,于是附用C/C++实现的题解。其中Node中的value为页面内容的模拟,链表中删除原节点和设置链表头部的时候要考虑到链表是否为空和首尾的情况。
struct Node{ int key; int value; Node* next; Node* pre; Node(int key,int value): key(key),value(value),next(nullptr),pre(nullptr){} }; class LRUCache { private: int size; Node* head; Node* rear; map<int,Node*> mp; public: LRUCache(int capacity) { this->size = capacity; head=nullptr; rear=nullptr; } int get(int key) { if(mp.count(key)>0){ Node* p = mp[key]; int value = p->value; remove(p); setHead(p); return value; }else{ return -1; } } void put(int key, int value) { if(mp.count(key)>0){ Node* p = mp[key]; p->value = value; remove(p); setHead(p); }else{ Node* p = new Node(key,value); if(mp.size()>=size){ map<int,Node*>::iterator it = mp.find(rear->key); mp.erase(it); remove(rear); } mp[key]=p; setHead(p); } } void remove(Node* p){ if(p==head){ head = p->next; if(head!=nullptr){ head->pre=nullptr; } }else if(p==rear){ rear = p->pre; if(rear!=nullptr){ rear->next=nullptr; } }else{ p->pre->next = p->next; p->next->pre = p->pre; } } void setHead(Node* p){ if(head==nullptr || rear==nullptr){ head=p; rear=p; }else{ p->next=head; head->pre=p; head=p; } } };
- 点赞
- 收藏
- 分享
- 文章举报
相关文章推荐
- C++实现LRU(最久未使用)缓存算法
- c++实现的常见缓存算法和LRU
- LRU、LFU缓存机制的算法设计与实现
- c++中虚多态的实现机制
- C++中事件机制的简洁实现及需要放弃的特性
- JDK动态代理之WeakCache缓存的实现机制
- VC实现C++的类的反射机制
- C++ 采集音频流(PCM裸流)实现录音功能(双缓存版本)
- RxCache 的代码分析,含缓存时间duration的在代码中改变的自己实现的机制
- LRU缓存实现(Java)
- Binder系统_c++实现内部机制代理类BpXXX分析
- Java实现LRU缓存
- Java实现简单的LRU缓存(A Simple LRU Cache in 5 lines)
- C++与Java中多态实现机制的区别
- Android 简单实现缓存机制
- LRU(Least Recently Used)缓存介绍与实现
- C++反射机制:可变参数模板实现C++反射
- C++异常机制的实现方式和开销分析(转载)
- Java简易LRU缓存实现(开发技巧)
- 基于LinkedHashMap实现LRU缓存调度算法原理