LRU Cache

設計一個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]
----------


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