zoukankan      html  css  js  c++  java
  • [LeetCode] LRU Cache

    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:	" << it->key <<"	value	" << 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;
    }
  • 相关阅读:
    Android SDK manager 无法更新解决方法
    platform_set_drvdata的源码分析
    从一个男人身上看出他的修养和抱负
    更换RAID1硬盘过程记录
    无线路由器连接有线路由器设置
    在ASP.NET下实现数字和字符相混合的验证码 (转载)
    不走寻常路 设计ASP.NET应用程序的七大绝招
    .NET 2005 使用MasterPages实现Web窗体模板
    用Visual C# 实现四则混合运算(转载)
    如何实施好CRM (转载)
  • 原文地址:https://www.cnblogs.com/diegodu/p/4599607.html
Copyright © 2011-2022 走看看