算法笔记-链表2

如何轻松写出正确的链表代码

本文创作灵感来源于 极客时间 王争老师的《数据结构与算法之美》课程,通过课后反思以及借鉴各位学友的发言总结,现整理出自己的知识架构,以便日后温故知新,查漏补缺。
理解了链表的基础知识,但是距离写出正确的链表代码还是有一段差距的,这个差距就需要我们反复练习,总结,归纳,再练习。王争老师提供了以下几点技巧,帮助我们迅速提高自己写出正确链表代码的动手能力。

理解指针或者引用的正确含义
  • 在C语言中有着指针的概念。所谓指针,可以理解成是一个特殊的变量,存储的不是具体的数值,而是内存地址。通常所说的指针指向 p ,就是说这个指针存储的是变量 p 的内存地址。在高级语言中,抛弃了指针的概念,转而用引用这个概念代替指针的作用。
    警惕指针丢失和内存泄漏
  • 链表中插入节点的时候,一定要注意指针的指向顺序。比如在 a ,b两个节点之间插入节点 n ,指针丢失的写法就是:a->next = n,n->next = a->next。再插入节点之前,a->next = b,但是按照上面的写法,直接a->next = n。这样直接导致链表失去了访问节点 b 内存地址的指针,n 节点后面无法跟上 b 节点,这就导致了指针丢失。
  • 在链表中删除节点的时候,一定要注意内存的释放。比如在 a,n,b三个节点中删除节点 n,内存泄漏的写法就是:a->next = n->next。这样,a 节点的后继指针指向了 b 节点,但是没有执行 n->next = null,就导致了删除节点依然指向 b 节点的内存地址,是的内存泄漏。
    利用哨兵简化实现难度
  • 引入哨兵的概念,简化代码的实行过程。王争老师举了一个例子:遍历一个数组,我们找出值等于 5 的元素的下标。常规写法,我们会利用for循环遍历数组,然后针对每一次循环都做一次当前元素是否等于 5 。当我们引入哨兵的概念时,获取数组最后一个元素,先做一次判断是否等于 5 ,如果不等于 5 ,我们创建一个变量(哨兵变量),该变量存储数组最后一个元素的值,另数组的最后一个元素值为 5 。对数组遍历,使用 while 循环,循环条件就是当前数组元素不等于 5 ,这样循环内部就少了一次值得对比,简化了代码操作。
  • 代码如下
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    int[] list = new int[10];
    int node = list[10];
    if(node == 5){
    return -1;
    }
    list[10] = 5;
    int i = 0;
    while(list[i] != 5){
    i++;
    }
    list[10] = node;
    return i;
重点留意边界条件处理
  • 当我们在处理集合的时候,往往编码以及测试的情况都是集合中是有足够的元素的。但是这并不代表集合中没有元素,只有一个元素等等特殊情况下,代码逻辑依然正确,所以这就需要我们留意观察边界条件。王老师给出了一下几种情况我们需要格外留意
  • 链表为空
  • 链表只包含一个节点
  • 链表只包含两个节点
  • 链表操作的是头结点和尾节点
    距离画图,辅助思考
  • 好记性不如烂笔头,当我们处理的业务逻辑比较复杂,完全可以接借助画图帮助我们具象化抽象的思维逻辑。

    总结

    初入算法学习,必是步履蹒跚,一路磕磕绊绊跌跌撞撞。看不懂别慌,也别忙着总结,先读五遍文章先,无他,唯手熟尔~
    与诸君共勉
-------------本文结束感谢您的阅读-------------