欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

C++ 基于List与Map实现的LRU缓存

程序员文章站 2022-05-20 21:34:16
...

常见的缓存淘汰算法有先进先出淘汰算法(FIFO),最近最少使用淘汰算法(LSU),最近最久未使用算法(LRU),MRU(最近最常使用算法)。其中最常用的就是LRU缓存淘汰算法,下面给出代码实现。


#include "stdafx.h"
#include <iostream>
#include <map>
#include <list>
using namespace std;

template<typename TKey, typename TValue>
class SimpleLRUCache
{
private:
	int m_iMaxSize;
	list<TKey> m_listLru; // 保存Key的链表,维护访问顺序
	
	typedef pair<typename list<TKey>::iterator, TValue> MPair;
	typedef shared_ptr<MPair> PairPtr; //保证资源释放
	map<TKey, PairPtr> m_mapPair; // 保存Key在链表中的位置和Key对应的Value

public:
	SimpleLRUCache(int iMaxSize)
	{
		m_iMaxSize = iMaxSize;
	}

	bool Contain(TKey& szKey)
	{
		auto iterFind = m_mapPair.find(szKey);
		if (iterFind == m_mapPair.end())
			return false;
		return true;
	}

	bool Get(TKey& szKey, TValue &rValue)
	{
		auto iterFind = m_mapPair.find(szKey);
		if (iterFind == m_mapPair.end())
			return false;

		rValue = iterFind->second->second;

		//	访问后移至链表头部
		auto iterList = iterFind->second->first;
		m_listLru.erase(iterList);
		m_listLru.push_front(iterFind->first);
		iterFind->second->first = m_listLru.begin();

		return true;
	}

	bool Put(TKey& szKey, TValue& szValue)
	{
		if (Contain(szKey))
			return false;

		//	在链表的头部插入
		m_listLru.push_front(szKey);
		auto iterFront = m_listLru.begin();
		PairPtr pairPtr = make_shared<MPair>(iterFront, szValue);
		m_mapPair.insert(make_pair(szKey, pairPtr));

		//	判断缓存容量是否超过最大值
		if (m_listLru.size() > m_iMaxSize)
		{
			//	移除最久未被访问元素
			auto myKey = m_listLru.back();
			Remove(myKey);
		}

		return true;
	}

	bool Remove(TKey &szKey)
	{
		auto iterFind = m_mapPair.find(szKey);
		if (iterFind == m_mapPair.end())
			return false;
		auto iterList = iterFind->second->first;
		m_listLru.erase(iterList);
		m_mapPair.erase(iterFind);

		cout << "Remove key" << szKey << endl;

		return true;
	}
};


int main()
{
	SimpleLRUCache<int, int> lruCache(10);

	for (int i = 0; i < 13; i++)
	{
		lruCache.Put(i, i);
	}

	int iVal;
	bool bGet;
	for (int i = 12; i >=0; i--)
	{
		bGet = lruCache.Get(i, iVal);
		if (bGet)
		{
			cout << "Get key=" << i << ", val=" << iVal << endl;
		}
	}

    return 0;
}

核心设计思想:

1、使用链表维护访问顺序

2、使用map加速查找

相关标签: 数学与算法