数据结构与算法之美-03链表

链表类型

  • 单链表
    数据结构与算法之美-03链表
  • 循环链表
    数据结构与算法之美-03链表
  • 双向链表
    数据结构与算法之美-03链表
  • 双向循环链表
    数据结构与算法之美-03链表
    注:这里暂时先只介绍常用的链表类型

链表与数组的对比

  • 内存分布
    数据结构与算法之美-03链表
    由上图可知:数组需要一块连续的内存来存储
    链表需要一组零散的内存块来存储
    如果我们申请一个 100MB 大小的数组,当内存中没有连续的、足够大的存储空间时,即便内存的剩余总可用空间大于 100MB,仍然会申请失败。但是申请链表就不会有问题!!!
  • 时间复杂度对比
    数据结构与算法之美-03链表
  • 优缺点对比

数组:
缺点:大小固定
优点:简单实用,访问效率更高(可借助CPU缓存机制)

链表:
缺点:内存不连续,访问效率不高。对内存使用苛刻,当链表发生频繁插入、删除操作时,会导致频繁的内存申请和释放。
优点:链表本身没有大小的限制,天然地支持动态扩容

空间换时间思想

  • 当内存空间充足的时候,如果我们更加追求代码的执行速度,我们就可以选择空间复杂度相对较高、但时间复杂度相对很低的算法或者数据结构。
  • 相反,如果内存比较紧缺,比如代码跑在手机或者单片机上,这个时候,就要反过来用时间换空间的设计思路。
  • 双向链表单向链表更加高效的删除操作

1、在删除给定指针指向的结点时,我们已经找到了要删除的结点,但是删除某个节点q需要知道其前驱结点,而单向链表并不支持直接获取前驱结点。
2、所以,为了找到前驱结点,我们还是要从头开始遍历结点。针对双向链表来说,上述情况就比较有优势了
3、虽说双向链表比单向链表实现起来空间复杂度更高,但是其删除节点时的简便性确凸显出来。
4、实际工程开发中,要具体考量时间换空间,还是空间换时间的方法!

快速写出链表代码小技巧

  • 理解指针或引用的含义
    将某个变量赋值给指针,实际上就是将这个变量的地址赋值给指针,或者反过来说,指针中存储了这个变量的内存地址,指向了这个变量,通过指针就能找到这个变量
  • 警惕指针丢失和内存泄漏

插入结点时,注意操作的顺序
删除链表结点时,也一定记得手动释放内存空间

  • 利用哨兵简化实现难度

针对链表的插入、删除操作,需要对插入第一个结点和删除最后一个结点的情况进行特殊处理。
可通过插入哨兵结点,统一所有操作。

  • 重点留意边界条件处理

如果链表为空时,代码是否能正常工作?
如果链表只包含一个结点时,代码是否能正常工作?
如果链表只包含两个结点时,代码是否能正常工作?
代码逻辑在处理头结点和尾结点的时候,是否能正常工作?

  • 举例画图,辅助思考
  • 多写多练,没有捷径

单链表反转
链表中环的检测
两个有序的链表合并
删除链表倒数第 n 个结点
求链表的中间结点