数据结构与算法之美 —— 如何实现LRU缓存淘汰算法?(总结)

链表与数组

  1. 链表定义: 百度百科
  2. 数组定义:百度百科
    总结:
    链表和数组最大差别是在内存空间结构上,连续(数组)和可非连续(链表)。数组通过内存地址和下标可以快速找到内存存储位置,链表是通过节点(指针)指向前后的地址一个个去查找。

电影座位比喻:

数组:一排座位标注了有顺序的123..编号。
链表:每个座位位置上记录了下个和上个位置的坐标。
查找:
数组座位: 数组来的直接,可以数数找位置,不用一个一个看。
链表座位: 我们找位置就必须从第一个座位开始找,找到它指向的下一个座位的坐标,然后再找到下一个看第二个座位的下一个是哪个座位...依次找到自己的位置。
-----数组查找速度快
添加座位:
数组座位:数组就需要新增空间,然后挪动插入当前需要插入的位置后所有位置向后移动(麻烦)。
链表座位:链表结构只需要找到需要加入的位置,修改标记指向即可(轻松)。
---- 链表插入快(删除同理)

链表细分

  1. 单链表:单向节点指向
    b93e7ade9bb927baad1348d9a806ddeb.jpg
  2. 双向链表:
    cbc8ab20276e2f9312030c313a9ef70b.jpg
  3. 循环链表:
    86cb7dc331ea958b0a108b911f38d155.jpg
  4. 双向循环链表:
    d1665043b283ecdf79b157cfc9e5ed91.jpg

    区别:
    单链表和双向链表的叙别主要是链表节点是否指向一边。
    循环和非循环链表主要区别在于首尾是否互相指向。

缓存

缓存常见淘汰策略:

常见的策略有三种:先进先出策略 FIFO(First In,First Out)、最少使用策略 LFU(Least Frequently Used)、最近最少使用策略 LRU(Least Recently Used)

链表结构实现(摘抄自:极客时间)

我的思路是这样的:我们维护一个有序单链表,越靠近链表尾部的结点是越早之前访问的。当有一个新的数据被访问时,我们从链表头开始顺序遍历链表。

  1. 如果此数据之前已经被缓存在链表中了,我们遍历得到这个数据对应的结点,并将其从原来的位置删除,然后再插入到链表的头部。
  2. 如果此数据没有在缓存链表中,又可以分为两种情况:
    如果此时缓存未满,则将此结点直接插入到链表的头部;
    如果此时缓存已满,则链表尾结点删除,将新的数据结点插入链表的头部。
    (数组思想同上一样)

自我思考:
如果是我从链表和数组中选择一种数据结构做缓存处理,我偏向于数组结构。1. 数组结构特点查询遍历快。原因: 既然是做缓存,那么本身做缓存的目的是什么?是为了多次访问相同数据更快,正好是数组的特点吧,访问快。 2. 缓存也存在加入和淘汰。 其实真的做缓存这个是可以一定程度上减少开销的。比如:通过估量缓存大小初始化足够或者相对接近的数组大小,减少加入缓存数据多次扩展数组,减少开销。(才疏学浅,敬请指教)

你可能感兴趣的:(数据结构与算法之美 —— 如何实现LRU缓存淘汰算法?(总结))