数据结构二——链表

文章出处:极客时间《数据结构和算法之美》-作者:王争。该系列文章是本人的学习笔记。

底层存储

数组:一块连续的内存空间。
链表:用指针串起来的一组零散的内存空间。
在这里插入图片描述
链表分类:单链表、双向链表、循环链表

单链表

内存块是连接的节点。每个节点存储数据和指向下一个节点的指针。第一个节点叫做头结点,最后一个节点叫做尾节点。尾节点的next=null。
在这里插入图片描述

操作特点

1 插入、删除很快,O(1)。
2 想要随机访问只能从头节点开始遍历,数到第k个节点。平均时间复杂度O(n)。想象队列就是一个排队的队伍。每个人只知道自己后面的那个人。

循环链表

结构特点:循环列表的尾节点指向链表的头结点。
在这里插入图片描述
用途:用于解决数据具有环形结构的问题。例如约瑟夫问题。

双向链表

双向链表的节点存储:数据+指向下一个节点的指针+指向上一个节点的指针。
在这里插入图片描述

用途1:更方便的插入删除

删除的使用场景一般为:给定一个值,将具有这个值得节点删除。只是删除需要O(1)的时间,但是查询的平均时间复杂度为O(n)。根据时间复杂度的加法原则,时间复杂度为O(n)。
另外一个场景是:已经给定一个节点,删除这个节点。单项链表因为没有向前的指针,所以需要从头开始遍历,找到要删除节点的前一个节点。平均时间复杂度(O(n))。如果是双向列表,因为有向前的指针,O(1)就可以实现。

在某个节点前插入一个元素,双向列表显示出了优势,因为有前向指针。时间为O(1)。

用途2:在有序列表中查找更方便

因为每次查询时,都要比较当前元素和要找元素的大小,然后决定向前走,还是向后走。

链表 VS 数组

在时间复杂度方面:
数组:插入、删除 O(n) ;随机访问O(1)
链表:插入、删除O(1);随机访问 O(n)

数组的优点:数组更简单,可以利用CPU缓存,速度更快。
数组的缺点:需要申请固定大小的空间,在扩容的时候更加浪费内存,可能产生OOM。

链表的优点:大小可以是不固定的。
链表的缺点:内存块是不连续的,不能利用CPU缓存。

思考题:如何基于链表给出LRU缓存

LRU缓存:是指删除最近访问少的元素 的缓存策略。
已经访问过的元素用链表存储。现在假设访问元素a,有如下情况:
1 a在链表中,那把a元素删除,插入在队列头部作为头结点。
2 a不在链表中
2.1 并且链表空间充足,则把a插入在链表头部。
2.2 并且链表空间不足,则把尾元素删除,把a插入在链表头部。
因为要遍历每个元素,所以平均时间复杂度是O(n)。如果使用散列表就能提高速度。

写好链表代码的几个技巧

1 理解指针的含义。将某个变量赋值给指针,实际上就是将这个变量的地址赋值给指针。
2 警惕指针丢失和内存泄漏
3 利用哑结点简化代码
4 留意边界条件的处理。链表可以考虑的几个边界条件有:
4.1 如果列表为空,代码可以正常运行吗?
4.2 如果列表只包含一个节点,代码可以正常运行吗?
4.2 如果列表含2个节点,代码可以正常运行吗?
4.3 代码逻辑在处理头、尾节点的时候,代码可以正常运行吗?

5 举例画图帮助思考
6 多写多练

关于链表面试中经常遇到的场景

1 单链表翻转
2 是否有环检测
3 2个有序链表合并
4 删除倒数第k个节点
5 求中间节点

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值