設計一個LRU cache, 如果想時間複雜度O(1), 則必須用到hash.
這裏有一個使用STL實現的lru cache 模板類源碼
LRU cache implementation in C++
http://timday.bitbucket.org/lru.html?1364610172
下面是自己隨便寫的一個lru測試程序, 邏輯驗證正確.
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <arpa/inet.h>
#include <sstream>
#include <vector>
#include <list>
#include <map>
#include <ext/hash_map>
#include <list>
#include <unistd.h> // for usleep
using namespace std;
using namespace __gnu_cxx;
#ifndef foreach
#define foreach(container,it) \
for(typeof((container).begin()) it = (container).begin();it!=(container).end();++it)
#endif
struct DataValue
{
string ss;
int appid;
string Info()
{
char buf[128];
snprintf(buf, sizeof(buf), "[ss:%s, appid:%d]", ss.c_str(), appid);
return buf;
}
};
int MakeValue(int appid, DataValue& v)
{
v.ss = "hello";
v.appid = appid;
return 0;
}
typedef int (*make_value_pt)(int, DataValue&);
class CLRU
{
public:
CLRU(make_value_pt fn, int cache_size):
_fn_make_value(fn),
CACHE_SIZE(cache_size)
{}
public:
void get(int appid, DataValue& dv)
{
// 如果key已經存在, 把key移動到隊tail
if (key_map.find(appid) != key_map.end())
{
key_lru_list.splice(key_lru_list.end(), key_lru_list, key_map[appid].second);
dv = key_map[appid].first;
}
// if not exiest
else
{
// if cash size is full, evict
if (key_lru_list.size() >= (unsigned int)CACHE_SIZE)
{
key_map.erase(key_lru_list.front());
key_lru_list.erase(key_lru_list.begin());
}
// make a value for key
_fn_make_value(appid, dv);
// insert
key_lru_list.push_back(appid);
key_map[appid] = pair<DataValue, list<int>::iterator>(dv, --key_lru_list.end());
}
}
// just for debug
void output()
{
foreach(key_lru_list, it)
{
int appid = *it;
printf("appid:%u, dv:%s\n",
appid, key_map[appid].first.Info().c_str());
}
}
public:
list<int> key_lru_list;
hash_map<int, pair<DataValue, list<int>::iterator> > key_map;
make_value_pt _fn_make_value;
int CACHE_SIZE;
};
int main()
{
CLRU lru(MakeValue, 3);
DataValue dv;
lru.get(1, dv);
printf("dv:%s\n", dv.Info().c_str());
lru.output();
printf("----------\n");
lru.get(2, dv);
printf("dv:%s\n", dv.Info().c_str());
lru.output();
printf("----------\n");
lru.get(3, dv);
printf("dv:%s\n", dv.Info().c_str());
lru.output();
printf("----------\n");
lru.get(4, dv);
printf("dv:%s\n", dv.Info().c_str());
lru.output();
printf("----------\n");
lru.get(3, dv);
printf("dv:%s\n", dv.Info().c_str());
lru.output();
printf("----------\n");
return 0;
}
輸出如下:dv:[ss:hello, appid:1]
appid:1, dv:[ss:hello, appid:1]
----------
dv:[ss:hello, appid:2]
appid:1, dv:[ss:hello, appid:1]
appid:2, dv:[ss:hello, appid:2]
----------
dv:[ss:hello, appid:3]
appid:1, dv:[ss:hello, appid:1]
appid:2, dv:[ss:hello, appid:2]
appid:3, dv:[ss:hello, appid:3]
----------
dv:[ss:hello, appid:4]
appid:2, dv:[ss:hello, appid:2]
appid:3, dv:[ss:hello, appid:3]
appid:4, dv:[ss:hello, appid:4]
----------
dv:[ss:hello, appid:3]
appid:2, dv:[ss:hello, appid:2]
appid:4, dv:[ss:hello, appid:4]
appid:3, dv:[ss:hello, appid:3]
----------