6.1 递归的概念
递归算法定义:一个算法直接或间接调用自己本身的算法
两种情况使用:
(1)问题的定义是递推的
阶乘函数
(2)问题的解法存在自调用
有序数组中查找一个数据元素是否存在的折半查找算法:
查找数组元素中的值17
6.2 递归算法的执行过程
阶乘函数的执行过程:
折半查找的执行过程:
6.3 递归算法的设计方法
适合于用递归算法求解的问题的充分必要条件:
(1)问题具有某种可借用的类同自身的子问题描述的性质
(2)某一有限步的子问题有直接的解的存在
设计递归算法的方法:
(1)把对原问题的求解设计成包含有对子问题求解的形式
(2)设计递归出口
举例:汉诺塔问题
Move Disk I from Peg X to Peg Y
示意图如下:
编写程序:
#include<stdio.h>
#include<stdlib.h>
//递归算法设计
void Towers(int n,char fromPeg,char toPeg,char auxPeg)
{
if(n==1) //递归出口
{
printf("%s%c %s%c\n","move disk 1 from peg",fromPeg,"to peg",toPeg);
return;
}
Towers(n-1,fromPeg,auxPeg,toPeg); //将n-1个圆盘从fromPeg借助toPeg移到auxPeg
printf("%s %d %s%c %s%c\n","move disk",n,"from peg",fromPeg,"to peg",toPeg);
//将圆盘n由fromPeg直接移至toPeg
Towers(n-1,auxPeg,toPeg,fromPeg); //将n-1个圆盘从auxPeg借助fromPeg移至toPeg
}
void main(void)
{
Towers(4,'A','C','B');
system("pause");
}
6.4 递归过程和运行栈
对于非递归函数,执行函数前,系统要保存两类信息:
(1)调用函数的返回地址
(2)调用函数的局部变量值
当执行完被调用函数、返回调用函数前,系统恢复斯奥用函数的局部变量,然后返回调用函数的返回地址
递归函数在被调用过程中类似,但保存信息的方法不同。递归函数运行前系统也需要保存两类信息,但递归函数是最后被调用的函数要最先返回,由于堆栈后进先出的特点与递归函数的特点吻合,所以使用堆栈来保存递归函数调用时的信息
运行时栈:系统用于保存递归函数调用信息的堆栈
工作记录:每一层递归调用所需保存的信息,在进入下一层递归调用时,系统就建立一个新的工作记录,并把这个工作记录进栈成为运行时栈新的栈顶,每返回一层递归调用,就退栈一个工作记录
活动记录:栈顶的工作记录
举例递归调用阶乘运算:
注:系统的运行时栈中保存的调用函数的返回地址为系统动态分配的地址
6.5 递归算法的效率分析
6.6 *递归算法到非递归算法的转换