30天学会C语言: Day 13-递回体验镇魂曲

递回

在函式里面可以呼叫函式本身

下面例子中,fun() 会先将参数 x 显示到视窗上,之後判断 x 是不是不等於0,若不等於0则呼叫 fun(x-1),如果等於0则不做任何动作(因为之後没有内容了,所以函式会结束)

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

void fun(int x){
	printf("%d ", x);
	if(x!=0)
		fun(x-1);
}

int main(){
	fun(5);

	return 0;
}

所以这段程序执行时,main() 会先呼叫 fun(5),在函式 fun() 中:

  1. 会先显示 x(5)到视窗上,因为 x 不等於0,所以会呼叫 f(x-1),也就是 f(4)
  2. 显示 x(4)到视窗上,因为 x 不等於0,所以会呼叫 f(x-1),也就是 f(3)
  3. 显示 x(3)到视窗上,因为 x 不等於0,所以会呼叫 f(x-1),也就是 f(2)
  4. 显示 x(2)到视窗上,因为 x 不等於0,所以会呼叫 f(x-1),也就是 f(1)
  5. 显示 x(1)到视窗上,因为 x 不等於0,所以会呼叫 f(x-1),也就是 f(0)
  6. 显示 x(0)到视窗上,因为 x 等於0,不执行任何动作,fun() 会结束并回到 main()

这样类似回圈可以重复的效果称为递回(Recursion)

递回的优点

递回执行时花费的资源可能比用回圈还大,设计时可能也比回圈还难,但递回还是有回圈无法达到的优点

回圈中如果有用到其他几次计算的结果,需要另外用一个阵列将每次的执行结果记录下来
例如费波那契数列,这个数列的第一项(x=0)是0和第二项(x=1)为1,之後的每一项都是前两项的和,也就是:

如果用回圈,必须搭配一个阵列纪录每个 F() 的值

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

int main(){
	int n, f[100];
	scanf("%d", &n);
	for(int i=0; i<=n; i++){
		if(i==0)
			f[i]=0;
		else if(i==1)
			f[i]=1;
		else
			f[i]=f[i-1]+f[i-2];
	}
	printf("%d\n", f[n]);

	return 0;
}

用递回编写程序时更加直观
这里的 F() 可以不用 if elseelse,因为执行的内容都是 return,会强制结束函式
所以对第一个 if() 来说,如果条件符合会执行 return 0,後面的内容被不会执行,如果条件不符才会执行後面的内容,对第二个 if() 来说也是,也就是说只有前两个的条件都不符才会执行最後一行,如果前面的条件符合了也一定不会执行後面的内容,所以可以确定这三个 return 一定只会执行其中一个

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

int F(int x){
	if(x==0)
		return 0;
	if(x==1)
		return 1;
	return F(x-1)+F(x-2);
}

int main(){
	int n;
	scanf("%d", &n);
	printf("%d\n", F(n));

	return 0;
}

另外递回也常和一些资料结构一起使用,之後会有相关范例,这个就下次再说吧!


<<:  Context Diagram 系统上下文图

>>:  30天学会 Python: Day 13-站在巨人的肩上

玩转 Storybook: Day 30 总结 & 学习资源

根据研究指出,重用程序码可以节省42–81%的时间,并提高生产力 40%。易於共享UI元件的Desi...

Day23|【Git】各种合并冲突与分别解决方式

了解分支的用途後,在合作开发上一定便利许多,但同样地,不是每件事情都顺顺利利,只要有合作的事情,总是...

专案小帮手- Vue CLI

前言 Vue CLI 是用来快速建置 Vue 开发环境的一套工具,它是由 Vue.js 团队所建立的...

JS 宽松相等、严格相等以及隐含转型 DAY54

严格相等 型别与内容 "皆" 需相等 // 内容一样 型别不一样 false c...

[Day01] 写给现在与将来的主管

我相信,很少人是做好准备才当上主管。通常是凭自己的技术过硬、绩效超群而被赋予领导职,然後开始学管理。...