递归算法是把问题转化为规模缩小了的同类问题的子问题。然后递归调用函数(或过程)来表示问题的解。
1. 递归算法的概念
递归过程一般通过函数或子过程来实现。递归方法:在函数或子过程的内部,直接或者间接地调用自己的算法。
2. 递归算法的实现
(1)确定递归公式
(2)确定边界(终了)条件
3. 递归算法的典型实例
上楼问题/斐波那契数列
问题描述: 楼梯有n阶台阶,上楼可以一步上1阶,也可以一步上2阶,编一程序计算共有多少种不同的走法.
问题分析:设n阶台阶的走法数为f(n)
显然有
f(1) = 1;
f(2) = 2;
f(n)={f(n-1)+f(n-2)} n>2
递归结束条件: n = 1;
伪代码:
long kindnum(int num)//返回方法数
{
if(num==1)//1级返回1种方法
return 1;
else if(num==2)//2级返回2种方法
return 2;
else
return kindnum(num-1)+kindnum(num-2);//3级以上
}
数列:1,1,2,3,5,8,13,21,34,55…….,被称为斐波那契数列。
斐波那契数列特点:第一、第二个数为1
,从第三个数开始,该值等于其前面两个数之和。
伪代码如下:
function fB($n)
{
if ($n == 0 || $n == 1) {
return 1;
}
if ($n > 1) {
return fB($n - 1) + fB($n - 2);
}
}
汉诺塔问题:
当只有一个盘子的时候,只需要从将A塔上的一个盘子移到C塔上。
当A塔上有两个盘子是,先将A塔上的1号盘子(编号从上到下)移动到B塔上,再将A塔上的2号盘子移动的C塔上,最后将B塔上的小盘子移动到C塔上。
当A塔上有3个盘子时,先将A塔上编号1至2的盘子(共2个)移动到B塔上(需借助C塔),然后将A塔上的3号最大的盘子移动到C塔,最后将B塔上的两个盘子借助A塔移动到C塔上。
当A塔上有n个盘子是,先将A塔上编号1至n-1的盘子(共n-1个)移动到B塔上(借助C塔),然后将A塔上最大的n号盘子移动到C塔上,最后将B塔上的n-1个盘子借助A塔移动到C塔上。
综上所述,除了只有一个盘子时不需要借助其他塔外,其余情况均一样(只是事件的复杂程度不一样)。
#include <stdio.h>
//第一个塔为初始塔,中间的塔为借用塔,最后一个塔为目标塔
int i=1;//记录步数
void move(int n,char from,char to) //将编号为n的盘子由from移动到to
{printf("第%d步:将%d号盘子%c---->%c\n",i++,n,from,to);
}
void hanoi(int n,char from,char denpend_on,char to)//将n个盘子由初始塔移动到目标塔(利用借用塔)
{
if (n==1)
move(1,from,to);//只有一个盘子是直接将初塔上的盘子移动到目的地
else
{
hanoi(n-1,from,to,denpend_on);//先将初始塔的前n-1个盘子借助目的塔移动到借用塔上
move(n,from,to); //将剩下的一个盘子移动到目的塔上
hanoi(n-1,denpend_on,from,to);//最后将借用塔上的n-1个盘子移动到目的塔上
}
}
void main()
{
printf("请输入盘子的个数:\n");
int n;
scanf("%d",&n);
char x='A',y='B',z='C';
printf("盘子移动情况如下:\n");
hanoi(n,x,y,z);
}
递归的基本思想:
问题分解:
把一个不能或不好解决的大问题转化为一个或几个小问题,再把这些小问题进一步分解成更小的小问题, 最小问题可以直接解决。
递归算法解题通常有三个步骤:
1)分析问题、寻找递归:找出大规模问题与小规模问题的关系,这样通过递归使问题的规模逐渐变小。
2)设置边界、控制递归:找出停止条件,即算法可解的最小规模问题。
3)设计函数、确定参数:设计函数体中的操作及相关参数。