leetcode-LRUCache的解

因为要频繁执行查询插入删除等操作,所以考虑用hash表来做。

为了实现LRU,可以根据数据的最后使用时间维护一个堆,查找和调整都是O(lgn) ,没有试过,不知道想法对不对。 

我采用的是双链表+map的办法,在表头插,表尾删。

class LRUCacheValue;
typedef pair<const int, LRUCacheValue> VTYPE;
class LRUCacheValue
{
public:
    VTYPE * next;
    VTYPE * prev;
    LRUCacheValue(int v);
    LRUCacheValue():value(-1), next(NULL), prev(NULL){}
    ~LRUCacheValue(){}
    int getValue() const;
    void setValue(int v);
private:
    int value;
};
LRUCacheValue::LRUCacheValue(int v):value(v), next(NULL), prev(NULL)
{
}
int LRUCacheValue::getValue() const
{
    return value;
}
void LRUCacheValue::setValue(int v)
{
    value = v;
}
class LRUCache{
public:
    typedef map<int, LRUCacheValue> MAP;
    LRUCache(int capacity) {
        _capacity = capacity;
        vmap.clear();
        head = NULL;
        tail = NULL;
    }
    int get(int key)
    {
        MAP::iterator it = vmap.find(key);
        if(it != vmap.end())
        {
            int ret = it->second.getValue();
            update(it, ret);
            return ret;
        }
        return -1;
    }
    void set(int key, int value) {
        MAP::iterator it = vmap.find(key);
        if(it != vmap.end())
        {
            update(it, value);
        }
        else
            insert(key, value);
    }
    void update(MAP::iterator it, int value)
    {
        VTYPE *v = &*it;
        VTYPE *pre = v->second.prev;
        VTYPE *nex = v->second.next;
        v->second.setValue(value);
        if(pre != NULL)
        {
            pre->second.next = nex;
            v->second.next = head;
            head->second.prev = v;
            v->second.prev = NULL;
            head = v;
            if(nex != NULL)
                nex->second.prev = pre;
            else
            {
                tail = pre;
            }
        }
    }
    void insert(int key, int value)
    {
        if(vmap.size() >= _capacity)
        {
            VTYPE * old = tail;
            VTYPE* p = tail->second.prev;
            if(p != NULL)
            {
                p->second.next = NULL;
                tail = p;
            }
            vmap.erase(old->first);
        }
        pair<MAP::iterator, bool> ret = vmap.insert(make_pair(key, LRUCacheValue(value)));
        VTYPE *inserted = &*ret.first;
        if(head != NULL)
        {
            head->second.prev = inserted;
            inserted->second.next = head;
            head = head->second.prev;
        }
        else
            head = inserted;
        if(tail == NULL)
            tail = head;
    }
private:
    unsigned int _capacity;
    MAP vmap;
    VTYPE* head;
    VTYPE* tail;
};

有一点之前没有注意的是,查询也应该更新查询到的元素在链表中的位置。

点赞