LRUCache的原理及实现(C++)


LRUCache的原理

LRU是Least Recently Used的缩写,意思是最近最少使用,它是一种Cache替换算法。 什么是
Cache?狭义的Cache指的是位于CPU和主存间的快速RAM, 通常它不像系统主存那样使用
DRAM技术,而使用昂贵但较快速的SRAM技术。 广义上的Cache指的是位于速度相差较大的两种
硬件之间, 用于协调两者数据传输速度差异的结构。除了CPU与主存之间有Cache, 内存与硬盘
之间也有Cache,乃至在硬盘与网络之间也有某种意义上的Cache── 称为Internet临时文件夹或
网络内容缓存等。

Cache的容量有限,因此当Cache的容量用完后,而又有新的内容需要添加进来时, 就需要挑选
并舍弃原有的部分内容,从而腾出空间来放新内容。LRU Cache 的替换原则就是将最近最少使用
的内容替换掉
。其实,LRU译成最久未使用会更形象, 因为该算法每次替换掉的就是一段时间内
最久没有使用过的内容。


LRUCache的实现

首先需要考虑的是数据结构,需要用一个结构来保存数据,另一个来记录使用的顺序。对于记录顺序的结构,因为可能存在大量的插入以及移动,为了能够保证其插入删除的效率一直在O(1),所以需要用到链表。而为了能够实现O(1)的查找,存储结构需要用到哈希,并且为了能够保证更新顺序时能够O(1)找到链表中对应的结点,还需要保存其迭代器作为哈希的value。
在这里插入图片描述

//利用哈希表来存储数据以及迭代器,来实现o(1)的查找
unordered_map<int, list<pair<int, int>>::iterator> _hashmap;
//利用双向链表来保存缓存使用情况,并保证o(1)的插入删除
list<pair<int, int>> _lrulist;
size_t _capacity;

具体的思路我都写在了注释中

#include<unordered_map>
#include<list>

using namespace std;

class LRUCache
{
public:
	LRUCache(size_t capacity)
		: _capacity(capacity)
	{}

	int get(int key) 
	{
		auto ret = _hashmap.find(key);

		//查找成功
		if (ret != _hashmap.end())
		{
			//获取数据的位置
			list<pair<int, int>>::iterator pos = ret->second;
			pair<int, int> kv = *pos;

			//将数据移动到队首
			_lrulist.erase(pos);
			_lrulist.push_front(kv);

			ret->second = _lrulist.begin();

			return kv.second;
		}
		//查找失败返回-1
		else
		{
			return -1;
		}
	}

	void put(int key, int value) 
	{
		//首先判断数据是否存在,来判定是插入还是更新
		auto ret = _hashmap.find(key);

		//如果数据存在,则是更新
		if (ret != _hashmap.end())
		{
			list<pair<int, int>>::iterator pos = ret->second;
			_lrulist.erase(pos);

			_lrulist.push_front(make_pair(key, value));
			ret->second = _lrulist.begin();
		}
		//不存在则是删除
		else
		{
			//数据已满
			if (_lrulist.size() == _capacity)
			{
				//删除最久未使用的数据
				pair<int, int> back = _lrulist.back();
				_lrulist.pop_back();
				_hashmap.erase(back.first);
			}
			//插入数据
			_lrulist.push_front(make_pair(key, value));
			_hashmap.insert(make_pair (key, _lrulist.begin()));
		}
	}

private:
	//利用哈希表来存储数据以及迭代器,来实现o(1)的get和put
	unordered_map<int, list<pair<int, int>>::iterator> _hashmap;
	//利用双向链表来保存缓存使用情况,并保证o(1)的插入删除
	list<pair<int, int>> _lrulist;
	size_t _capacity;
};

猜你喜欢

转载自blog.csdn.net/qq_35423154/article/details/107876954
今日推荐