先讲一下背景,作为一个算法小白最近在读一本算法书,相信大家也很熟悉:《漫画算法:小灰的算法之旅》。但是在读到第2章数据结构基础2.2小节 - 链表时,产生了一些疑惑,在这里分享一下自己的疑惑和寻找到的答案,希望可以给有同样疑惑的同学提供参考。
其次,讲一下我的疑惑。在看到链表的基本操作 - 删除头部节点时:
书中原文:“头部删除,也很简单,把链表的头节点设为原先头节点的next指针即可。”
看到这里,在不知道head是什么的情况下就想不通了,新的头节点next指针应该为第二个节点的地址,为什么要设为原先头节点的next指针呢?于是我就去查阅了其他有关链表的参考资料,原来是这样。
单向链表结构.png
大家会发现与书中相比,结构图中多出了一个“头节点”,与书中提到的头节点有些不一样,Head也有些不一样,这是怎么回事呢?其实是这样的:
Head:称为头指针,存放指向头节点或首元节点的指针,指向头节点或首元节点。
头节点:位于Head之后,首元节点之前,可以有也可以没有。头节点是没有存放数据的,只有指向下一个节点(首元节点)的指针next。(书中示例无头节点)
首元节点:第一个存放数据的节点。位于Head或头节点后的第一个节点。书中提到的头节点实质是首元节点。
看完上面的介绍,再返回去看头部删除的步骤就是这样的:“头部删除也很简单,把链表的首元节点设为头指针的next指针即可”,即将Head(头指针)指向新的首元节点,自然原来的首元节点也就被删除了。
头部删除.png
看完这个解释,是不是清楚多了?我是的!
同样的,头部插入,书中原文:
第1步:把新节点的next指针指向原先的头节点。
第2步:把新节点变为链表的头节点。
根据上述介绍,步骤就应该是这样的:
第1步:把新节点的next指针指向原先的首元节点。
第2步:把新节点变为链表的首元节点(即将头指针指向新节点)。
头部插入.png
上述在介绍头节点时提到了头节点是可有可无的,但都是基于无头节点时的操作。抱着探索精神,又继续找寻头节点存在的意义是什么呢?
(1)防止单链表为空,当链表为空的时候,带头结点的头指针就指向头结点。不需要判空,头指针始终指向头结点,处理统一。
(2)是为了方便单链表的特殊操作。不带头结点的链表对首元结点、中间结点需分别处理,而带头结点的链表因为有头结点,首元结点、中间结点的操作相同,从而减少分支,使算法变得简单,流程清晰。如:对单链表进行插入、删除操作时,如果在首元结点之前插入或删除的是首元结点,不带头结点的单链表需改变头指针的值,而带头结点的单链表不需改变头指针的值,操作都是针对节点的。
有头节点时删除.png
图例2,有头节点时头部插入:
有头节点时头部插入.png
图例3,有头节点时中间插入:
有头节点时中间插入.png










网友评论