Python实现可自定义更新策略的LRU Cache

LRU Cache

  LRU(Least Recently Used),直译为“最近最少使用”,其实称“最久未被使用”更为恰当。这是一个非常重要的算法,在学操作系统的时候第一次遇见,在做leetcode的时候再次遇见,知道是用于做缓存的页面置换。但是LRU不仅仅用于这一个用途,凡是有数据更新策略的应用,LRU都可以是候选算法。比如redis、memcached、oracle等缓存和数据库、或在其它应用场景方面也有类似的需求。总之要达到的目的是:保持新鲜,剔除陈旧,减少交换。
  
- 算法原理
  需求描述:
  实现LRU算法,主要工作是实现LRU Cache的数据结构,或者说实现这种类。lru缓存的主要操作有两个,一个是get,获取数据是否在cache中,如果在,则把该数据放到缓存最前面;另一个的主要操作是set,在缓存中存放某个值,并且存放到最前面,如果缓存中有这个值,则更新,如果缓存满了,则删除缓存中最后面的值。总之,缓存中最前面的值是最近被使用过的,缓存有大小限制,超出要删除最久未被使用的值。要求所有操作时间复杂度均为o(1)。
  分析:
  直觉看上去,数据从近到远以此排列,这是一个线性结构,列表(顺序线性表/数组),链表,队列,栈?
  先考虑目的要求,要求最近使用的在最前,最久未使用的在最后,队列是FIFO的结构,栈是FILO的结构,都不符合要求。
  再考虑数据更新,要求o(1)复杂度下,把数据更新到最前面。列表被排除,无法满足要求。只有链式结构才可以在o(1)下完成更新。
  最后考虑数据查找,链式结构下,数据查找复杂度为o(n),又不能满足o(1)的复杂度。看来必须依赖其它数据结构的辅助。
  用列表完成o(1)的更新,不可能啊,想想看,将数组中一个位置的数挪到最前面,那这个位置之前的数据都要后移一位,怎样都不能实现o(1)的开销。那就考虑链式结构下如果实现o(1)的查找吧。通常情况下,查找链表中一个位置上的值,需要从头结点开始,依次后移查找。如果有尾结点也一样依次向前移动,时间复杂度为o(n)。那么我们能不能将每个结点的位置记下来,直接去存放结点的那个位置查找呢?哈希表派上了用场。哈希表存放结点位置的对应关系,能够满足o(1)下的数据查找,同时链表能够实现o(1)的数据更新,符合预想的要求。
  总结:在Cache结构中,需要一个hash table,用于存放位置关系,需要一个链表,用于更新数据,链表我们使用双向链表。大体结构为:
  这里写图片描述

class LRU:
    var table = {}
    
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答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、付费专栏及课程。

余额充值