折耳布偶 发表于 2022-9-22 15:33:38

关于递归的课后作业题

在本代码中,用户输入5,得到结果为:5 4 3 2 1 0 0 0 1 2 3 4
我的问题是:在执行up_and_down函数时 先进入5 然后打印5 然后if语句执行up_and_down函数 再下面一行的打印语句根本没有被执行那么答案中的最后几个数字0 1 2 3 4 是怎么打印出来的呢?求分析up_and_down函数的具体执行过程。
#include <stdio.h>

void up_and_down(int n);

void up_and_down(int n)
{
      printf("%d ", n);
      if (n > 0)
      {
                up_and_down(--n);
      }
      printf("%d ", n);
}

int main(void)
{
      int n;

      printf("请输入一个整数:");
      scanf("%d", &n);

      up_and_down(n);
      putchar('\n');

      return 0;
}

jackz007 发表于 2022-9-22 16:19:36

本帖最后由 jackz007 于 2022-9-22 16:28 编辑

void up_and_down(int n)
{
      printf("%d ", n);
      if (n > 0)
      {
                up_and_down(--n);
      }
      printf("%d ", n);
}
      一共递归 6 次,每次递归,在入口要打印一个 n,在出口打印一个 n - 1(n == 0 时例外),这个没问题吧,那就看看 6 次递归的打印内容吧:
第1次:5
第2次:       4
第3次:            3
第4次:               2
第5次:                      1
第6次:                           0
第6次:                           0
第5次:                      0
第4次:               1
第3次:            2
第2次:       3
第1次:4
         第 6 次比较特殊,因为已经到底了,所以,没有参与递归,也就没有 -- n 的过程,所以,两个口打印的都是 0 值。
         把这些数值按照从上到下的顺序写到一起,就是你所看到的打印内容了。

折耳布偶 发表于 2022-9-22 16:47:06

jackz007 发表于 2022-9-22 16:19
一共递归 6 次,每次递归,在入口要打印一个 n,在出口打印一个 n - 1(n == 0 时例外),这个没 ...

感谢指点,还是没搞懂执行为什么n-1会被打印。不是在if语句就直接重新开始该函数了吗,为什么最后一行打印n-1会被执行呢

jackz007 发表于 2022-9-22 16:49:00

折耳布偶 发表于 2022-9-22 16:47
感谢指点,还是没搞懂执行为什么n-1会被打印。不是在if语句就直接重新开始该函数了吗,为什么最后一行打 ...

      那是它在调用自己,调用完还会继续执行后面的语句,调用自己和调用另外一个函数没有什么区别。

折耳布偶 发表于 2022-9-22 16:49:53

jackz007 发表于 2022-9-22 16:49
那是它在调用自己,调用完还会继续执行后面的语句,调用自己和调用另外一个函数没有什么区别。

明白了 谢谢

howzyao 发表于 2022-9-23 02:00:33

jackz007 发表于 2022-9-22 16:49
那是它在调用自己,调用完还会继续执行后面的语句,调用自己和调用另外一个函数没有什么区别。

调用自己和调用另外一个函数没有什么区别

谢谢,这句话太好了

howzyao 发表于 2022-9-23 02:41:25

本帖最后由 howzyao 于 2022-9-23 03:37 编辑

先看上半部分,--n行的上半部分。
54321进去函数体,依次打印,但每次执行函数,
都未完成,
所以,都是上面的printf打的。

第6次if,导致0入参,所以,
第1个0,由上面一个print打印出,
此时,是进去了函数体,打印第1个0后,if不执行,
此时,同一时间,同一空间,完成了函数的调用。
但第0进入的那一次,打了2个0
以5432100,的状态,结束。

这时,来到右大括号。
这时的右大括号,可以理解成 完成本次调用,
这也是首次一个 函数体 的执行完毕。

也就是函数调用自己6次的最里层。这是精髓。

函数体退出,自然是一层一层地退出,
先是第6层开始退出,
此时就来到了 高级鱼油jackz007
所说的“另外一个函数开始调用自己”这个状态。

我理解的呢,就是退出函数。也就是说,
退出第6层,下面的printf打0,
这个0是0入参的 同一空间 不同时间的 产物:
本函数体终于
到右花括号
前半部分简单逻辑结束了。

后半部分,重要逻辑来了:
此时应当试想,当初5次调用函数时,
函数体执行完毕了吗?没有,那就只能接着执行,
这就是所谓的 “退出函数体”的概念,
退出第5层,下面的printf接着打1,这个1是不同时间,相同空间的产物,接着到右花括号,
结束5次调用,退到4次调用,该打几?不用说了吧?
。。。直到第n次以 n-1入参==最后1次 第5次以5-1入参打出4
万事大吉,圆满收工。

这是我自己理解的 递归 不知道是不是这个原理。
请广大鱼油审阅。

howzyao 发表于 2022-9-23 03:49:59

本帖最后由 howzyao 于 2022-9-23 03:52 编辑

总结了一下,
实际上,递归,就是n*2+2的循环次数,且
以 n+1 个执行次数实现 递归函数体 的上半部分,
对此例:有
(n*2+2)/2=a(x)时,函数a平分变量x,且x取反向变化。

howzyao 发表于 2022-9-23 03:59:53

若放到我们做一个动作时,比如:
左看看(其实回中没有表达)右看看
这么一个动作,可以用一个递归函数来表达:
void a(int&);
...
int direction=3;//入参
左边看时,4个动画,3210 归位。
右边看时,4个动画,0012 归位。
完美贴图 完美动作。

折耳布偶 发表于 2022-9-23 15:37:00

howzyao 发表于 2022-9-23 03:59
若放到我们做一个动作时,比如:
左看看(其实回中没有表达)右看看
这么一个动作,可以用一个递归函数来表 ...

感谢指点
页: [1]
查看完整版本: 关于递归的课后作业题