LRU cache 算法的实现

什么是LRU

LRU Cache是一个Cache置换算法,含义是“最近最少使用”,当Cache满(没有空闲的cache块)时,把满足“最近最少使用”的数据从Cache中置换出去,并且保证Cache中第一个数据是最近刚刚访问的。由“局部性原理”,这样的数据更有可能被接下来的程序访问。

LRU基本算法

要求

  1. 提供两个接口:一个获取数据int get(int key),一个写入数据void set(int key, int value)
  2. 无论获取数据还是写入数据,这个数据要保持在最容易访问的位置。
  3. 缓存的数据大小有限,当缓存满时置换出最长时间没有被访问的数据,否则直接把数据加入缓存即可。

算法

  1. 使用list来保存缓存数据的访问序列,头指针指向刚刚访问过的数据

  2. 使用map保存数据的key数据所在链表中的位置。map主要用于加速查找(log(n)的时间复杂度)。

  3. 每次获取数据时,遍历map判断数据(使用数据的key)是否在缓存中,在则返回数据(存在则通过数据所在链表中的位置返回数据值);不在则返回-1。

  4. 每次写入新的数据时,可能有三种情况:

    1. 数据已在缓存中
      遍历map判断数据是否已在缓存中,在则更新数据值,并置数据缓存在链表头
    2. 数据不在缓存中,缓存已满
      剔除掉链表末尾的数据和map指定的数据key,并把新的数据加入到缓存链表的头,并更新map
    3. 数据不在缓存中,缓存未满
      直接把新的数据加入到缓存链表的头,并更新map

LRU实现

实现方案:使用stl的map和list
这里map使用unordered_map(hashmap)+list(双向链表),因此本质上使用hashmap和双向链表

class LRUCache{
    int m_capacity;
    
    //m_map_iter->first: key, m_map_iter->second: list iterator;
    unordered_map<int,  list<pair<int, int>>::iterator> m_map; 
    
    //m_list_iter->first: key, m_list_iter->second: value;
    list<pair<int, int>> m_list;                              
public:
    LRUCache(int capacity): m_capacity(capacity) {
      
    }
    
    int get(int key) {
        auto found_iter = m_map.find(key);
        // key 不存在
        if (found_iter == m_map.end()) 
            return -1;
        
        // key存在时,更新list的key所在节点的位置为list第一元素
        m_list.splice(m_list.begin(), m_list, found_iter->second); 
        
        return found_iter->second->second; 
    }
    
    void set(int key, int value) {
        auto found_iter = m_map.find(key);
        // key存在
        if (found_iter != m_map.end()) 
        {
            // 移动key所在list中的位置
            m_list.splice(m_list.begin(), m_list, found_iter->second); 
            // 更新值
            found_iter->second->second = value; 
            return;
        }
        // 缓存已满且key不存在,删除list中最后一个节点,并从map中删除该key;
        // 注意:这里就是为什么list存储的是key和value 键值对的原因,需要删除map中指定key
        if (m_map.size() == m_capacity) 
        {
           int key_to_del = m_list.back().first; 
           m_list.pop_back();           
           m_map.erase(key_to_del);  
        }
        // 缓存不满,list把key和value加入到list的第一个位置,并存储到map中
        m_list.emplace_front(key, value); 
        m_map[key] = m_list.begin();      
    }
};

涉及的数据结构

  1. std::map:主要用于实现快速访问(logn),存储key对应的list的位置信息,这里对应key对应list的迭代器
  2. std::list:主要用于存储key和value值
