关于递归概念的澄清

时间:2014-02-25 02:48:37

标签: c++ recursion

如果我编写如下所示的代码

,我对递归有疑问
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步......

我无法在脑中循环代码......

8 个答案:

答案 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指向Ap->link(即A.link)称为q并指向Bq->link (也就是说B.link)为NULL,称之为r。

  p      q      r
----->A----->B----->0

现在我们致电inorder(p)

  1. p不是NULL,所以inorder(p)调用inorder(q)(步骤1)
  2. q不是NULL,所以inorder(q)调用inorder(r)(步骤1)
  3. r为NULL,因此inorder(r)跳过该块并将控制返回到inorder(q)
  4. inorder(q)打印B.info(第2步)
  5. inorder(q)调用inorder(r)(步骤3),再次将控制返回到inorder(q),将控制返回到inorder(p)
  6. inorder(p)打印A.info(第2步)
  7. inorder(p)调用inorder(q)(步骤3),再次运行2-5(再次打印B.info),然后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

理解与调用堆栈相关的概念将有助于理解递归的内容。