LRUCache

#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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值