### 回答1: 使用Python编写LRU缓存算法的一个简单实现可以如下:def lru_cache(maxsize): cache = {} queue = [] def wrapper(func): def inner(*args, **kwargs): key = str(args) + str(kwargs) if key in cache: return cache[key] result = func(*args, **kwargs) if len(queue) >= maxsize: del cache[queue.pop(0)] cache[key] = result queue.append(key) return result return inner return wrapper使用Python编写LRU缓存算法的一个简单实现可以如下:def lru_cache(maxsize): cache = {} queue = [] def wrapper(func): def inner(*args, **kwargs): key = str(args) + str(kwargs) if key in cache: return cache[key] result = func(*args, **kwargs) if len(queue) >= maxsize: del cache[queue.pop(0)] cache[key] = result queue.append(key) return result return inner return wrapper答:使用Python编写LRU缓存算法的一个简单实现可以如下:def lru_cache(maxsize): cache = {} queue = [] def wrapper(func): def inner(*args, **kwargs): key = str(args) + str(kwargs) if key in cache: return cache[key] result = func(*args, **kwargs) if len(queue) >= maxsize: del cache[queue.pop(0)] cache[key] = result queue.append(key) return result return inner return wrapper用Python编写LRU缓存算法是可行的,通过使用上面提供的简单实现可以实现这一功能。 ### 回答2: LRU(Least Recently Used)算法是一种常用的缓存替换策略,它根据数据节点的使用顺序来决定是否将数据从缓存中删除。当缓存已满,需要替换一个节点时,LRU算法选择最近最少使用的数据节点进行替换。 下面是通过Python实现一个简单的LRU Cache算法: ```python class LRUCache: def __init__(self, capacity): self.capacity = capacity self.cache = {} self.keys = [] def get(self, key): if key in self.cache: self.keys.remove(key) self.keys.append(key) # 更新使用顺序 return self.cache[key] else: return -1 def put(self, key, value): if key in self.cache: self.keys.remove(key) self.keys.append(key) # 更新使用顺序 self.cache[key] = value else: if len(self.keys) >= self.capacity: # 删除最近最少使用的数据节点 del_key = self.keys[0] del self.cache[del_key] self.keys = self.keys[1:] self.keys.append(key) # 更新使用顺序 self.cache[key] = value ``` 在这个实现中,我们使用一个字典 `cache` 来保存数据节点的键值对,并使用列表 `keys` 来记录数据节点的使用顺序。`capacity` 参数指定了缓存的最大容量。 在 `get` 方法中,如果需要获取的 `key` 存在于缓存中,我们首先从 `keys` 列表中移除 `key`,然后将其添加到列表的末尾,以表示最近使用过。然后返回对应的值。如果 `key` 不存在于缓存中,返回 -1。 在 `put` 方法中,如果需要插入的 `key` 已经存在于缓存中,我们同样要将其移除并重新添加到 `keys` 列表的末尾,并更新对应的值。否则,如果缓存已满,我们删除 `keys` 列表的第一个元素,然后从 `cache` 字典中删除对应的键值对。最后,将新的 `key` 和 `value` 添加到 `keys` 列表和 `cache` 字典中。 这样,我们就实现了一个简单的LRU Cache算法。 ### 回答3: LRU缓存(Least Recently Used,最近最少使用)是一种常用的缓存算法,它根据数据的使用历史来决定哪些数据应该保留在缓存中。当缓存达到最大容量时,如果有新数据要放入缓存中,那么就需要删除最久未使用的数据。 下面是用Python实现LRU缓存算法的示例代码: ```python class LRUCache: def __init__(self, capacity: int): self.capacity = capacity self.cache = {} self.order = [] def get(self, key: int) -> int: if key in self.cache: self.order.remove(key) self.order.append(key) return self.cache[key] else: return -1 def put(self, key: int, value: int) -> None: if key in self.cache: self.order.remove(key) elif len(self.cache) >= self.capacity: oldest_key = self.order.pop(0) del self.cache[oldest_key] self.cache[key] = value self.order.append(key) ``` 以上代码中,LRUCache类是实现LRU缓存算法的主要类。它有三个主要成员变量:capacity表示缓存的容量,cache是一个字典,用于存储缓存数据,order是一个列表,用于记录数据的访问顺序。 `get`方法用于从缓存中获取指定的键对应的值。如果键存在于缓存中,就将该键移到最后,表示最近使用过,然后返回该键对应的值;否则返回-1。 `put`方法用于向缓存中添加新的键值对。如果键已经存在于缓存中,就将该键移到最后,表示最近使用过,然后更新该键对应的值;如果缓存已满,就删除最久未使用的键值对;最后在缓存中添加新的键值对,并将该键添加到order列表的最后。 这样通过LRUCache类,我们可以轻松实现一个LRU缓存,并且保证缓存的容量不会被超出。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值