【基础篇】5 # 链表(下):写好链表代码的六个实用技巧

简介: 【基础篇】5 # 链表(下):写好链表代码的六个实用技巧

说明

【数据结构与算法之美】专栏学习笔记



技巧一:理解指针或引用的含义

指针或引用都是存储所指对象的内存地址。将某个变量赋值给指针,实际上就是将这个变量的地址赋值给指针。


例如:

  • p —> next = q:表示 p 结点中的 next 指针存储了 q 结点的内存地址。
  • p —> next = p —> next —> next:表示 p 结点的 next 指针存储了 p 结点的下下一个结点的内存地址。



技巧二:警惕指针丢失和内存泄漏


例子:在结点 a 和相邻的结点 b 之间插入结点 x,假设当前指针 p 指向结点 a。

ed87191e3e554bf4918b57950deee061.png


错误写法如下

p —> next = x;
x —> next = p —> next;


如果按照上面的写法,先将 p 的 next 指针指向 x 结点,然后将 x 的结点的 next 指针指向 b 结点。但是这里第一步操作完指针指向结点 x,第二步就是 x 自己指向自己,导致链表断裂,结点 b 往后的所有结点都无法访问到。


正确写法如下:顺序倒一下


x —> next = p —> next;
p —> next = x;

插入结点时,要注意操作的顺序,这样才不会丢失指针,导致内存泄漏。另外删除链表结点时,也一定要记得手动释放内存空间。



技巧三:利用哨兵简化实现难度

什么是哨兵?


例子1:空链表中插入第一个结点

if (head == null) {
  head = new_node;
}


例子2:删除链表中的最后一个结点

if (head -> next == null) {
   head = null;
}


针对链表的插入、删除操作,需要对插入第一个结点和删除最后一个结点的情况进行特殊处理。哨兵就是用来处理这些边界问题的,它不直接参与业务逻辑。


引入哨兵结点,不管链表是不是空,head 指针都会一直指向这个哨兵结点,并且一直存在,哨兵结点也不存储数据。


   带头链表:指有哨兵结点的链表

   不带头链表:指没有哨兵结点的链表


带头链表示意图:


ad685bf026aa40089256712c6e2ebb8b.png


删除最后一个节点的时候:


   在没有加哨兵的时候,这个时候用 p -> next = p -> next -> next 没用,就一个节点的话 p -> next 和 p -> next -> next 都是 null,相当于null = null。


   如果加上哨兵,哨兵是恒存在于链表中的,删除链表中的最后一个元素(是删除哨兵以外的最后一个,哨兵不参与业务逻辑)所以当哨兵后还跟着一个元素时,也就是有最后一个元素时,站在哨兵的位置依旧可以执行 p -> next = p -> next -> next,进而把最后一个删掉。


利用哨兵简化编程难度技巧的常见的有插入排序、归并排序、动态规划等。



技巧四:重点留意边界条件处理


检查链表代码是否正确的边界条件:


  • 如果链表为空时、链表只包含一个结点时、链表只包含两个结点时,代码是否可行?
  • 代码逻辑在处理头结点和尾结点的时候,代码是否可行?



技巧五:举例画图,辅助思考


对于稍微复杂的链表操作,可以使用举例法和画图法。


示例:往单链表中插入一个数据


165b0fbc453c4dcd9f28bf9798c11fde.png


技巧六:多写多练,没有捷径


熟练的写出一些常见的链表操作:


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



目录
相关文章
|
6月前
|
存储 编译器 C语言
【数据结构】C语言实现带头双向循环链表万字详解(附完整运行代码)
【数据结构】C语言实现带头双向循环链表万字详解(附完整运行代码)
55 0
【数据结构】数组、双链表代码实现
【数据结构】数组、双链表代码实现
|
2月前
|
存储 算法 C语言
C语言手撕实战代码_循环单链表和循环双链表
本文档详细介绍了用C语言实现循环单链表和循环双链表的相关算法。包括循环单链表的建立、逆转、左移、拆分及合并等操作;以及双链表的建立、遍历、排序和循环双链表的重组。通过具体示例和代码片段,展示了每种算法的实现思路与步骤,帮助读者深入理解并掌握这些数据结构的基本操作方法。
代码随想录Day03 | 链表基础1 LeetCode T203 移除链表元素 T707设计链表 T206 反转链表
代码随想录Day03 | 链表基础1 LeetCode T203 移除链表元素 T707设计链表 T206 反转链表
49 0
|
5月前
|
存储 算法
【单向链表】数据结构——单向链表的介绍与代码实现&笔记
【单向链表】数据结构——单向链表的介绍与代码实现&笔记
|
6月前
leetcode代码记录(移除链表元素
leetcode代码记录(移除链表元素
30 0
|
6月前
|
存储
链表的实现(文末附完整代码)
链表的实现(文末附完整代码)
54 2
|
6月前
|
存储
数据结构基础:一篇文章教你单链表(头插,尾插,查找,头删等的解析和代码)
数据结构基础:一篇文章教你单链表(头插,尾插,查找,头删等的解析和代码)
|
6月前
在实现链表的代码中,为什么要使用继承而不是组合?
在实现链表的代码中,为什么要使用继承而不是组合?
35 3
|
6月前
|
设计模式 测试技术
在实现链表的代码中,为什么要使用`Node`类而不是直接在`LinkedList`类中定义节点?
在实现链表的代码中,为什么要使用`Node`类而不是直接在`LinkedList`类中定义节点?
47 1