如果我编写如下所示的代码
,我对递归有疑问inorder(p){
if(p!=NULL){
inorder(p->link); //step 1
cout<<p->info<<" "; //step 2
inorder(p->link); //step 3
}
}
这里,我怀疑的是,当执行步骤1时,控制返回到该功能,然后再次执行步骤1并且控制将再次返回到函数,直到p为NULL,如果这是该过程则如何控制将进入第2步,即“cout”和第3步......
我无法在脑中循环代码......
答案 0 :(得分:1)
在&#34;控件返回相同功能之前&#34;在步骤1中,CPU做了一个重要的步骤:它标记了inorder
代码中的位置,它需要重新执行一次&#34;第二级&#34; inorder
返回(在步骤1之后的那个位置)。在那里,&#34;第二级&#34;在进入&#34;第三级&#34;,&#34;第四级&#34;之前再次标记返回位置,依此类推。最终,N
级别获得NULL
,因此会立即返回。然后N-1
级将打印info
,然后第二次调用inorder
。现在返回的位置是不同的 - 它就在第3步之后。一旦N
- 级别完成,N-1
- st级也完成,返回N-2
- nd等级,然后到N-3
- rd,依此类推,直到第一个级别退出。
这是一个示例树:
A
/ \
B C
/ \
D E
顺序遍历的过程如下:
inorder(A) -- step 1, level 1
inorder(B) -- step 1, level 2
inorder(NULL) -- returns
cout << B -- step 2, level 2
inorder(NULL) -- returns
return -- level 2 returns
cout << A -- step 2, level 1
inorder(C) -- step 3, level 2
inorder(D) -- step 1, level 3
inorder(NULL) -- returns
cout << D -- step 2, level 3
inorder(NULL) -- returns
return -- level 3 returns
cout << C -- step 2, level 2
inorder(E) -- step 1, level 3
inorder(NULL) -- returns
cout << E -- step 2, level 3
inorder(NULL) -- returns
return -- level 3 returns
return -- level 2 returns
return -- level 1 returns
答案 1 :(得分:0)
如果您想了解递归的工作原理,您应该了解call stack
。这是link。
希望这会有所帮助......
答案 2 :(得分:0)
假设p
指向A
,p->link
(即A.link
)称为q并指向B
和q->link
(也就是说B.link
)为NULL,称之为r。
p q r
----->A----->B----->0
现在我们致电inorder(p)
。
答案 3 :(得分:0)
我第一次碰到递归是一个阶乘函数。 因子是数学中的基本函数,给定数字N,它返回的数字等于小于N的所有正整数的乘积。
在C ++中考虑这个简单的代码,很好地演示了递归。
int fact(int x)
{
if(x==1)
return 1;
x = x*fact(x-1);
return x;
}
这输入一个整数,然后在递减整数后调用自身,直到整数为1,并返回x。注意该行'return x;'直到它完成之前的行才被调用。
答案 4 :(得分:0)
我认为你的代码是正确的。您正尝试以下列方式打印链接列表:
inorder(p){
if(p!=NULL)
{
inorder(p->link); //step 1 to navigate to next link
cout<<p->info<<" "; //step 2 as main operation
inorder(p->link); //step 3 to navigate to next link
}
}
翻译成英文
inorder(p)
{
if p points to a linked list
{
print the list p points to;
print content of p;
print the list p points to again;
}
if p points to a null linked list
{
do nothing;
}
}
然后是1 - >的链表。 2 - &gt; 3将输出((3)2(3))1((3)2(3))
如您所见,只有在步骤1遇到空链表时,控件才会转到步骤2。信息打印完毕后,会传递给第3步。
因此,
当节点“3”的链表时,
第1步遇到null并返回;
第2步打印出3;
第3步遇到null并返回;
当节点“2”的链表时
步骤1执行在节点“3”处执行的任何操作; //打印3
第2步打印出2;
步骤3执行在节点“3”处执行的任何操作; // print 3
当节点“1”的链表时
步骤1执行在节点“2”处执行的任何操作; // print 3 2 3
第2步打印出1;
步骤3执行在节点“2”处执行的任何操作; // print 3 2 3
答案 5 :(得分:0)
当第一次调用inorder(p-&gt; link)时,将其视为检查点。它将继续调用它达到NULL的点。然后执行第2行,并且对第二次调用顺序执行相同的操作(p-> link)。所以这形成了一个树
inorder(p->link) -> coutinfo -> inorder(p->link) / ^ / ^ V / V / inorder()->cout->inorder() inorder()->cout->inorder() . ^ / \ . ^ / \ . | . . . | . . . | . | inorder(p->link) //(p->link is NULL) inorder(p->link) //(p->link is NULL)
答案 6 :(得分:0)
考虑一下游戏,如果你家中不同的地方留下5条消息。每条消息都会引导您进入下一条消息要赢得游戏,您必须找到所有5条消息并将其返回给游戏主机。但是,当你找到它们时,你无法接收这些信息......你必须记住它们的位置,并按照你找到它们的相反顺序来接收它们。
你会走到第一个项目,记下它的位置并遵循线索;保持心理记录,你需要在以后返回的地方拿起线索。你会对接下来的4条线索做同样的事情。
当你找到最后的线索,所以不再存在时,你就会开始向后工作,回到找到每条线索的位置,然后检索它们。
找到第一个线索就像是第一次打电话给“inorder()”。跟随第二个线索的线索就像你打电话给“inorder(p-&gt; link)”。找到所有线索后找出线索就像回到代码中的“step2”一样。
答案 7 :(得分:0)
每次调用函数inorder时,数据(称为激活帧或帧)都被放在称为调用堆栈的数据结构上。每个帧跟踪函数本地的数据,例如传递给函数的参数,指向函数调用者的激活帧的指针,以及重要的是,要在调用函数中执行的下一行代码的地址。因此,当您递归调用inorder时,您将递归地向此堆栈添加帧,并且每个帧包含下一行代码的地址,该代码应在相应的函数完成并且控制权返回给函数调用者时执行。
换句话说,当您从称为步骤1的行调用inorder并且传入的参数p为NULL时,当函数退出时,调用函数将在称为步骤2的行开始执行。
有关详细信息,请参阅维基百科页面http://en.wikipedia.org/wiki/Call_stack。
理解与调用堆栈相关的概念将有助于理解递归的内容。