LRU算法实现

1. LRU简介

        LRU(Least recently used,最近最少使用)是缓存置换策略中的一种常用的算法。其核心思想是“如果数据最近被访问过,那么将来被访问的几率也更高”。当缓存队列已满时,新的元素加入队列时,需要从现有队列中移除一个元素,LRU 策略就是将最近最少被访问的元素移除,从而腾出空间给新的元素。

        当对key进行访问时(一般有查询,更新,增加,在get()和set()两个方法中实现即可)时,将该key放到队列的最前端(或最后端)就行了,这样就实现了对key按其最后一次访问的时间降序(或升序)排列,当向空间中增加新对象时,如果空间满了,删除队尾(或队首)的对象。

2. 算法实现

2.1 普通实现

        借助于普通dict和list来实现,dict保存键值对,list保证插入的有序(借助列表来记录插入的顺序)。

# 基于普通dict和list实现
class LRUCache(object):
    def __init__(self, size=5):
        self.size = size
        self.cache = dict()
        self.key_list = []

    def get(self, key):
        if key in self.cache:
            self.key_list.remove(key)
            self.key_list.insert(0, key)
            return self.cache[key]
        else:
            return None

    def set(self, key, value):
        if key in self.cache:  # 更新
            self.key_list.remove(key)  
        elif len(self.cache) == self.size:  # 删除插入
            old_key = self.key_list.pop()
            self.cache.pop(old_key)
        self.cache[key] = value       # 一般插入
        self.key_list.insert(0, key)

使用hash表来定位结点位置,get()和set()的时间复杂度均为O(1),空间复杂度为O(n)。

2.2 借助OrderedDict

python中有一个标准库的类的OrderedDict(有序字典),该类有以下两个方法用来实现LRU算法就十分简单:

1. popitem(last=True):有序字典的 popitem() 方法移除并返回一个 (key, value) 键值对。 如果 last 值为真,则按 LIFO 后进先出的顺序返回键值对,否则就按 FIFO 先进先出的顺序返回键值对。
 2. move_to_end(key, last=True):将现有 key 移动到有序字典的任一端。 如果 last 为真值(默认)则将元素移至末尾;如果 last 为假值则将元素移至开头。如果 key 不存在则会触发 KeyError。

from collections import OrderedDict, defaultdict
 
class LRU:
    def __init__(self, capacity=128):
        self.capacity = capacity    # 缓存容量
        self.cache = OrderedDict()  # 有序字典缓存
 
    def put(self, key, value):
        if key in self.cache:
            # 若数据已存在,表示命中一次,需要把数据移到缓存队列末端
            self.cache.move_to_end(key)
            return
        if len(self.cache) >= self.capacity:
            # 若缓存已满,则需要淘汰最早没有使用的数据
            self.cache.popitem(last=False)
        # 录入缓存
        self.cache[key]=value
 
    # 遍历key
    def travel(self):
        for key in self.cache.keys():
            print(key)
 
    def get(self, key):
        if key in self.cache:
            val = self.cache.pop(key)
            self.cache[key] = val
        else:
            val = None
 
        return val

3. 测试

test = LRUCache()
test.set('a', 1)
test.set('b', 2)
test.set('c', 3)
test.set('d', 4)
test.set('e', 5)
# test.set('f',6)
print(test.get('a'))
print(test.set('b1', 55))
print(test.get('e'))
print(test.key_list)
for k, v in test.cache.items():
    print(k, "\t", v)

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值