随笔- 59  评论- 817  文章- 0 

10年架构师图解单链表,一篇图文彻底搞懂

§单链表的定义


每一个节点都有一个向后的指针(
引用)指向下一个节点,最后一个节点指向NULL表示结束,有一个Head()指针指向第一个节点表示开始。如下图:



§单链表的特点


耗子戴眼镜,鼠目寸光
我们只能拿到头节点,(
在不逐个遍历的情况下),后面还有多少个节点,它们是什么,它们在哪里,谁是最后一个节点?这些我们统统都无法知道。

肉包子打狗,有去无回
遍历时只能从前往后,
是单向的,一旦错过某个节点,只能从头再遍历一次,确保这次不要错过。

§节点的增/删/交换


增加节点
此时必须有两个指针,一个指向插入位置
的那个节点,称它为prev指针,一个指向待插入的节点,称它为node指针。如下图:


插入过程相等于链接的断开与重建。如下图:

用代码表示:
node.next = prev.next
prev.next = node


删除节点
此时最好有两个指针,一个指向待删除节点前的那个节点,称它为prev指针,一个指向待删除节点,称它为node指针。如下图:

用代码表示:
node = prev.next
prev.next = node.next
node.next = NULL


交换节点
此时必须有两个指针,一个指向待交换的两个节点前的那个节点,称它为prev指针,一个指向待交换的两个节点中的第一个节点,称它为first指针。如下图:

用代码表示:
first = prev.next
prev.next = first.next
first.next = prev.next.next
prev.next.next = first


§逆序


将链表的顺序倒过来。有两种方法:依次交换法集体向后转法

依次交换法
1先和2交换,再和3交换,再和4交换,再和5交换,现在1已经在最后了,2是第一个。如下图:


2先和3交换,再和4交换,再和5交换,此时2已经是倒数第二个了,3是第一个。如下图:


依次类推,用3进行一轮交换,再用4进行一轮交换,逆序就完成了。如下图:

感觉和冒泡排序法有些神似


集体向后转法
这种方法的思路来自于
体育课一排纵队和体育老师面对面站着。老师就是头节点,纵队就是单链表。

纵队集体向后转,老师再走过去和新纵队面对面
单链表换了方向,头节点换了指向

需要三个指针,一个指向
已经向后转过的部分,称为done指针;一个指向正要向后转的那个节点,称为doing指针;一个指向剩余待向后转的部分,称为todo指针。

一开始
还没有一个向后转的,因此done = NULL,doing指向第一个,即doing = head,todo指向第二个,即todo = doing.next。如下图:


让正在向后转的节点(即doing)的next指针指向已经向后转过的(即done);done,doing,todo三个指针分别向右移动一个节点。如下图是操作过程操作后的结果


用代码表示:
doing.next = done
done = doing
doing = todo
(如果doing是NULL,结束)
todo = todo.next(如果next是NULL,则赋NULL)


同理,进行一步,如下图:



同理,最后一步,结束后即完成逆序。如下图:



两种方法的比较,一是链表的方向不变变换节点位置;二是节点位置不变变换链表的方向

§LeetCode,以K个节点为一组逆序

这是leetcode中linkedlist部分的一道题,级别是hard。

如果k=3,每3个节点逆序一下,直到结尾,如果最后剩余的节点不够3个,则原样保留。

第一步,0、1、2逆序



第二步,3、4、5逆序



第三步,6、7、8逆序



第四步,9原样保留



要求:只能定义常量个数的额外变量(或者说只能使用额外常量的内存)。

PS:这道题目虽然是hard级别,但是有了以上的讲解,相信大多数人都能做出来。注意边界条件和细心即可。

相关文章

小学生都能看懂的表达式计算(图解)

五分钟轻松了解Hbase列式存储(图解)




(完)


编程新说


用独特的视角说技术

 

posted on 2019-01-09 08:43 编程新说(李新杰) 阅读(...) 评论(...) 编辑 收藏