1.递归是什么
是一种解决问题的方法,函数就是自己调用自己被称为递归。
1.1递归的思想
将一个大型问题拆分(大事化小),递推,回归。
1.2递归的限制条件
递归是有限制条件的
每次递归之后越来越接近这个限制条件
2.递归举例
2.1 举例1:用递归求n的阶乘:
int Fact(int n)
{
if (n == 0)
return 1;
else
return n * Fact(n - 1);
}
int main()
{
int n = 0;
scanf("%d", &n);
int ret = Fact(n);
printf("%d ", ret);
return 0;
}
总结:输入3,进入函数,执行Fact(n-1),随后进行递推,在满足限制条件后,进行回归。
2.2 举例2:顺序打印整数的每一位
#include<stdio.h>
void Print(int n)
{
if (n > 10)
{
Print(n / 10);
}
printf("%d ", n % 10);
}
int main()
{
int n = 0;
scanf("%d", &n);
Print(n);
return 0;
}
总结:如输入1234,将1234的每一位递推出后,回归进行打印。
每一次函数调用,都会向内存栈区上申请一块空间,这一块空间主要是用来存放函数中的局部变量,和函数调用过程中的上下文的信息,这一块空间一般称为函数的运行时堆栈,也叫函数栈帧空间。编译器会自动根据需要开辟空间。当函数调用结束时这块空间会回收。(详情请见下节:函数栈帧的创建和销毁)
迭代的方式
#include<stdio.h>
int Fact(int n)
{
int i = 0;
int ret = 1;
for (i = 1; i <= n; i++)
{
ret = ret * i;
}
return ret;
}
非递归的效率更高
2.3 举例3:斐波那契问题
#include<stdio.h>
int Fib(int n)
{
if (n <= 2)
{
return 1;
}
else
return Fib(n - 1) + Fib(n - 2);
}
int main()
{
int n = 0;
scanf("%d", &n);
int ret = Fib(n);
printf("%d ", ret);
return 0;
}
迭代方式
int Fib(int n)
{
int a = 1;
int b = 1;
int c = 1;
while (n >= 3)
{
c = a + b;
a = b;
b = c;
n--;
}
return c;
}
拓展学习:
青蛙跳台阶问题
有一只青蛙一次可以跳一个台阶,也可以一次跳两个台阶,说跳到第n个台阶有多少种跳法?
青蛙第一次可能跳一级台阶或者两级台阶,你可以将每一次跳都当成第一次跳台阶,运用递归的思想解决问题,假设n=4,第一次跳了一节台阶,那么还剩三节台阶,第一次跳了两阶台阶,那么还剩两节没有跳,将这两种情况相加。
代码如下:
#include<stdio.h>
int Jump(int n)
{
if (n == 1)
return 1;
else if (n == 2)
return 2;
else
return Jump(n - 1) + Jump(n - 2);
}
int main()
{
int n = 0;
scanf("%d", &n);
int ret = Jump(n);
printf("%d\n", ret);
return 0;
}
汉诺塔问题
有ABC三个柱子,A上有n个盘子,现要求把A上的盘子移动到C上,并且保证每次移动大盘子在小盘子下边。