zoukankan      html  css  js  c++  java
  • 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.

    参考:http://www.cnblogs.com/TenosDoIt/p/3417157.html

    题目大意:设计一个用于LRU cache算法的数据结构。 题目链接。关于LRU的基本知识可参考here

    分析:为了保持cache的性能,使查找,插入,删除都有较高的性能,我们使用双向链表(std::list)和哈希表(std::unordered_map)作为cache的数据结构,因为:

    • 双向链表插入删除效率高(单向链表插入和删除时,还要查找节点的前节点)
    • 哈希表保存每个节点的地址,可以基本保证在O(1)时间内查找节点

    具体实现细节:

    • 越靠近链表头部,表示节点上次访问距离现在时间最短,尾部的节点表示最近访问最少
    • 查询或者访问节点时,如果节点存在,把该节点交换到链表头部,同时更新hash表中该节点的地址
    • 插入节点时,如果cache的size达到了上限,则删除尾部节点,同时要在hash表中删除对应的项。新节点都插入链表头部。     

    C++实现代码:

    #include<unordered_map>
    #include<list>
    #include<iostream>
    using namespace std;
    
    struct CacheNode
    {
        int key;
        int value;
        CacheNode(int k,int v):key(k),value(v) {}
    };
    class LRUCache
    {
    public:
        LRUCache(int capacity)
        {
            size=capacity;
        }
    
        int get(int key)
        {
            auto iter=cacheMap.find(key);
            if(iter!=cacheMap.end())
            {
                cacheList.splice(cacheList.begin(),cacheList,iter->second);
                cacheMap[key]=cacheList.begin();
                return cacheMap[key]->value;
            }
            return -1;
        }
    
        void set(int key, int value)
        {
            auto iter=cacheMap.find(key);
            if(iter!=cacheMap.end())
            {
                cacheMap[key]->value=value;
                cacheList.splice(cacheList.begin(),cacheList,cacheMap[key]);
                cacheMap[key]=cacheList.begin();
            }
            else
            {
                if(size==(int)cacheList.size())
                {
                    //记得要先删除map中的元素,然后再删除list中的地址,不然map中的地址无效,有可能指向后来插入的元素
                    cacheMap.erase(cacheList.back().key);
                    cacheList.pop_back();
                }
                cacheList.push_front(CacheNode(key,value));
                cacheMap[key]=cacheList.begin();
            }
        }
    private:
        int size;
        unordered_map<int,list<CacheNode>::iterator> cacheMap;
        list<CacheNode> cacheList;
    };
    
    int main(){
        LRUCache lru_cache(1);
        lru_cache.set(2,1);
        cout<<lru_cache.get(2)<<endl;
        lru_cache.set(3,2);
        cout<<lru_cache.get(2)<<endl;
        cout<<lru_cache.get(3)<<endl;
    }
  • 相关阅读:
    ADB命令大全
    Backup your Android without root or custom recovery -- adb backup
    Content portal for Pocketables Tasker articles
    Is there a way to detect if call is in progress? Phone Event
    Tasker to proximity screen off
    Tasker to detect application running in background
    Tasker to create toggle widget for ES ftp service -- Send Intent
    Tasker to proximity screen on
    Tasker to answer incoming call by pressing power button
    Tasker to stop Poweramp control for the headset while there is an incoming SMS
  • 原文地址:https://www.cnblogs.com/wuchanming/p/4123799.html
Copyright © 2011-2022 走看看