1.定义
- 循环:反复执行某一区域的代码。(如果不加控制,就会形成死循环)
- 递归:在函数体内直接或间接调用函数本身。(如果不加控制,无休止调用自身,直到堆栈溢出)
2.使用循环或递归所要满足的条件
- 循环:
(1)实际问题中有许多具有规律性的重复操作。
(2)必须要有结束循环的终止条件。
- 递归:
(1)把要解决的一个问题转化为一个新的问题,而新的问题的解决方法与原问题的解决方法相同,只是所处理的问题规模不一样,通常规模是越来越小。
(2)可以应用这个转化过程使问题得到解决。
(3)必须要有一个明确结束递归的条件。
3.使用循环或递归的例子
- 求阶乘
(1)循环
double Fact(int n)
{
double sum=1.0;
for(int i=1;i<=n;i++)
sum*=i;
return sum;
}
(2)递归
Fact(n) = n! = 1 x 2 x 3 x ... x (n-1) x n = (n-1)! x n = Fact(n-1) x n
double Fact(int n)
{
if(!n)
return 1.0;
return (n*Fact(n-1));
}
- 斐波那契数列(即 1,1,2,3,5,8,13……)
(1)循环
int fab(int n)
{
int a=0,b=1,c=1;
if(n==1 || n==2)
return 1;
else
{
for(int i=3;i<=n;i++)
{
a=b;
b=c;
c=a+b;
}
return c;
}
}
(2)递归
int fib(int n)
{
if(n==1 ||n==2)
return 1;
else
return fib(n-1)+fib(n-2);
}
- 汉诺塔游戏
有三根杆子A,B,C。A杆上有N个(N>1)穿孔圆盘,盘的尺寸由下到上依次变小。要求按下列规则将所有圆盘移至C杆:
每次只能移动一个圆盘;
大盘不能叠在小盘上面。
提示:可将圆盘临时置于B杆,也可将从A杆移出的圆盘重新移回A杆,但都必须尊循上述两条规则。
问:如何移?最少要移动多少次?
递归void hanio(char a,char b,char c,int n) //将n个盘子从a挪到c
{
if(n==1)
printf("%c-->%c\n",a,c);
else
{
hanio(a,c,b,n-1);//将n-1个盘子从a挪到b
printf("%c-->%c\n",a,c);//将最后一个盘子从a移到c
hanio(b,a,c,n-1);//将n-1个盘子从b挪到c
}
}
在本题中不建议使用循环,原因将在下面循环优缺点中讲述。
4.循环及递归的优缺点
- 循环:
(1)优点:循环方法比递归快,因为循环避免了一系列函数调用和返回中所涉及的参数传递和返回值的额外开销。
(2)缺点:对于复杂的解,代码量大,可读性不好。
- 递归:
(1)优点:程序代码简洁,逻辑性好,可读性高。
(2)缺点:时间和空间的消耗比较大,效率降低。(压栈和出栈操作)