递归后函数如何执行操作?

时间:2011-07-30 13:53:23

标签: c++ recursion programming-languages computer-science

我知道递归是一种在函数本身内调用函数的技术。 但是下面的代码让我对第一次递归后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

7 个答案:

答案 0 :(得分:5)

起初可能有点难以理解递归。当我这样想时,它“点击”了我:你有一个基本情况,这是导致递归函数而不是再调用自身的条件,然后你有另一部分(你的代码中的“else”),继续调用该函数。 “ring == 1”条件是您的基本情况。

每次使用较小的参数调用函数“move_rings”。在每次后续调用中,变量“rings”变小(因此“靠近基本情况”),直到“rings == 1”为真,然后函数停止调用自身。

希望有所帮助。

答案 1 :(得分:3)

因为每次调用move_rings()时,它的第一个参数都会变小。最后,假设一个非无限数量的环,该函数将仅在一个环上被调用。这是导致递归返回的终止条件。

将其描绘成二叉树结构。假设一个非无限数量的节点,您最终将到达一个叶子节点,超过该节点就不再存在。然后,您可以开始遍历堆栈以及找到叶节点的其他代码路径。

答案 2 :(得分:1)

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

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

答案 3 :(得分:0)

每次函数递归时,它都会得到一个递减1的响铃次数。最后,所有分支都达到rings==1状态并终止。您可以将其想象为二叉树,其分支处于else状态,其叶子处于if状态。

答案 4 :(得分:0)

else分支中,呼叫以rings - 1完成。由于您永远不会增加它,最终rings1并且if分支将被点击。由于此分支中不发生递归,因此该方法终止。

答案 5 :(得分:0)

每次调用move_rings函数时,响铃次数减1。最终,响铃次数为1。 但是,这段代码确实可以产生无限循环,因为它编写得不好。从不检查环数大于1.因此,如果在main函数中输入的环数小于1,则永远不会达到停止递归的条件。

答案 6 :(得分:0)

move_rings调用move_rings时,函数的第二次调用将彻底恢复。它有一组完全独立的变量。就像move_rings调用任何其他函数一样。它碰巧是调用具有相同名称并包含相同逻辑的“另一个函数”。

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