[LeetCode] LRU Cache

本文详细介绍了如何使用双向链表和哈希表实现LRU缓存,包括核心操作get和set的实现细节,以及如何通过访问频率调整缓存元素的位置,确保高效性能。

Design and implement a data structure for Least Recently Used (LRU) cache. It should support the following operations: get and set.

get(key) - Get the value (will always be positive) of the key if the key exists in the cache, otherwise return -1.
set(key, value) - Set or insert the value if the key is not already present. When the cache reached its capacity, it should invalidate the least recently used item before inserting a new item.

 

Hide Tags
  Data Structure
 
 
 

分析
为了使查找、插入和删除都有较高的性能,我们使用一个双向链表 (std::list) 和一个哈希表
(std::unordered_map),因为:
• 哈希表保存每个节点的地址,可以基本保证在 O(1) 时间内查找节点
• 双向链表插入和删除效率高,单向链表插入和删除时,还要查找节点的前驱节点
具体实现细节:
• 越靠近链表头部,表示节点上次访问距离现在时间最短,尾部的节点表示最近访问最少
• 访问节点时,如果节点存在,把该节点交换到链表头部,同时更新 hash 表中该节点的地址
• 插入节点时,如果 cache 的 size 达到了上限 capacity,则删除尾部节点,同时要在 hash 表中删
除对应的项;新节点插入链表头部

 

更多分析见  http://www.cnblogs.com/diegodu/p/4569048.html    http://www.cnblogs.com/dolphin0520/p/3741519.html

struct cacheNode{
   int  key;
   int  val;
   cacheNode(int k, int v)
   {
        key = k;
        val = v;
   }
};


class LRUCache{
    private:
        int m_capacity;
        list<cacheNode> m_list;//double link of cacheNode
        map< int, list<cacheNode>::iterator > m_map; // map of key and list::iterator

    public:
        LRUCache(int capacity)
        {
            m_capacity = capacity;
        }

        int get(int key) {
            if(m_map.find(key) == m_map.end())
            {
                return -1;
            }
            else
            {
                //move the node to head of double list
                list<cacheNode>::iterator it = m_map[key];
                m_list.splice(m_list.begin(), m_list, it);
                return m_list.begin()->val;
            }
        }

        void set(int key, int value)
        {
            if(m_map.find(key) == m_map.end())
            {
                //delete the back one if reach capacity
                if(m_capacity == m_list.size())
                {
                    cacheNode tmp = m_list.back();
                    m_list.pop_back();
                    m_map.erase(tmp.key);
                }
                // insert new one into the head
                cacheNode node(key, value);
                m_list.push_front(node);
                m_map[key]= m_list.begin();
            }
            else
            {
                //move the node to head of double list
                list<cacheNode>::iterator it = m_map[key];
                m_list.splice(m_list.begin(), m_list, it);
                //update value
                m_list.begin()->val = value;

            }

        }

        void printCache()
        {
            for(list<cacheNode>::iterator it = m_list.begin(); it != m_list.end(); it++)
            {
                cout << "key:\t" << it->key <<"\tvalue\t" << it->val <<endl;
            }
            cout << endl;
        }
};


int main()
{
    LRUCache cache(5);
    cache.set(1, 1);
    cache.set(2, 2);
    cache.set(3, 4);
    cache.set(4, 4);
    cache.set(5, 5);
    cache.printCache();
    cache.set(6, 6);
    cache.printCache();
    cache.set(2, 9);
    cache.printCache();
    cache.set(3, 3);
    cache.printCache();
    cache.get(5);
    cache.printCache();
    return 0;
}

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值