一.不带头结点的单链表逆转:
此时只需要设计一个函数即可,无须设计不带头节点的链表输入的主函数。
以下是链表逆转的函数:
list Reverse(list L){
ptrtonode New=NULL,Old=L,tmp;
while(Old){
tmp=Old->next;
Old->next=New;
New=Old;
Old=tmp;
}
L=New;
return L;
}
思想是使用两个表(表头)New 和 Old(不知道new和old是否是devc++中的关键词,一开始程序无法运行,后来一顿瞎几把改就能运行了,这里推测new和old是devc++中的关键词)。
tmp作为暂时储存的用于下一次循环中的节点。
新表不断增加节点并调转方向,旧表不断减少节点。当旧表为空时结束循环,最后将L头节点赋予新表表头,即旧表的最后一个元素。
这里可能不好理解,由于备战期末,这次就不画流程图演示了。
第一次循环:设定tmp为2节点,让1结点指向空。并让1节点为新表表头,然后让旧表表头为tmp(2节点)。
第二次循环:设定tmp为3节点,让2结点->next指向1节点。并让2节点为新表表头,然后让旧表表头为tmp(3节点)。
......
最后一次循环:设定tmp为空,让旧表最后一个节点->next指向倒数第二个节点,并让最后一个节点作为新表表头。然后销毁old。
此时将L头节点赋予新表表头,即完成操作,返回反转后的链表list L。
二.带头结点的链表逆转。
带头结点,意味着第一个元素是头节点L->next。
list Reverse(list L){
if (L == NULL || L->next == NULL) {
return head;
}#如果链表不存在或只有头节点,则直接返回。
ptrtonode New=NULL,Old=L->next,tmp;
while(Old){
tmp=Old->next;
Old->next=New;
New=Old;
Old=tmp;
}
L->next=New;
return L;
}
此时有一个疑问就是,在第二次循环中,位序为2的节点的->next被设置指向newhead(即位序为1的节点),此时位序为一的节点正在被头节点->next所指。也就是说:位序为2的节点和头节点的->next同时指向位序为1的节点。
求助shitgpt4结果如下:
您的理解是正确的,但有一点需要明确:在反转链表的过程中,头节点的
next
指针不会立即更新。它只在反转过程结束后,即整个链表被反转后,才会更新为指向新的第一个数据节点。在第二次循环中,的确位序为2的节点的
next
被设置为指向位序为1的节点(即newHead
),但此时头节点仍然指向原链表的第一个数据节点(位序为1的节点)。头节点的next
只有在整个反转过程完成后才会改变。
也就是说,节点同时被两个指针所指并不会引发问题。只要在循环结束后,让L->next指向新表头就行了。
这里突然想到另一个问题:如果L->next==new。那么可以说是L指向new还是L->next指向new。
最终答案是:L->next
指向 new
。
更新一下前面的描述,应该就没问题了,如果有错希望指出,欢迎提问。
除此之外,还有很多种方法逆转单链表,由于备战期末,就不再一一描述了。