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