数据结构与算法 - 链表


前言

数组需要一块连续的内存空间来存储,对内存的要求很高,而链表通过指针将一组零散的内存块串联起来使用,其中内存块称为链表的结点,每个链表的结点除了存储数据,还需要记录链上的下一个结点的地址,记录该地址的指针叫作后继指针next,如图1所示。链表结构五花八门,三种最常见的链表:单链表双向链表以及循环链表
图1

**图1**

一、常用链表

1.单链表

  图1所示即为单链表,第一个节点称头节点,最后一个节点称尾节点。尾节点特殊在于:指针不是指向下一个节点,而是指向一个空地址NULL。

2.双向链表

  图2所示即为双向链表,每个结点不止有一个后继指针next指向后面的结点,还有一个前驱指针prev指向前面的结点。从图2中可以看出,双向链表需要额外的两个空间来存储后继节点和前驱结点。如果存储同样数量的数据,双向链表比单向链表占用更多的内存空间。
  它支持双向遍历,可以支持时间复杂度为O(1)的情况下找到前驱结点,对于删除给定指针指向的结点来说,我们找到了要删除的结点,但是删除某个结点q之前需要知道其前驱结点,而单链表不能直接获得其前驱结点,所以为了找到前驱结点,我们还是要从头结点开始便利,知道p->next = q,说明p是q的前驱结点,对于这种情况,单链表删除操作需要O(n)的时间复杂度,而双向链表只需要O(1)的时间复杂度。
  除了插入、删除操作有优势外,对于一个有序的链表,双向链表的按值查询效率也比单向链表高一些。因为,我们可以记录上次的查找位置p,每次查询时,根据要查找的值与p的大小关系,决定往前还是往后,平均只需查找一半的数据。

在这里插入图片描述

**图2**

3.循环链表

  图3所示即为循环链表(一种特殊的链表),与单链表的唯一区别就在与尾节点(指针指向头结点),优点是从链头到链位比较方便,当处理的数据具有环形结构特点时,特别适合采用循环链表。
在这里插入图片描述

**图3**

二、链表VS数组

  数组和链表,它们插入、删除以及随机访问操作的时间复杂度正好相反(链表的插入删除O(1),随机访问O(n))。但实际开发并不能局限于用复杂度分析来决定使用哪个数据结构,还要考虑实际使用过程的效率以及内存。


三、如何基于链表实现LRU缓存淘汰算法

1.常见的三种缓存淘汰策略

(1)先进先出策略(First In,First Out - FIFO)

(2)最少使用测类(Least Frequently Used - LFU)

(3)最近最少使用策略(Least Recently Used - LRU)

2.用链表实现LRU缓存淘汰法

  维护一个有序单链表,越靠近链表尾部的结点是越早之前访问的。当有一个新数据被访问时,从链表头开始顺序遍历链表。
  (1)如果此数据之前已经缓存在链表中,遍历得到该数据对应的结点,将其从原来的位置删除,然后插入到链表的头部;
  (2)如果此数据并未缓存在链表中,又可以分为两种情况:1)缓存未满,将此节点直接插入到链表的头部;2)缓存已满,删除尾节点,将新的数据结点插入链表的头部。

3.用数组实现LRU缓存淘汰策略

  也是维护一个有序数组,越靠近头部(下标越小)的元素是越早之前访问的。当有一个新数据被访问时,从数组尾部开始遍历。
  (1)数组未满时:若存在,则直接复制到尾部(不删除,避免每次访问删除,数组插入删除很浪费时间);若不存在,则直接新增到尾部。时间复杂度:O(n)
  (2)数组已满时:删除第一个,新增到尾部。时间复杂度:O(1)

四、判断一个字符串是否是回文字符串

  首先,回文字符串:正读和反读都一样的字符串。(刚开始学习,对快慢指针(找环、找中间结点等)的使用并不了解)使用快慢两个指针找到链表中点,慢指针每次前进一步,快指针每次前进两步。在慢指针前进的过程中,同时修改起next指针,使得链表前半部分反序。最后比较中点两侧的链表是否相等。时间复杂度:O(n),空间复杂度O(1)(空间复杂度的计算是看额外的内存消耗,不是看链表本身需要多少存储空间)


总结

  与数组一样,链表也支持数据查找、插入和删除操作。对于数据查找(随机访问):数组数据连续存储,根据首地址和下表,通过寻址公式能直接计算出对应的内存地址,而链表需要根据指针一个节点一个节点地一次便利,知道找到相应的结点;对于插入、删除操作:数组为了保持内存数据的连续性,需要做大量的数据搬移,所以时间复杂度是O(n),而链表的存储空间本身就不是连续的,不需要为了保持内存的连续性而搬移结点,所以链表的插入和删除很快。
  记住空间换时间的设计思想。将循环链表和双向链表整合到一起就是双向循环链表

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值