C++ 基於List與Map實現的LRU緩存

常見的緩存淘汰算法有先進先出淘汰算法(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加速查找

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章