C 递归反向链表
我很难理解这个递归代码是如何工作的,我已经通过C 递归反向链表,c,recursion,linked-list,reverse,singly-linked-list,C,Recursion,Linked List,Reverse,Singly Linked List,我很难理解这个递归代码是如何工作的,我已经通过gdb绘制并运行了代码 void RecursiveReverse(struct node** headRef) { struct node* first; struct node* rest; if (*headRef == NULL) return; // empty list base case first = *headRef; // suppose first = {1, 2, 3} rest = first-&g
gdb
绘制并运行了代码
void RecursiveReverse(struct node** headRef)
{
struct node* first;
struct node* rest;
if (*headRef == NULL) return; // empty list base case
first = *headRef; // suppose first = {1, 2, 3}
rest = first->next; // rest = {2, 3}
if (rest == NULL) return; // empty rest base case
RecursiveReverse(&rest); // Recursively reverse the smaller {2, 3} case
// after: rest = {3, 2}
first->next->next = first; // put the first element on the end of the list
first->next = NULL;
*headRef = rest; // fix the head pointer
}
我理解,当递归调用堆栈正在构建时,并且一旦列表只包含{3},那么如果(rest==NULL)第一次为true
,则空的rest基本大小写
在此之后,递归调用堆栈开始中断并点击
first->next->next=first第一次使用{2,3}
执行此行之前,在gdb
中输出:
(gdb)p *first
{data = 2, next = 0x1003001f0}
(gdb) p *rest
{data = 3, next = 0x0}
执行这行之后
(gdb) p *rest
{data = 3, next = 0x1003000a0}
继续执行代码以点击first->next->next=first代码>,第二次:
(gdb) p **head_ref
{data = 1, next = 0x1003000a0}
(gdb) p *rest
{data = 3, next = 0x1003000a0} // expected p *rest to be 2
在这里,我希望本地指针rest
应该指向节点2,因为在构建递归调用堆栈时,**headRef
指向节点1,在第rest=first->next行之后代码>,已执行rest
指向节点2
之后*headRef=rest代码>,是否应该headRef
指向节点2
为什么本地状态会丢失,而其余部分指向节点3?这里是简化的伪代码。它基本上是这样工作的:
RecursiveReverse(head):
if head is empty:
return
RecursiveReverse(head->next)
// When we come here, the whole list except the first
// element has been reversed. So all that's left to do
// is to reverse the final step
head->next->next = head
head->next = NULL
这里要认识到的最重要的一点是,在递归调用之后,除了第一个元素外,整个列表都已反转。假设您有一个列表,它的其余部分已经反转
在反转其余部分之前,列表具有此结构
first -> first_of_rest -> second_of_rest->...->nth_of_rest->nullptr
在反转其余部分后,您将得到
first -> nullptr <- first_of_rest <- second_of_rest <-...<-nth_of_rest
| |
________________________________________________________
the rest part of the list
abd将节点first
旁边的数据成员设置为“指向”nullptr
first->next = NULL;
因此,我们有
nullptr <-first <- first_of_rest <- second_of_rest <-...<-nth_of_rest
NulLPTR最难的部分是接受“<代码>递归sivReVSE(/REST)”的概念,它实际上与其余的相反。@ HasLoValDOS在列表只有两个元素时就足以考虑其中一个基本情况。在反转其余部分之后,当列表看起来像<代码> 1>2NeX/<代码>包含<代码> null < /代码>时,为什么不行*headRef=rest
将*headRef
更改为指向节点2,就像在列表仅包含{2,3}时将*headRef
更改为指向节点3一样?rest怎么总是等于{3,…}
之后呢?@HasloVardos头部是通过引用传递的。参见函数参数声明结构节点**headRef。函数的最后一个语句*headRef=rest;因此,只有在基本情况{2,3}中,*headRef=rest
实际修改head,使其指向restrest等于3
,之后这个赋值操作就变得不相关了,因为它做了同样的事情?
nullptr <-first <- first_of_rest <- second_of_rest <-...<-nth_of_rest