iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > Python >LRUCache的实现原理及利用python实现的方法
  • 795
分享到

LRUCache的实现原理及利用python实现的方法

原理方法LRUCache 2022-06-04 19:06:23 795人浏览 独家记忆

Python 官方文档:入门教程 => 点击学习

摘要

简介 LRU(Least Recently Used)最近最少使用,最近有时间和空间最近的歧义,所以我更喜欢叫它近期最少使用算法。它的核心思想是,如果一个数据被访问过,我们有理由相信它在将来被访问的概率就越

简介

LRU(Least Recently Used)最近最少使用,最近有时间和空间最近的歧义,所以我更喜欢叫它近期最少使用算法。它的核心思想是,如果一个数据被访问过,我们有理由相信它在将来被访问的概率就越高。于是当LRU缓存达到设定的最大值时将缓存中近期最少使用的对象移除。LRUCache内部使用LinkedHashMap来存储key-value键值对,并将LinkedHashMap设置为访问顺序来体现LRU算法。

无论是对某个key的get,还是set都算做是对该key的一次使用。当set一个不存在的key,并且LRU Cache中key的数量超过cache size的时候,需要将使用时间距离现在最长的那个key从LRU Cache中清除。

LRU Cache实现

在Java中,LRUCache是通过LinkedHashMap实现的。鄙人照猫画虎,实现一个python版的LRU Cache(可能和其他大神的实现有所区别)。

首先,需要说明的是:

LRU Cache对象内部会维护一个 双端循环链表 的 头节点

LRU Cache对象内部会维护一个dict

内部dict的value都是Entry对象,每个Entry对象包含:

key的hash_code(hash_code = hash(key),在本实现中,hash_code相同的不同key,会被当作一个key来处理。因此,对于自定义类,应该实现魔术方法:__hash__) v - (key, value)对中的value prev - 前一个对象 next - 后一个对象

具体实现是:

当从LRU Cache中get一个key的时候:

计算该key的hash_code 从内部dict中获取到entry 将该entry移动到 双端循环链表 的 第一个位置 返回entry.value

当向LRU Cache中set一个(key, value)对的时候:

计算该key的hash_code,

从LRU Cache的内部dict中,取出该hash_code对应的old_entry(可能不存在),然后根据(key, value)对生成一个new_entry,之后执行:

dict[hash_code] = new_entry 将new_entry提到 双端循环链表 的第一个位置 如果old_entry存在,则从链表中删除old_entry 如果是新增了一个(key, value)对,并且cache中key的数量超过了cache size,那么将双端链表的最后一个元素删除(该元素就是那个最近最少被使用的元素),并且从内部dict中删除该元素

HashMap的实现原理

面试过程中也经常会被问到):数组和链表组合成的链表散列结构,通过hash算法,尽量将数组中的数据分布均匀,如果hashcode相同再比较equals方法,如果equals方法返回false,那么就将数据以链表的形式存储在数组的对应位置,并将之前在该位置的数据往链表的后面移动,并记录一个next属性,来指示后移的那个数据。

注意:数组中保存的是entry(其中保存的是键值)

Python实现


class Entry:
 def __init__(self, hash_code, v, prev=None, next=None):
 self.hash_code = hash_code
 self.v = v
 self.prev = prev
 self.next = next

 def __str__(self):
 return "Entry{hash_code=%d, v=%s}" % (
  self.hash_code, self.v)
 __repr__ = __str__

class LRUCache:
 def __init__(self, max_size):
 self._max_size = max_size
 self._dict = dict()
 self._head = Entry(None, None)
 self._head.prev = self._head
 self._head.next = self._head

 def __setitem__(self, k, v):
 try:
  hash_code = hash(k)
 except TypeError:
  raise

 old_entry = self._dict.get(hash_code)
 new_entry = Entry(hash_code, v)
 self._dict[hash_code] = new_entry

 if old_entry:
  prev = old_entry.prev
  next = old_entry.next
  prev.next = next
  next.prev = prev

 head = self._head
 head_prev = self._head.prev
 head_next = self._head.next

 head.next = new_entry
 if head_prev is head:
  head.prev = new_entry
 head_next.prev = new_entry
 new_entry.prev = head
 new_entry.next = head_next

 if not old_entry and len(self._dict) > self._max_size:
  last_one = head.prev
  last_one.prev.next = head
  head.prev = last_one.prev
  self._dict.pop(last_one.hash_code)

 def __getitem__(self, k):
 entry = self._dict[hash(k)]
 head = self._head
 head_next = head.next
 prev = entry.prev
 next = entry.next

 if entry.prev is not head:
  if head.prev is entry:
  head.prev = prev
  head.next = entry

  head_next.prev = entry
  entry.prev = head
  entry.next = head_next

  prev.next = next
  next.prev = prev

 return entry.v

 def get_dict(self):
 return self._dict

if __name__ == "__main__":
 cache = LRUCache(2)
 inner_dict = cache.get_dict()

 cache[1] = 1
 assert inner_dict.keys() == [1], "test 1"
 cache[2] = 2
 assert sorted(inner_dict.keys()) == [1, 2], "test 2"
 cache[3] = 3
 assert sorted(inner_dict.keys()) == [2, 3], "test 3"
 cache[2]
 assert sorted(inner_dict.keys()) == [2, 3], "test 4"
 assert inner_dict[hash(2)].next.v == 3
 cache[4] = 4
 assert sorted(inner_dict.keys()) == [2, 4], "test 5"
 assert inner_dict[hash(4)].v == 4, "test 6"

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对编程网的支持。

--结束END--

本文标题: LRUCache的实现原理及利用python实现的方法

