需要解释“河内之塔”中的递归调用

时间:2014-02-10 14:58:55

标签: c recursion towers-of-hanoi

我理解递归的概念以及它如何与每次调用叠加。但我无法解释递归调用是如何工作的,并且当有两个函数调用由printf命令分隔时会被打印。任何人都可以向我解释这个递归调用是如何工作的吗?

我找到了一个名为“河内之塔”的游戏示例。 Ut被用作递归的一个例子。代码:

#include <stdio.h>

void transfer(int n, char from, char to, char temp);

int main()
{
    int n;

    printf("how many disk");
    scanf("%d", &n);
    printf("\n");
    transfer(n, 'L', 'R', 'C');
    return 0;
}

/*
 * n = number of disk,
 * from = origin,
 * to = destination,
 * temp = temporary storage
 */
void transfer(int n, char from, char to, char temp)
{
    if (n > 0) {
        // Move n-1 disks from origin to temporary
        transfer(n - 1, from, temp, to);

        // Move n th disk from origin to destination
        printf("move disk %d from %c to %c\n", n, from, to);

        // Move n-1 disks from temporary to destination
        transfer(n - 1, temp, to, from);
    }
}

对于n=3,它会提供这样的输出

move disk 1 from L to R //
move disk 2 from L to C // 
move disk 1 from R to C // 
move disk 3 from L to R // 
move disk 1 form C to L // 
move disk 2 from C to R //
move disk 1 from L to R //

2 个答案:

答案 0 :(得分:1)

我写了this post来回答这个问题,我相信很多初学者都会面对这个问题。

当您拥有n个磁盘时会发生什么。

任务是将n个磁盘从L移动到RT,这可以分解为:

  1. n-1磁盘从L移至T
  2. 将底部磁盘从L移至R
  3. n-1磁盘从T移至R
  4. 现在请注意,步骤1和3本身就是一个有n-1磁盘和不同源和目标极点的河内塔问题。步骤1是将n-1个磁盘从L移动到TR的问题,步骤2是从n-1移动T磁盘的问题到RL

    因此问题被分解为可以一步解决的子问题,这是一个2磁盘问题实例。

    1. 将顶部磁盘从L移至T
    2. 将底部磁盘从L移至R
    3. 将顶部磁盘从T移至R

答案 1 :(得分:0)

你可能会想到一个名为“end-recursive”的特殊变体的递归! 河内算法塔不是末端递归的。相反,它甚至使用递归两次:

  1. 将N-1个磁盘在磁盘N上方移动到临时堆栈(第一次传输()函数调用)
  2. 将磁盘N移动到目标堆栈(printf)
  3. 将N-1个磁盘从临时堆栈移回目标bove磁盘N(第二次传输()函数调用)
  4. transfer()函数递归背后的想法是:如果调用n> 1个磁盘进行操作,它会将'work'委托给自己的递归调用。如果使用n == 1调用它只是移动磁盘。

    这是一个修改后的版本,应该让事情更清楚:

    void transfer(int n, char from, char to, char temp)
    {
        if (n > 1) {
            // Move n-1 disks from origin to temporary
            transfer(n - 1, from, temp, to);
        }
    
        // Move n th disk from origin to destination
        printf("move disk %d from %c to %c\n", n, from, to);
    
        if (n > 1) {
            // Move n-1 disks from temporary to destination
            transfer(n - 1, temp, to, from);
        }
    }