定义
一个函数直接或间接调用自己
不同函数之间的相互调用
# include <stdio.h>
void f();
void g();
void k();
void f()
{
printf("FFF\n");
g();
printf("1111\n");
}
void g()
{
printf("GGG\n");
k();
printf("2222\n");
}
void k()
{
printf("KKK\n");
}
int main(void)
{
f();
return 0;
}
自己调用自己
# include <stdio.h>
void f(int n)
{
if (n == 1)
printf("哈哈\n");
else
f(n-1);
}
int main(void)
{
f(3);
return 0;
}
递归举例 — 求阶乘
(1)阶乘的循环实现
# include <stdio.h>
int main(void)
{
int val;
int i, mult = 1;
printf("请输入一个数:");
printf("val = ");
scanf("%d", &val);
for (i=1; i<=val; i++)
mult *= i;
printf("%d的阶乘是:%d", val, mult);
return 0;
}
(2)阶乘的递归实现
# include <stdio.h>
long f(long n)
{
if (1 == n)
return 1;
else
return f(n-1) * n;
}
int main(void)
{
printf("%d\n", f(100));
}
递归举例—求1+2+…+100的和
# include <stdio.h>
long sum(int n)
{
if (1 == n)
return 1;
else
return sum(n-1) + n;
}
int main(void)
{
printf("%ld\n", sum(100));
return 0;
}
函数调用
递归满足的三个条件
(1)递归必须得有一个明确的终止条件
(2)该函数所处理的数据规模必须在递减
(3)这个转化必须是可解的
递归和循环之间的关系
所有的循环都可以用递归实现,递归不一定都可以用循环实现。
递归:易于理解,处理速度慢,存储空间大
循环:不易理解,处理速度快,存储空间小
递归举例—汉诺塔
汉诺塔的由来:
汉诺塔是源自印度神话里的玩具。上帝创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按大小顺序摞着64片黄金圆盘。上帝命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘的上面不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。有预言说,这件事完成时宇宙会在一瞬间闪电式毁灭。也有人相信婆罗门至今还在一刻不停地搬运着圆盘。
伪算法
if(n>1)
{
先把A柱子上的前n-1个盘子从A借助C移到B
将A柱子上的第n个盘子直接移到C
再将B柱子上的n-1个盘子借助A移到C
}
# include <stdio.h>
void hannuota(int n, char A, char B, char C)
{
/*
若果是1个盘子
直接将A柱子上的盘子从A移到C
否则
现将A柱子上的n-1个盘子借助C移到B
直接将A柱子上的盘子从A移到C
最后将B柱子上的n-1个盘子借助A移到C
*/
if (1 == n) {
printf("将编号为%d的盘子直接从%c柱子移到%c柱子\n", n, A, C);
} else {
hannuota(n-1, A, C, B);
printf("将编号为%d的盘子直接从%c柱子移到%c柱子\n", n, A, C);
hannuota(n-1, B, A, C);
}
}
int main(void)
{
hannuota(7, 'A', 'B', 'C');
return 0;
}
递归的应用
(1)树和森林就是以递归的方式定义的
(2)树和图的很多算法都是以递归来实现的
(3)很多数学公式就是以递归的方式定义的,比如斐波那契数列