#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;
}
LRUCache
最新推荐文章于 2024-01-18 23:10:44 发布