程序调用自身的编程技巧称为递归( recursion)。递归作为一种算法在程序设计语言中广泛应用。 一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。递归的能力在于用有限的语句来定义对象的无限集合。一般来说,递归需要有边界条件、递归前进段和递归返回段。当边界条件不满足时,递归前进;当边界条件满足时,递归返回。
递归算法一般用于解决三类问题: (1)数据的定义是按递归定义的。(Fibonacci函数) (2)问题解法按递归算法实现。 这类问题虽则本身没有明显的递归结构,但用递归求解比迭代求解更简单,如Hanoi问题。 (3)数据的结构形式是按递归定义的。 如二叉树、广义表等,由于结构本身固有的递归特性,则它们的操作可递归地描述。
递归的缺点: 递归算法解题相对常用的算法如普通循环等,运行效率较低。因此,应该尽量避免使用递归,除非没有更好的算法或者某种特定情况,递归更为适合的时候。在递归调用的过程当中系统为每一层的返回点、局部量等开辟了栈来存储。递归次数过多容易造成栈溢出等。
在我看来,递归算法是不停直接或间接调用自身函数,每次调用会改变一个或者多个变量,直到变量到达边界,结束调用。
递归常用于这类问题的解决:
1.斐波那契数列
#include<stdio.h>
const int MAX=101;
int a[MAX];
int f(int n)
{
if(a[n]!=-1) return a[n];
else
{
a[n]=f(n-1)+f(n-2);
return a[n];
}
}
int main()
{
int n;
scanf("%d",&n);
for(int i=0;i<=MAX-1;i++) a[i]=-1;
a[0]=0;a[1]=1;
printf("%d",f(n));
return 0;
}
2.汉诺塔
#include<stdio.h>
#include<stdlib.h>
static int count = 0;
void move(char getone, char putone) {
count ++;
printf("%c-->%c\n", getone, putone);
}
void hanoit(int n, char a, char b, char c) {
if(n == 1)
{
move(a, c);
}
else
{
hanoit(n - 1, a, c, b);
printf("count :%d\n",count);
move(a, c);
hanoit(n - 1, b, a, c);
}
}
int main() {
int m;
scanf("%d", &m);
hanoit(m, 'A', 'B', 'C');
printf("count :%d",count);
system("pause");
return 0;
}
3.杨辉三角
#include <stdio.h>
long Func(int r, int c) //杨辉三角算法函数
{
return (c == 1 || c == r) ? 1 : Func( r - 1, c - 1 ) + Func( r - 1, c );
}
int main()
{
int i, j, n;
printf("请输入杨辉三角形的行数(1 ~ 20):");
scanf("%d", &n);
for( i = 1; i <= n; i++) // 输出n行
{
for( j = 1; j <= i; j++)
printf("%4d", Func(i, j)); //计算并输出杨辉三角形
printf("\n");
}
return 0;
}