在C中可视化递归

时间:2016-07-12 17:35:22

标签: c recursion printing

我试图了解递归如何在阶乘函数中起作用。我应该打印什么,以便我可以看到每次递归调用期间实际发生了什么? 这是代码:

#include <stdio.h>
#include <stdlib.h>


long factorial(long number) {
  if(number <= 1) {
    return 1;
  } else {
    return number * factorial(number - 1);
  }
}

int main() {
  int i;

  for(i = 0; i <= 10; i++) {
    printf("%2d ! = %ld\n", i, factorial(i));
  }

  return 0;
}

5 个答案:

答案 0 :(得分:4)

以下代码

#include <stdio.h>
#include <stdlib.h>


long factorial (int level, long number){
    int result;
    printf("[%03d] Calculating: %d\n", level, number);

    if(number <= 1)
    {
        result = 1;
    }
    else
    {
        result = number * factorial(level+1, number - 1);
    }

    printf("[%03d] Returning:   %d\n", level, result);
    return result;
}
int main(){
    int i;
    for(i = 0; i <= 10; i++)
    {
        printf("%2d ! = %ld\n", i, factorial(0, i));
    }
    return 0;
}

给出了这个输出

[000] Calculating: 10
[001] Calculating: 9
[002] Calculating: 8
[003] Calculating: 7
[004] Calculating: 6
[005] Calculating: 5
[006] Calculating: 4
[007] Calculating: 3
[008] Calculating: 2
[009] Calculating: 1
[009] Returning:   1
[008] Returning:   2
[007] Returning:   6
[006] Returning:   24
[005] Returning:   120
[004] Returning:   720
[003] Returning:   5040
[002] Returning:   40320
[001] Returning:   362880
[000] Returning:   3628800
10 ! = 3628800

其中[XXX]是当前的递归级别。

答案 1 :(得分:2)

试试这个

long factorial (long number){
if(number <= 1){
    return 1;
}else{
    return number * factorial(number - 1);

}
}

假设我们将4作为第一个参数传递,然后函数求值为:

long factorial (long number /*==4*/){
if(4 <= 1){//false
    return 1;
}else{
    return 4 * factorial(4 - 1);

}
}

注意返回in else无法完成,因为它调用另一个函数 - factorial(4-1)。 所以4必须乘以阶乘(3)的结果。所以它去执行阶乘(3)。

现在我们得到

long factorial (long number /*==3*/){
if(3 <= 1){//false
    return 1;
}else{
    return 3 * factorial(3 - 1);

}

}

但是这里的回归再次无法完成,因为它将因子称为3-1 = 2。

现在需要评估阶乘(2),其结果将乘以3并传递给前一次返回。再次:

long factorial (long number /*==2*/){
if(2 <= 1){//false
    return 1;
}else{
    return 2 * factorial(2 - 1);

}

}

我们有类似的问题。但是现在当执行阶乘(2-1)时,函数将立即返回1,因此上面的行将返回2.

此结果将插入前一次返回的结果,给出2 * 3;这个结果 - 6 - 将插入前一次返回并产生6 * 4,这是最终结果24。

答案 2 :(得分:2)

对于一些荒谬的事情,要考虑factorial的主体:

long factorial_body(long number) {
  if(number <= 1) {
    return 1;
  } else {
    return number * factorial(number - 1);
  }
}

然后,重写factorial以致电factorial_body,在通话中打印一些内容。

long factorial (long number) {
    static char output[4096];
    static int level;
    static int index;
    int saved_index;
    long result;
    switch (level++) {
    case 1:  index += snprintf(output + index, sizeof(output) - index, "= ");
    default: index += snprintf(output + index, sizeof(output) - index,
                               "%ld x ", number + 1);
    case 0:  snprintf(output + index, sizeof(output) - index,
                      "factorial(%ld)\n", number);
    }
    saved_index = index;
    printf("%s", output);
    result = factorial_body(number);
    index = saved_index;
    snprintf(output + index, sizeof(output) - index,
             --level ? "%ld\n" : "= %ld\n", result);
    printf("%s", output);
    return result;
}

factorial(10)将生成以下输出:

factorial(10)
= 10 x factorial(9)
= 10 x 9 x factorial(8)
= 10 x 9 x 8 x factorial(7)
= 10 x 9 x 8 x 7 x factorial(6)
= 10 x 9 x 8 x 7 x 6 x factorial(5)
= 10 x 9 x 8 x 7 x 6 x 5 x factorial(4)
= 10 x 9 x 8 x 7 x 6 x 5 x 4 x factorial(3)
= 10 x 9 x 8 x 7 x 6 x 5 x 4 x 3 x factorial(2)
= 10 x 9 x 8 x 7 x 6 x 5 x 4 x 3 x 2 x factorial(1)
= 10 x 9 x 8 x 7 x 6 x 5 x 4 x 3 x 2 x 1
= 10 x 9 x 8 x 7 x 6 x 5 x 4 x 3 x 2
= 10 x 9 x 8 x 7 x 6 x 5 x 4 x 6
= 10 x 9 x 8 x 7 x 6 x 5 x 24
= 10 x 9 x 8 x 7 x 6 x 120
= 10 x 9 x 8 x 7 x 720
= 10 x 9 x 8 x 5040
= 10 x 9 x 40320
= 10 x 362880
= 3628800

如果以上输出有助于增强您对递归的理解,我很怀疑。但是,努力了解打印代码的工作原理可能会更好地理解递归。

答案 3 :(得分:1)

而不是print语句添加您要打印到数组或其他内容的任何内容,然后在递归函数完成后按插入顺序(fifo)打印出来。

答案 4 :(得分:1)

这应该会让你跟踪 factorial 的执行情况,并带有缩进:

long factorial(long number, int depth){
    printf("%*s enter, number = %d\n", 4*depth, "", number);
    long result = 1;
    if (number > 1) result = number * factorial(number-1, depth+1);
    printf("%*s exit,  result = %d\n", 4*depth, "", result);
    return result;
}