【python刷题】LRU
| 什么是LRU? |
LRU是Least Recently Used的缩写,即最近最少使用,是一种常用的页面置换算法,选择最近最久未使用的页面予以淘汰。该算法赋予每个页面一个访问字段,用来记录一个页面自上次被访问以来所经历的时间 t,当须淘汰一个页面时,选择现有页面中其 t 值最大的,即最近最少使用的页面予以淘汰。
我们需要记住以下几点就行了:这里以队列为例
- 要设置一个容量,比如我们设置队列的长度为2;
- 当进来一个元素,比如('a',1),插入到列表中[('a',1)],再进来一个('b',2),插入到列表中,[('a',1),('b',2)],再进来一个('c',3),此时列表已满,这时我们要将最久未被使用的元素删除,也就是('a','1'),再将新元素插入到列表中,[('b',2),('c',3)];
- 假设这时我们使用了('b','2'),那么当前元素就是我们最近使用过的了,队列就变为[('c',3),('b',2)],下次再添加一个新的元素的时候就是优先将('c','3')移除了;
- 我们要保证删除和插入的时间复杂度为O(1),因此要使用字典,而且字典中的元素要是有序的,因此使用python自带的OrderedDict;
- 进一步的是,假设我们要自己实现底层,那么使用的结果就是hash双向链表,这样查找、删除、插入的时间复杂度就都是O(1);
| 方法一:列表模拟 |
class LRUCache:
#@param capacity,an integer
def __init__(self,capacity):
self.cache ={}
self.used_list=[]
self.capacity = capacity
#@return an integer
def get(self,key):
if key in self.cache:
#使用一个list来记录访问的顺序,最先访问的放在list的前面,最后访问的放在list的后面,故cache已满时,则删除list[0],然后插入新项;
if key != self.used_list[-1]:
self.used_list.remove(key)
self.used_list.append(key)
return self.cache[key]
else:
return -1
def set(self,key,value):
if key in self.cache:
self.used_list.remove(key)
elif len(self.cache) == self.capacity:
self.cache.pop(self.used_list.pop(0))
self.used_list.append(key)
self.cache[key] = value
| 方法二:有序字典模拟 |
import collections
# 基于orderedDict实现
class LRUCache(collections.OrderedDict):
'''
function:利用collection.OrdereDict数据类型实现最近最少使用的算法
OrdereDict有个特殊的方法popitem(Last=False)时则实现队列,弹出最先插入的元素
而当Last=True则实现堆栈方法,弹出的是最近插入的那个元素。
实现了两个方法:get(key)取出键中对应的值,若没有返回None
set(key,value)更具LRU特性添加元素
'''
def __init__(self, size=2):
self.size = size
self.cache = collections.OrderedDict() # 有序字典
def get(self, key):
if key in self.cache.keys():
# 因为在访问的同时还要记录访问的次数(顺序)
value = self.cache.pop(key)
# 保证最近访问的永远在list的最后面
self.cache[key] = value
return value
else:
value = None
return value
def set(self, key, value):
if key in self.cache.keys():
self.cache.pop(key)
self.cache[key] = value
elif self.size == len(self.cache):
self.cache.popitem(last=False)
self.cache[key] = value
else:
self.cache[key] = value
测试小例子:
if __name__ == '__main__':
test = LRUCache()
test.set('a', 1)
print(test.cache)
test.set('b', 2)
print(test.cache)
test.set('c', 3)
print(test.cache)
test.set('d', 4)
print(test.cache)
test.set('e', 5)
print(test.cache)
# test.set('f',6)
t1 = test.get('d')
print(t1)
print(test.cache)
结果:
OrderedDict([('a', 1)])
OrderedDict([('a', 1), ('b', 2)])
OrderedDict([('a', 1), ('b', 2), ('c', 3)])
OrderedDict([('b', 2), ('c', 3), ('d', 4)])
OrderedDict([('c', 3), ('d', 4), ('e', 5)])
4
OrderedDict([('c', 3), ('e', 5), ('d', 4)])
| 方法三:hash双向链表 |
class Node:
def __init__(self, key, val):
self.key = key
self.val = val
self.next = None
self.prev = None
class DoubleList:
def __init__(self):
self.head = Node(0, 0)
self.tail = Node(0, 0)
self.size = 0
self.head.next = self.tail
self.tail.prev = self.head
def addLast(self, x):
x.prev = self.tail.prev
x.next = self.tail
self.tail.prev.next = x
self.tail.prev = x
self.size += 1
def remove(self, x):
x.prev.next = x.next
x.next.prev = x.prev
self.size -= 1
def removeFirst(self):
if self.head.next == self.tail:
return None
first = self.head.next
self.remove(first)
return first
def getSize(self):
return self.size
class LRUCache:
def __init__(self, capacity):
self.cap = capacity
self.cache = DoubleList()
self.dic = {}
def makeRecently(self, key):
x = self.dic.get(key)
self.cache.remove(x)
self.cache.addLast(x)
def addRecently(self, key, val):
x = Node(key, val)
self.cache.addLast(x)
self.dic[key] = x
def deleteKey(self, key):
x = self.dic.get(key)
self.cache.remove(x)
self.dic.pop(key)
def removeLeastRecently(self):
deleteNode = self.cache.removeFirst()
deleteKey = deleteNode.key
self.dic.pop(deleteKey)
def get(self, key):
if not key in self.dic:
return -1
self.makeRecently(key)
return self.dic.get(key)
def put(self, key ,val):
if key in self.dic:
self.deleteKey(key)
self.addRecently(key, val)
return
if self.cap == self.cache.size:
self.removeLeastRecently()
self.addRecently(key, val)
这种实现还有点问题,只要掌握思路就好了。
参考:
百度百科
https://blog.csdn.net/qq_35810838/article/details/83035759
labuladong的算法小抄
【python刷题】LRU的更多相关文章
- Python 刷题笔记
Python 刷题笔记 本文记录了我在使用python刷题的时候遇到的知识点. 目录 Python 刷题笔记 选择.填空题 基本输入输出 sys.stdin 与input 运行脚本时传入参数 Pyth ...
- python刷题第二周
1: 第3章-5 字符转换 (15 分) 本题要求提取一个字符串中的所有数字字符('0'--'9'),将其转换为一个整数输出. 输入格式: 输入在一行中给出一个不超过80个字符且以回车结束的字符串. ...
- python刷题第四周
本周有所收获的题目: 第一题: 第4章-17 水仙花数(20 分) (20 分) 水仙花数是指一个N位正整数(N≥3),它的每个位上的数字的N次幂之和等于它本身. 例如:153=1×1×1+5×5×5 ...
- python刷题第三周
以下是本周有所收获的题目 第一题: 第4章-4 验证"哥德巴赫猜想" (20 分) 数学领域著名的"哥德巴赫猜想"的大致意思是:任何一个大于2的偶数总能表示为两 ...
- python刷题专用函数。。
无它,非bin()莫属. bin(x) Convert an integer number to a binary string. The result is a valid Python expre ...
- python 刷题必备
1.判断输入的数字是否是回文数: 学习内容:把数字转成字符串 1. def is_palindrome(n): n=str(n) m=n[::-1] return n==m 2. tmp_str = ...
- Python 刷题知识点
if : elif : else : print('{0} \n{1} \n{2}' .format((a + b), (a - b), (a * b))) print(*[num**2 for nu ...
- python部落刷题宝学到的内置函数(二)
感觉到刷题宝有一个好处,也许也不是好处,它的答案必须是真正输出的值,也就是说应该输出字符串aaaa的时候,答案必须写成界面上返回的值,即'aaaa'.有利于真正记忆返回值类型,但是....太繁琐了 1 ...
- python部落刷题宝学到的内置函数
最近加入了python部落,感觉里面的刷题宝很有意思,玩了一下,知道了许多以前并不清楚的内置函数,然后感觉到快要记不住了,所以开始陈列一下 1.divmod(a,b):取a除以b的商和余数,功效等价于 ...
随机推荐
- C#动态实体集的反序列化(动态JSON反序列化)
一.使用场景 我们在将 JSON 反序列化实体集的时候,如果字段是固定的,那么我们序列化非常简单,对应字段写的实体集就可以了.比如下面这种: { "data":[ { " ...
- 如何使用iis发布多个ftp,为何ftp 503错误?
使用iis做网站时,需要每个网站都是80端口,所以用到了域名,为了方便发布应用,故将所有网站均添加了ftp发布,当我添加ftp域名绑定后,发现根本无法登陆ftp服务器,后经过百度+博客发现,解决方案: ...
- Android 音视频开发(一):PCM 格式音频的播放与采集
什么是 PCM 格式 声音从模拟信号转化为数字信号的技术,经过采样.量化.编码三个过程将模拟信号数字化. 采样 顾名思义,对模拟信号采集样本,该过程是从时间上对信号进行数字化,例如每秒采集 44100 ...
- Cassandra与Kafka的集成
Cassandra和Kafka经常一起用于微服务架构中.本文将介绍几种Cassandra和Kafka常见的集成模式. 简介 如果您的开发团队乐于接纳微服务架构的优点,那么您就会了解到,Kafk ...
- C语言输入字符串
首先强调一点,C语言没有字符串的概念!所谓的字符串实际上还是以数组形式保存的. 方法1 -- 通过"%s"输入 优点:简单明了,输入字符只要不大于数组长度都可以. #includ ...
- 企业集群架构-03-NFS
NFS 目录 NFS NFS基本概述 NFS应用场景 NFS实现原理 NFS总结 NFS服务端安装 环境准备 服务端安装NFS 服务端NFS配置 服务端开机自启 服务端验证配置 NFS客户端挂载卸载 ...
- 万万没想到,面试中,连 ClassLoader类加载器 也能问出这么多问题…..
1.类加载过程 类加载时机 「加载」 将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在内存上创建一个java.lang.Class对象用来封装类在方法区内的数据 ...
- WPF + RDLC + 动态生成列 + 表头合并
如下,评论超过20条,马上发代码*(੭*ˊᵕˋ)੭*ଘ,效果如下: 代码逻辑简单. WPF使用RDLC需要使用如下DLL 新建WPF 窗体,黏贴下大概如下 <Window xmlns:rv=&q ...
- 用python做youtube自动化下载器 代码
目录 项目地址 思路 流程 1. post i. 先把post中的headers格式化 ii.然后把参数也格式化 iii. 最后再执行requests库的post请求 iv. 封装成一个函数 2. 调 ...
- Mysql-Incorrect string value
[问题描述] com.mysql.jdbc.MysqlDataTruncation: Data truncation: Incorrect string value: '\xF0\x9F\x8E\x8 ...