LRUCache

#include 
#include 
#include 
#include 
#include 
#include 

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 kvtk_map;

typedef std::map tk_map;

class LRUCache
{
private:
    const int _capacity;

    std::vector 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 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::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 

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)