本文链接: https://www.lsjlt.com/news/15950.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • KNN算法原理及python实现
    文章目录 1 KNN算法原理1.1 基本概念1.2 KNN算法原理1.3 实现步骤1.3 KNN算法优缺点 2 python手工实现KNN算法2.1 KNN算法预测单个数据2.2 KNN算...
    99+
    2023-10-22
    python 机器学习
  • 分析redis原理及实现方法
    小编给大家分享一下分析redis原理及实现方法,希望大家阅读完这篇文章后大所收获,下面让我们一起去探讨吧!1 什么是redisredis是nosql(也是个巨大的map) 单线程,但是可处理1秒10w的并发...
    99+
    2024-04-02
  • Python实现决策树算法的原理与实现方式
    决策树算法属于监督学习算法的范畴,适用于连续和分类输出变量,通常会被用于解决分类和回归问题。 决策树是一种类似流程图的树结构,其中每个内部节点表示对属性的测试,每个分支表示测试的结果,每个节点都对应一个类标签。 决策树算法思路 ...
    99+
    2024-01-22
    算法的概念
  • Base64加密的原理及PHP中的实现方法
    Base64是一种将二进制数据编码成ASCII字符的编码方式,它可以将任何内容(例如图片、文件)转换为可读的字符串。Base64广泛应用于电子邮件、网页、App等领域,也是PHP中常见的加密方式之一。本文将介绍Base64加密的原理及PHP...
    99+
    2023-05-14
  • c++与python实现二分查找的原理及实现
    目录1、时间复杂度与优缺点2、python实现3、C++实现在计算机中,数据的查找方式与其存储方式关系密切。试想一下,如果图书馆中书籍杂乱无章的存放,那么要想找到心仪的书籍将会非常困...
    99+
    2024-04-02
  • Java Bellman-Ford算法原理及实现方法
    本篇内容介绍了“Java Bellman-Ford算法原理及实现方法”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一 点睛如果遇到...
    99+
    2023-07-02
  • spring aop底层原理及实现方法
    这篇文章主要介绍spring aop底层原理及实现方法,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!使用要分析spring aop的底层原理,首先要会使用,先创建一个普通maven webapp项目,引入spring...
    99+
    2023-06-14
  • Semaphore的原理和实现方法
    本篇内容介绍了“Semaphore的原理和实现方法”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!Semaphore数据结构// G...
    99+
    2023-06-15
  • 利用Python实现数值积分的方法
    目录1. 栗子2. 矩形计算面积2.1 左侧边长计算面积2.2 右侧边长计算面积2.3 中值边长计算面积3. 梯形计算面积4. 真值比对5. 总结1. 栗子 为了加深大家的印象,首先...
    99+
    2024-04-02
  • Python利用treap实现双索引的方法
    前言: 在很多应用场景下,我们不但需要堆的特性,例如快速知道数据最大值或最小值,同时还需要知道元素的排序信息,因此本节我们看看如何实现鱼和熊掌如何兼得。假设我们有一系列数据,它的元...
    99+
    2024-04-02
  • 利用java实现动态代理的方法
    这篇文章将为大家详细讲解有关利用java实现动态代理的方法,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。java 动态代理的方法总结AOP的拦截功能是由java中的动态代理来实现的。说白了,...
    99+
    2023-05-31
    java 动态代理 ava
  • Android TextView跑马灯实现原理及方法实例
    目录前言探秘TextView#onDrawMarquee小结应用MarqueeTextViewMarquee效果总结前言 自定义View实现的跑马灯一直没有实现类似 Android ...
    99+
    2024-04-02
  • Vue双向绑定原理及实现方法
    目录双向绑定示例vue3双向绑定双向绑定 Vue 的双向绑定是通过数据劫持和发布-订阅模式实现的。 当 Vue 实例初始化时,它会对 data 选项中的每个属性使用 Object.d...
    99+
    2023-05-17
    Vue双向绑定 Vue3双向绑定实现
  • Python实现原神抽卡的方法
    目录话不多说,直接贴所有代码运行效果需要用到的两张图片总结话不多说,直接贴所有代码 import random import sys import tkinter as tk ...
    99+
    2024-04-02
  • Java动态代理的原理及实现方法是什么
    本篇内容主要讲解“Java动态代理的原理及实现方法是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java动态代理的原理及实现方法是什么”吧!代理是指:某些场景下对象会找一个代理对象,来辅助...
    99+
    2023-07-02
  • Java对象池技术的原理及其实现方法
    这篇文章主要讲解了“Java对象池技术的原理及其实现方法”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Java对象池技术的原理及其实现方法”吧!摘 要 :本文在分析对象池技术基本原理的基础上...
    99+
    2023-06-03
  • 浅谈线性表的原理及简单实现方法
    一、线性表原理:零个或多个同类数据元素的有限序列原理图:特点 :有序性有限性同类型元素第一个元素无前驱,最后一个元素无后继,中间的元素有一个前驱并且有一个后继线性表是一种逻辑上的数据结构,在物理上一般有两种实现 顺序实现和链表实现二、基于数...
    99+
    2023-05-31
    线性表
  • SPFA算法的实现原理及其应用详解
    目录一、前言二、SPFA 算法1、SPFA算法的基本流程2、代码详解三、SPFA 算法已死一、前言 SPFA算法,全称为Shortest Path Faster Algorithm,...
    99+
    2023-05-20
    SPFA算法原理 SPFA算法应用 SPFA算法
  • Ajax的原理及实现过程
    这篇文章主要介绍“Ajax的原理及实现过程”,在日常操作中,相信很多人在Ajax的原理及实现过程问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Ajax的原理及实现过程”的疑惑...
    99+
    2024-04-02
  • setTimeout的实现原理及使用注意
    这篇文章主要讲解了“setTimeout的实现原理及使用注意”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“setTimeout的实现原理及使用注意”吧!se...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作