您的位置:首页 > 编程语言 > C语言/C++

LRUCache

2014-01-21 10:37 344 查看
#include <stdexcept>
#include <list>
#include <iostream>
#include <algorithm>
#include <vector>
#include <map>

typedef struct vkt
{
int v;
int k;
unsigned int t;
}vkt_t, *vkt_p;

inline bool time_comp(const vkt_p& l, const vkt_p& r)
{
return l->t < r->t;
}

typedef std::map<int, vkt_p> kvtk_map;

typedef std::map<int, int> tk_map;

class LRUCache
{
private:
const int _capacity;

std::vector<vkt_p> vkt_buf;

vkt_p ori_buf;

kvtk_map kvtk;

tk_map tk;

const unsigned int max_time;

unsigned int guard;

protected:
vkt_p new_vkt(void)
{
if (vkt_buf.empty())
return NULL;
vkt_p p = vkt_buf.back();
vkt_buf.pop_back();
return p;
}

void del_vkt(vkt_p p)
{
vkt_buf.push_back(p);
}

void adjust_time()
{
if (guard >= max_time)
{
tk.clear();

std::list<vkt_p> lv;

for (kvtk_map::const_iterator iter = kvtk.begin(); iter != kvtk.end(); ++iter)
{
lv.push_back(iter->second);
}

lv.sort(time_comp);

int i = 0;

for (kvtk_map::const_iterator iter = kvtk.begin(); iter != kvtk.end(); ++iter)
{
iter->second->t = i++;
}

guard = i;

for (std::list<vkt_p>::const_iterator iter = lv.begin(); iter != lv.end(); ++iter)
{
tk.insert(std::make_pair((*iter)->t, (*iter)->k));
}
}
}

public:
LRUCache(int capacity) : _capacity(capacity + 1), max_time(~0), guard(0)
{
if (capacity <= 0)
throw std::invalid_argument("capacity must > 0");

ori_buf = new vkt_t[_capacity];

vkt_buf.reserve(_capacity);

for (int i = 0; i < _capacity; ++i)
{
vkt_buf.push_back(ori_buf + i);
}
}

~LRUCache() { delete[] ori_buf; ori_buf = NULL; }

int get(int key)
{
kvtk_map::iterator iter = kvtk.find(key);
if (iter == kvtk.end())
return -1;

tk_map::iterator tkiter = tk.find(iter->second->t);
if (tkiter != tk.end())
tk.erase(tkiter);

iter->second->t = guard++;

int v = iter->second->v;

tk.insert(std::make_pair(iter->second->t, key));

adjust_time();

return v;
}

void set(int key, int value)
{
kvtk_map::iterator iter = kvtk.find(key);
if (iter == kvtk.end())
{
vkt_p p = new_vkt();
if (p != NULL)
{
p->v = value; p->k = key; p->t = guard;
iter = kvtk.insert(std::make_pair(key, p)).first;
}
}
if (iter != kvtk.end())
{
tk_map::iterator tkiter = tk.find(iter->second->t);

if (tkiter != tk.end())
tk.erase(tkiter);

iter->second->t = guard++;

iter->second->v = value;

tk.insert(std::make_pair(iter->second->t, key));
}

if (kvtk.size() == _capacity)
{
tk_map::iterator tkiter = tk.begin();

if (tkiter != tk.end())
{
int k = tkiter->second;

tk.erase(tkiter);

kvtk_map::iterator iter = kvtk.find(k);

if (iter != kvtk.end())
{
del_vkt(iter->second);
kvtk.erase(iter);
}
}
}

adjust_time();
}

int size(void) const { return (int)kvtk.size(); }

int old_val(void) const
{
tk_map::const_iterator tkit = tk.begin();

if (tkit != tk.end())
{
kvtk_map::const_iterator kvtkit = kvtk.find(tkit->second);
if (kvtkit != kvtk.end())
return kvtkit->second->v;
}

return -1;
}

int new_val(void) const
{
tk_map::const_reverse_iterator tkit = tk.rbegin();

if (tkit != tk.rend())
{
kvtk_map::const_iterator kvtkit = kvtk.find(tkit->second);
if (kvtkit != kvtk.end())
return kvtkit->second->v;
}

return -1;
}
};

#include <cassert>

int main(int argc, char* argv[])
{
LRUCache lru(10);

assert(-1 == lru.get(0));

for (int i = 0; i < 0xFF0; ++i)
{
lru.set(i, i);
}

assert(lru.size() == 10);

for (int i = 0; i < 100; ++i)
{
lru.set(i, i);
}

assert(lru.size() == 10);

assert(lru.get(5) == -1);

assert(lru.get(95) == 95);

assert(lru.get(100) == -1);

assert(lru.new_val() == 95);

assert(lru.old_val() == 90);

lru.set(4, 10);

assert(lru.new_val() == 10);

assert(lru.old_val() == 91);

assert(lru.get(0) == -1);

lru.set(0, 0);

assert(lru.new_val() == 0);

assert(lru.old_val() == 92);

return 0;
}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  c++ LRU