引例代码:
//逆转
void reverse(LinkLIst L2)//逆转L2这个结构体 头指针并不发生改变 故不需要引用
{
LinkLIst r,s,t;
r=L2->next;
if(NULL==r)
{
return; //链表为空
}
s=r->next;
if(NULL==s)
{
return; //链表只有一个结点
}
t=s->next;
while (t)//如果t不为空
{
s->next=r;//t往后移的前提
r=s;//以下三句是三个指针同时往后走一步
s=t;
t=t->next;
L2->next->next=NULL;//逆置后,链表第一个结点的next要为NULL
L2->next=s;//s才是新链表的表头
}
s->next=r;//t为NULL后倒数第二个还需要指向前一个完成最后的逆置
}
此代码不需要引用原因:
这段代码逆转了链表 L2
的内容,但并没有改变链表头指针的指向。因为链表的头指针(即 L2
)没有被修改,所以不需要使用引用。
在函数中,逆转链表的过程仅仅修改了链表中的指针关系,而没有涉及到头指针的改变。链表的头指针仍然指向原来的位置(即仍然作为头结点)。因此,如果调用这个函数,并且希望在调用后继续使用链表的头指针,不需要传递头指针的引用。
注意,即使链表的头指针没有发生变化,函数内部仍然可以通过指针操作修改链表的内容。这是因为链表的节点通过指针相互连接,而函数的参数传递是通过值传递的。这里,传递的是链表头节点的一个副本,但通过这个副本仍然可以访问和修改链表中的节点。
所以,由于链表头指针没有被修改,这个逆转函数不需要使用引用。
但是在代码中头指针又重新指向了最后一个节点并且在逆转后成为了新的头结点 为什么不能算作是头指针改变?
因为在代码中,虽然函数执行后头指针重新指向了原链表的最后一个节点,但这并不等同于头指针的改变。因为头指针的定义是指向链表的第一个节点的指针。即使头指针指向了链表中的某个其他节点,只要它没有指向新分配的内存地址,它仍然被视为原始链表的头指针。(转置中并没有分配新的内存地址)
代码中,虽然头指针 L2
在逆转后指向了原链表的最后一个节点 s
,但它仍然指向了原始链表的地址,并没有指向新的内存分配位置。因此,虽然头指针指向了链表中的不同节点,但并没有发生头指针的实际改变。
要想发生头指针的改变,通常需要进行如下操作之一:
- 分配新的内存来存储新的头节点,并将头指针指向这个新分配的内存地址。
- 删除原头节点,使得原头指针失去作用,并且更新头指针指向链表的新头节点。
代码中,虽然链表头节点的位置发生了变化,但头指针仍然指向原始链表的地址,因此不算作头指针的改变。
什么情况下才算是头指针的改变:
头指针的改变是指头指针所指向的内存地址发生变化。在链表中,头指针通常指向链表的第一个节点,而头节点包含了链表的第一个元素以及指向下一个节点的指针。
头指针的改变可以发生在以下情况:
-
链表为空时的头指针改变: 当链表为空,头指针指向
NULL
,如果在某个操作中为链表添加了第一个节点,那么头指针会发生改变,指向新添加的节点。 -
删除头节点时的头指针改变: 如果链表非空,而你删除了链表的头节点,那么头指针会被更新,指向新的头节点。
-
在链表前插入新节点时的头指针改变: 如果在链表的头部插入了一个新节点,那么头指针会发生改变,指向新插入的节点。
-
在链表前删除节点时的头指针改变: 如果在链表的头部删除了一个节点,那么头指针会被更新,指向新的头节点。
在这些情况下,如果希望在函数外部能够感知到头指针的改变,就需要传递头指针的指针或引用,以便在函数内部能够修改外部的头指针。如果仅在函数内部修改链表中的节点,而不修改头指针,通常不需要传递头指针的引用。