2011-07-30 52 views
4

我知道递归是一种在函数本身内调用函数的技术。 但下面的代码混淆了我它是如何能在第一递归之后做cout部分:函数如何在递归之后执行一个动作?

(此代码解决了河内难题塔)

#include <iostream> 
using namespace std; 

void move_rings(int n, int src, int dest, int other); 

int main(void) 
{ 
    int rings;      
    cout << "Number of Rings: "; 
    cin >> rings; 
    move_rings(rings, 1, 3, 2); 

    system("PAUSE"); 
} 

void move_rings(int rings, int source, int destination, int other) 
{ 
    if (rings == 1) 
    { 
     cout << "Move from " << source << " to " << destination << endl; 
    } 
    else  
    { 
     move_rings(rings - 1, source, other, destination); 
     cout << "Move from " << source << " to " << destination << endl; 
     move_rings(rings - 1, other, destination, source); 
    } 
} 

正如你所看到的,在功能move_ringsif声明后自行调用。

当我想象这一点,我看到永无止境的循环......这怎么可能对这个功能做

cout << "Move from " << source << " to " << destination << endl; 

一部分?

程序的输出是这样的:

Move from 1 to 3 
Move from 1 to 2 
Move from 3 to 2 
Move from 1 to 3 
Move from 2 to 1 
Move from 2 to 3 
Move from 1 to 3 
+1

您是否使用了一些IDE(例如Eclipse)?如果是这样,您可以使用调试器逐步完成程序,以更好地了解发生了什么。学习如何使用调试器是一项基本技能,所以现在就开始吧。 –

+0

谢谢你的提示,但我还是开始了编程though..I'll肯定很快 – Raven

+0

研究它@Deanie - 请阅读[编辑权限](http://stackoverflow.com/help/privileges/edit)尤其是关于“微小的,微不足道的修改令人沮丧的部分 - 尝试在编辑时让帖子显着更好,纠正您观察到的所有问题。”特别是,请记住,除非您有2,000位代表,否则每次编辑(甚至是微不足道的,仅用于标记的编辑)都需要最多5位其他用户的投票。请进行编辑。 –

回答

5

递归首先可能有点难以掌握。据“点击”对我来说,当我想过这个问题是这样的:你有一个基本情况,这是这将导致递归函数本身了电话的条件,然后你有另一部分(“其他“在你的代码中),函数将继续被调用。 “戒指== 1”条件是您的基本情况。

功能“move_rings”被调用,每次一个较小的论点。在随后的每次调用中,变量“rings”变小(因此“移近”基本情况),直到“rings == 1”为真,然后该函数停止调用它自己。

希望有所帮助。

+0

非常感谢你的回答(以及所有其他答案)...我能够掌握一点它,现在我知道,当基本情况(或if条件)达到1时,它会打印出来.. – Raven

+0

..现在,另一个问题出现在我的头上......最后一个递归移动是如何工作的? (“move_rings(rings - 1,other,destination,source);”part)...既然环现在等于1,那么ring-1的参数是否等于零?从而成为一个无限循环?.. .. AARGH(我的牙齿被敲定与这些递归东西) – Raven

+0

一旦“move_rings”终止,“环”的价值将是不管它是什么时调用启动了第一次循环调。递归调用中使用的“铃声”版本实际上是一个“本地”版本,不会影响主“move_rings”调用中“铃声”的值。当本地版本等于1时,第一组递归调用结束,但主“move_rings”函数继续使用旧值“ring”。 Anders Abel的回答与思考这个问题有关。 – 2011-07-30 14:51:22

0

每一次函数递归中,它被一个振铃次数减1。最后,所有分支机构达到rings==1状态,终止。您可以将其想象为一个二叉树,其分支处于else状态,其叶子处于if状态。

1

因为在每次调用move_rings时它都会传递参数rings - 1。最后,传递的参数将为1rings == 1将为true。

在处理递归(或任何类型的可重入)函数时,了解局部变量的工作方式非常重要。每个函数的调用都有自己的本地变量和参数。设想一堆砖(如河内塔中的一堆)。每个砖块都包含功能参数。当一个函数被调用时,这个函数的参数被放置在堆栈的顶部,函数被执行,使用最顶层的砖的值。当函数返回时,最上面的砖被丢弃,返回到下面砖的值。

+0

这是非常有帮助的,我想在可视化第一递归函数时,我错过了“局部变量的化身”的一部分......但现在,它更清晰的给我...谢谢你这么多 – Raven

0

else分支中,通话使用rings - 1完成。由于你永远不会增加它,最终rings将是1if分支将被击中。由于在这个分支中没有发生递归,所以该方法终止。

3

因为每调用一次​​,它的第一个参数就会变小。最终,假设一个非无限数目的环,该功能将仅在一个环上被调用。这是导致递归返回的终止条件。

将其描绘为一棵二叉树结构。假设节点数量不是无限的,你最终会到达一个叶节点,超过这个节点就没有了。然后,您可以开始遍历堆栈以及找到叶节点的其他代码路径。

0

每次调用move_rings函数时,环数都减1。最终,戒指的数量将是1. 然而,这段代码确实会产生无限循环,因为它的写法不好。从不检查环的数量是否大于1.因此,如果在主函数中输入的环数小于1,永不会达到停止递归的条件。

0

move_rings调用move_rings,函数的第二个电话开始完全新鲜的。它有一组完全独立的变量。就好像move_rings调用了其他任何函数。它恰好在调用具有相同名称并包含相同逻辑的“另一个函数”。

在函数的第二次调用中,rings将具有较低的值,因为第一次调用为该参数传递的值比它自己小。最终,在这些递归调用中的一个上,值将达到1,并且在函数开头的if测试将测试为真。这避免了进一步的递归,并且该函数返回。该函数的前一个调用然后从它原来的位置恢复,就像调用了其他函数一样。它完成它的打印,然后在发生类似事件时进行另一次递归调用,然后完成。等一路“备份”。

相关问题