LRU的学习和LRU的模拟实现
Posted zhaocx111222333
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LRU的学习和LRU的模拟实现相关的知识,希望对你有一定的参考价值。
LRU是什么
LRU是Least Recently Used的缩写,意思是最近最少未使用,它是一种Cache替换算法。
广义上的Cache指的是位于速度相差较大的两种硬件之间, 用于协调两者数据传输速度差异的结构。
LRU在缺页中断中利用广泛,每次访问一个页,就会把页数放入一个数据结构,当数据结构满了就会淘汰掉最近最少未使用的页数,这个数据结构可以保证最新被访问的数据在最开始的位置。
图片来自网络。
组织结构
这样一个数据结构要保持高效实现O(1)的put和get,可以使用使用双向链表+哈希表来实现。是因为双向链表可以实现任意位置O(1)的插入和删除,使用哈希表是因为哈希表的增删查改也是O(1)
使用双向链表来作为存储结构存储具体的数据
list<pair<int, int>>
利用存储键值对高效控制链表
利用哈希映射链表的迭代器实现链表的高效查找
哈希表的结构就是
unordered_map<int, list<pair<int, int>>::iterator>
Key就是用来记录插入的信息,而Value则是该节点对应链表的迭代器,可以通过Key高效的获取这个节点在链表的位置。
实现和详细注释
#include<iostream>
#include<list>
#include<unordered_map>
using namespace std;
class LRU {
public:
LRU(int capacity) {
_capacity = capacity;
}
//根据Key高效获取Value,这里也代表访问
int get(int key) {
auto hashit = _hashmap.find(key);
if (hashit != _hashmap.end()) //存在就刷新位置并返回Value
{
auto listit = hashit->second;
pair<int, int> kv = *listit;
_list.erase(listit);
_list.push_front(kv);
_hashmap[key] = _list.begin(); //更新哈希表迭代器
return kv.second;
}
else
{
return -1;
}
}
void Push(int key, int value) {
// 1.如果数据不存在则进行插入
//(判断容量是否满)满了需要链表尾删,哈希表删除
//不满就直接尾插
// 2.如果数据存在则进行数据更新到链表头
auto hashit = _hashmap.find(key); //获取迭代器
if (hashit == _hashmap.end()) //数据不存在
{
if (_list.size() >= _capacity)
{
_hashmap.erase(_list.back().first); //拿到链表尾的Key删除哈希表
_list.pop_back(); //链表尾删
}
_list.push_front(make_pair(key, value));
_hashmap[key] = _list.begin(); //获取迭代器并插入哈希表
}
else
{
auto listit = hashit->second; //拿到即将被删除的迭代器
pair<int, int> kv = *listit; //不用make_pair,用旧的赋值改value也行
kv.second = value; //修改迭代器的value
_list.erase(listit);
_list.push_front(kv);
_hashmap[key] = _list.begin();
}
}
private:
list<pair<int, int>> _list;
unordered_map<int, list<pair<int, int>>::iterator> _hashmap;
size_t _capacity; //需要指定该结构的容量大小
};
以上是关于LRU的学习和LRU的模拟实现的主要内容,如果未能解决你的问题,请参考以下文章