纯小白学数据结构——链表

1.常用场景:LRU缓存淘汰算法
1)缓存
2)缓存淘汰策略
2.链表结构
(1)链表VS数组
从底层的存储结构来看:数组需要一块连续的内存空间,比如申请一个100MB大小的数组,当内存中 没有连续的、足够大的存储空间时,会申请失败;
链表不需要连续的内存空间,通过“指针”将一组零散的内存块串联起来
在这里插入图片描述
(2)链表结构
(i)单链表
把内存块称为链表的“结点”,每个结点除了存储数据外,还需要记录链上的下一个结点的地址,记录下个结点地址的指针叫做后继指针next。
两个特殊的结点:头结点、尾结点;头结点记录链表的基地址,有了它可以遍历得到整条链表;尾结点的指针不是指向下一个结点,而是指向一个空地址NULL。
在这里插入图片描述
插入和删除操作,只需要考虑相邻结点的指针改变,时间复杂度为O(1),而数组是O(n);
在这里插入图片描述
但随机访问不如数组高效,链表需要根据指针一个结点一个结点地依次遍历,直到找到相应的结点。时间复杂度为O(n),数组为O(1):(1+2+3+…+n)/n = O(n)平均时间复杂度,O(1)直接根据寻址地址公式得到。
(ii)循环链表
一种特殊的单链表,唯一区别在尾结点。尾结点的指针指向链表的头结点。像环一样首尾相连。优点是从链尾到链头比较方便,多适用于环型结构数据,如约瑟夫问题。
在这里插入图片描述
(iii)双向链表
支持两个方向,每个结点还有一个前驱指针prev指向前面的结点。需要额外的两个空间来存储后继结点和前驱结点的地址。若存储同样多的数据,比单链表占用更多的内存空间,但可以支出双向遍历,灵活性:
在这里插入图片描述
双向链表支出O(1)时间复杂度找到前驱结点,在某些情况下插入、删除比单链表简单、高效:
删除操作:
删除结点中“值等于某个给定值”的结点;
删除给定指针指向的结点。
对于第一种情况,无论单链表还是双向链表,为了查找到值等于给定值的结点,都需要从头结点开始一个一个依次遍历对比,删除操作时间复杂度O(1),遍历查找时间复杂度是O(n),根据时间复杂度加法法则,情况一的链表操作总时间复杂度为O(n).
对于第二种情况,已经找到了要删除的结点,但删除某个结点q需要知道前驱结点,要从头结点开始遍历链表,则双向链表的时间复杂度为O(1),单链表为O(n)。
同理对于插入操作一样分析。
对于有序链表,双向链表平均只需要查找一半的数据
实际软件开发,如:LinkedHashMap
设计思想:用空间换时间
对于执行较慢的程序,可以通过消耗更多的内存(空间换时间)来进行优化;消耗过多内存的程序,通过消耗更多的时间(时间换空间)来降低内存的消耗。
3.链表VS数组性能大比拼
实际中,不能仅利用复杂度分析就决定使用哪个数据结构来存储数据:在这里插入图片描述
数组连续的内存空间,可借助CPU的缓存机制,访问效率更高。链表不连续存储对CPU缓存不友好,没办法有效预读。
数组缺点是大小固定,链表无大小限制,支持动态扩容。
资料学习:极客时间——数据结构与算法之美

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值