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

 

时间: 2024-10-24 17:30:14

LRU Cache的相关文章

LeetCode: LRU Cache 最近最少使用算法 缓存设计

设计并实现最近最久未使用(Least Recently Used)缓存.   题目描述: 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

[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

哪个Map最适合用来实现LRU Cache?

问题描述 前段时间面试碰到的一道题,最近进了这家公司了,再拿出来看看.求大神继续解脱.30.下面哪个Map最适合用来实现LRUCache?A.HashtableB.TreeMapC.HashMapD.IdentityHashMapE.WeakHashMap网上给的答案是A.为什么?大家一般如何实现这个最近最少使用cache? 解决方案 解决方案二:就那几个可选的来说只能是A了因为是线程安全的不过个人认为应该用Mapmap=Collections.synchronizedMap(newLinked

Redis作为LRU Cache的实现

公有云Redis服务:https://www.aliyun.com/product/kvstore?spm=5176.8142029.388261.37.59zzzj 背景 Redis作为目前最流行的KV内存数据库,也实现了自己的LRU(Latest Recently Used)算法,在内存写满的时候,依据其进行数据的淘汰.LRU算法本身的含义,这里不做赘述,严格的LRU算法,会优先选择淘汰最久没有访问的数据,这种实现也比较简单,通常是用一个双向链表+一个哈希表来实现O(1)的淘汰和更新操作.但

关于LRU缓存的实现算法讨论

业务模型 读.写.删的比例大致是7:3:1,至少要支持500w条缓存,平均每条缓存6k,要求设计一套性能比较好 的缓存算法. 算法分析 不考虑MemCached,Velocity等现成的key-value缓存方案,也不考虑脱离.NET gc自己管理内存,不考 虑随机读取数据及顺序读取数据的场景,目前想到的有如下几种LRU缓存方案 算法 分析 SortedDictionary .NET自带的,内部用二叉搜索树(应该不是普通树,至少是做过优化的树)实现的,检索为O (log n),比普通的Dicti

Python实现LRU算法的2种方法

  这篇文章主要介绍了Python实现LRU算法的2种方法,本文分别给出了用OrderedDict实现.用dict+list实现两种方法,需要的朋友可以参考下 LRU:least recently used,最近最少使用算法.它的使用场景是:在有限的空间中存储对象时,当空间满时,会按一定的原则删除原有的对象,常用的原则(算法)有LRU,FIFO,LFU等.在计算机的Cache硬件,以及主存到虚拟内存的页面置换,还有Redis缓存系统中都用到了该算法.我在一次面试和一个笔试时,也遇到过这个问题.

Redis近似LRU算法优化

公有云Redis服务:https://www.aliyun.com/product/kvstore?spm=5176.8142029.388261.37.59zzzj 背景 在前一篇文章<Redis作为LRU Cache的实现>中,我们看到了在Redis 2.8.19中LRU算法的具体实现,Redis使用了24 bit的lru时间戳来模拟一个近似的LRU算法,节省了实现一个严格LRU算法所需要的大量内存空间. 但是,上篇文章我们也挖了一个坑,说过现有的近似算法模拟效果还有待提高,今天这篇文章就

java中利用spring cache解耦业务中的缓存

虽然以前实现缓存的方式,是定义了缓存操作接口,可以灵活实现不同的缓存,可毕竟精力有限,要完成不同的缓存实现也是件麻烦的事.更要命的是,业务代码中有大量缓存操作的代码,耦合度太高,看着很不优雅. 所以呢,抽空了解了一下其它实现方案.这不,spring3.1开始,支持基于注解的缓存,算是目前我比较可以接受的一种方案吧.学完之后还是做一下笔记吧. spring cache是一套基于注解实现的缓存技术,其本身是并不是具体实现,不过默认实现了ConcurrentMap和EHCache实现的缓存.当然也是支

java LRU(Least Recently Used )详解及实例代码_java

java LRU(Least Recently Used )详解 LRU是Least Recently Used 的缩写,翻译过来就是"最近最少使用",LRU缓存就是使用这种原理实现,简单的说就是缓存一定量的数据,当超过设定的阈值时就把一些过期的数据删除掉,比如我们缓存10000条数据,当数据小于10000时可以随意添加,当超过10000时就需要把新的数据添加进来,同时要把过期数据删除,以确保我们最大缓存10000条,那怎么确定删除哪条过期数据呢,采用LRU算法实现的话就是将最老的数据