(一)定义详解
1.头结点:
(1)数据结构中,在单链表的开始结点之前设立一个节点称之为头结点,
头结点的数据域可以不存储任何信息,也可以存储链表的长度等附加信息,
头结点的指针域存储指向第一个结点的指针(即第一个结点的存储位置)。
(2)作用:方便链表的操作,减少代码量,
举个例子,要知道在链表中插入,删除一个元素是更改这个结点上一个结点的指针域的位置来实现的,那么怎么样来对第一个结点来进行这些操作,有,但是麻烦,不如引入一个头结点来的方便。总之,引入头结点就可以很少的考虑到一些特殊情况,减少代码量。
2.头指针:
注意注意注意
(1)头指针是指链表中 ,指向第一个结点的指针。 这一点很重要
(2)头指针具有标识作用,所以常常会用头指针冠以链表的名字。(原理:结点类实例化创建对象时的引用,指向头结点对象自然就是头指针了)所以你定义一个链表,那么链表的名字一般就是这个链表的头指针。例如:
ListNode L = new ListNode(0);
这个新实例化的链表名字L就是这个链表的头指针。
(3)无论链表是否为空,头指针均不为空,头指针是链表的必要元素。
所以头节点和头指针不是一回事,
即头节点的指针域不是头节点, 头节点的指针域 指向 首结点
头结点对象的引用才是头指针
二)个人理解
在我学习数据结构的时候,因为对头指针和头结点的理解不够深刻,曾花费了自己大量的时间,下面的都是我自己遇到的一些疑难,我写下来一一解答,即是对自己这段阶段的完美的结束,也希望能帮到你们。这是我对java链表的定义(很浅显)
public class ListNode{
int val;//定义数据域
ListNode next;//定义指针域
ListNode(int x){
val = x;
}
}
1.大部分情况下,我们说的链表指的都是带着头结点的链表,
如链表L,
它的头结点在第一个元素结点之前,所以这个链表的第一个结点是指头结点,
第一个元素结点在头结点之后,而这第一个元素结点通常也被说为开始结点。话不多说,放图
注意注意:这是带有头结点的链表,有的链表是不带有头结点,自己多观察
这张图里第一个结点是头结点,所以头指针指向头结点
2.头指针是指向第一个结点位置的指针,
所以当链表有头结点时,那么头指针就是指向头结点的指针了,
当链表没有头结点时,头指针就是指向第一个元素结点即开始结点的指针了。
3.曾经我碰到这么一行代码,没怎么看懂:
public ListNode reverse(ListNode head){
ListNode dummy = new ListNode(0);
dummy.next = head;
曾经的我是这样以为的:
嗯,new一个新的链表,没错,然后让传进来的链表的头指针head的值(即地址)赋值给这个新的链表dummy的头指针,没错啊,
咦,不啊?next不是下一个的意思吗?那么dummy.next = head的意思不就是将head这个头指针的值(就是头结点的地址)赋值给头节点dummy的下一个指针,首节点,那么首节点指向head这个链表头结点,
那我就这样说,头指针dummy的下一个指针指向了head这个头指针,那么dummy指到哪里去了呢?这位置怎么没有对上嘞?那后面的位置不都是错开来的吗?我好烦!画个图就是这样:
曾经的我为了这个问题想破了天,也在网上搜了不少,诶,却依然没弄懂,因为这个问题,导致我对诸如此类的链表传递地址,都是头指针的位置没有对上,导致我对后面的代码,脑子里都是大大的疑惑,虽然思路看懂了,但是却依旧为此烦恼,原因皆因为这个头指针的问题。
答案:
next在java链表里的定义(我定义的,不一定是别人定义的)的意思是指针域的意思(请看上面我对链表的定义),在这里就不能看做英文里下一个的意思,所以dummy.next = head 的意思是将head这个头指针赋值给dummy.next这个头节点对象的指针域,
这是两个链表之间的传导在于两个头指针的操作
jummy具有双重意义,一个是结点类实例化创建对象时的引用,头指针
一个是jummy.next时代表的头结点对象的指针域
这样就对的上了,即传进来的形参head变量是个地址,指向head的那个链表的头结点,将head这个指针的值(即头结点的地址)复制给dummy.next,就是dummy这个链表的头指针被赋值了一个地址,这个地址指向head这个链表头结点的位置。这么说的话,就是正确的了,两个链表就能对的上了。
可能有一点点绕口,请慢慢品尝。