0407.链表(上):如何实现LRU缓存淘汰算法.pdf

0407.链表(上):如何实现LRU缓存淘汰算法.pdf

  1. 1、本文档共9页,可阅读全部内容。
  2. 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
  3. 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  4. 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多

07|链表(上):如何实现LRU缓存

淘汰算法?

今天我们来聊聊“链表(Linkedlist)”这个数据结构。学习链表有什么用呢?为

了回答这个问题,我们先来讨论一个经典的链表应用场景,那就是LRU缓存

淘汰算法。

缓存是一种提高数据读取性能的技术,在硬件设计、软件开发中都有着非常广

泛的应用,比如常见的CPU缓存、数据库缓存、浏览器缓存等等。

缓存的大小有限,当缓存被用满时,哪些数据应该被清理出去,哪些数据应该

被保留?这就需要缓存淘汰策略来决定。常见的策略有三种:先进先出策略

FIFO(FirstIn,FirstOut)、最少使用策略LFU(LeastFrequentlyUsed)、

最近最少使用策略LRU(LeastRecentlyUsed)。

这些策略你不用死记,我打个比方你很容易就明白了。假如说,你买了很多本

技术书,但有一天你发现,这些书太多了,太占书房空间了,你要做个大扫

除,扔掉一些书籍。那这个时候,你会选择扔掉哪些书呢?对应一下,你的选

择标准是不是和上面的三种策略神似呢?

好了,回到正题,我们今天的开篇问题就是:如何用链表来实现LRU缓存淘

汰策略呢?带着这个问题,我们开始今天的内容吧!

五花八门的链表结构

相比数组,链表是一种稍微复杂一点的数据结构。对于初学者来说,掌握起来

也要比数组稍难一些。这两个非常基础、非常常用的数据结构,我们常常将会

放到一块儿来比较。所以我们先来看,这两者有什么区别。

我们先从底层的存储结构上来看一看。

为了直观地对比,我画了一张图。从图中我们看到,数组需要一块连续的内存

空间来存储,对内存的要求比较高。如果我们申请一个100MB大小的数组,

当内存中没有连续的、足够大的存储空间时,即便内存的剩余总可用空间大于

100MB,仍然会申请失败。

而链表恰恰相反,它并不需要一块连续的内存空间,它通过“指针”将一组零散

的内存块串联起来使用,所以如果我们申请的是100MB大小的链表,根本不

会有问题。

1

链表结构五花八门,今天我重点给你介绍三种最常见的链表结构,它们分别

是:单链表、双向链表和循环链表。我们首先来看最简单、最常用的单链表。

我们刚刚讲到,链表通过指针将一组零散的内存块串联在一起。其中,我们把

内存块称为链表的“结点”。为了将所有的结点串起来,每个链表的结点除了存

储数据之外,还需要记录链上的下一个结点的地址。如图所示,我们把这个记

录下个结点地址的指针叫作后继指针next。

从我画的单链表图中,你应该可以发现,其中有两个结点是比较特殊的,它们

分别是第一个结点和最后一个结点。我们习惯性地把第一个结点叫作头结点,

把最后一个结点叫作尾结点。其中,头结点用来记录链表的基地址。有了它,

我们就可以遍历得到整条链表。而尾结点特殊的地方是:指针不是指向下一个

结点,而是指向一个空地址NULL,表示这是链表上最后一个结点。

2

与数组一样,链表也支持数据的查找、插入和删除操作。

我们知道,在进行数组的插入、删除操作时,为了保持内存数据的连续性,需

要做大量的数据搬移,所以时间复杂度是O(n)。而在链表中插入或者删除一个

数据,我们并不需要为了保持内存的连续性而搬移结点,因为链表的存储空间

本身就不是连续的。所以,在链表中插入和删除一个数据是非常快速的。

为了方便你理解,我画了一张图,从图中我们可以看出,针对链表的插入和删

除操作,我们只需要考虑相邻结点的指针改变,所以对应的时间复杂度是

O(1)。

但是,有利就有弊。链表要想随机访问第k个元素,就没有数组那么高效了。

因为链表中的数据并非连续存储的,所以无法像数组那样,根据首地址和下

标,通过寻址公式就能直接计算出对应的内存地址,而是需要根据指针一个结

点一个结点地依次遍历,直到找到相应的结点。

你可以把链表想象成一个队伍,队伍中的每个人都只知道自己后面的人是谁,

所以当我们希望知道排在第k位的人是谁的时候,我们就需要从第一个人开

始,一个一个地往下数。所以,链表随机访问的性能没有数组好,需要O(n)

的时间复杂度。

好了,单链表我们就简单介绍完了,接着来看另外两个复杂的升级版,循环链

表和双向链表。

循环链表是一种特殊的单链表。实际上,循环链表也很简单。它跟单链表唯一

的区别就在尾结点。我们知道,单链表的尾结点指针指向空地址,表示这就是

您可能关注的文档

文档评论(0)

yzs890305 + 关注
实名认证
内容提供者

该用户很懒,什么也没介绍

1亿VIP精品文档

相关文档