220 likes | 458 Views
第 11 章 递归. 递归的定义 常见递归问题 递归的实现 递归转化为非递归的一般过程 递归的时间和空间复杂度. 递归的定义. 概念: 递归: 一个事件或对象部分的由自己组成,或者按它自己来定义。 递归算法分类: 递推: 为得到问题的解,将其推到比原来问题简单的问题求解上。 回归: 简单问题得到解后,回归到原问题的解上。. 递归函数分类: 直接递归: 函数直接调用本身。 A( ) {…… CALL A( ) ...... } 间接递归: 一函数在调用其他函数时,又产生了对自身的调用。
E N D
第11章 递归 递归的定义 常见递归问题 递归的实现 递归转化为非递归的一般过程 递归的时间和空间复杂度
递归的定义 概念: 递归:一个事件或对象部分的由自己组成,或者按它自己来定义。 递归算法分类: 递推:为得到问题的解,将其推到比原来问题简单的问题求解上。 回归:简单问题得到解后,回归到原问题的解上。
递归函数分类: 直接递归:函数直接调用本身。 A( ) {…… CALL A( ) ...... } 间接递归:一函数在调用其他函数时,又产生了对自身的调用。 A( ) B( ) {…… {…… CALL B() CALL A() …… } …… }
常见递归问题 汉诺塔问题 八皇后问题 组合公式的计算
汉诺塔问题 问题描述:有三个命名为A、B、C的塔座,在塔座A上插有n个直径各不相同的,从小到大依次编号为1,2,3,……,n的圆盘,编号越大的圆盘其直径越大;要求将A轴上的n个圆盘全部移至塔座C上并仍按同样顺序叠放,并且圆盘移动时必须遵循下列规则: 每次只能移动一个圆盘。 圆盘可以插入A、B、C中任一个塔座上。 任何时候都不能将一个较大的圆盘压在较小的圆盘上。
汉诺塔问题的递归算法: void hanoi ( int n, char x, char y, char z) {/*递归算法*/ if(n= =1) move(x,z); else { hanoi(n-1,x,z,y);/*把N-1个盘子从X借助Z移到Y*/ printf(”%c-%c\n”, x,z);/*把盘子N从X直接移到Z*/ hanoi(n-1,y,x,z);/*把N-1个盘子从Y借助X移到Z */ } } 返回
八皇后问题 问题描述:在一个88的棋盘上放置8个皇后,那么n个皇后的问题就是在nn的棋盘上放置n个皇后。 规则:不允许两个皇后在同一行,同一列或同一对角线上。 图示:
八皇后问题的算法: Void Eight_que(int q) { int i,j; while(i<max_N) { if (search(q,i)!= null) { queen[q]=j; if(q=max_n-1) { for(j=1;j<max_n;j++) printf(“%d,%d”,j, queen (j));} else Eight_que(q+1);} i++;} }
int search(int x,int i) { int j,m,atk; atk=0; j=1; while(atk = =0) && (j < x)) { m= queen[j]; atk=(m= =i)||(abs(m-i)= = abs(j-x)); j++; } return(atk); }/*search*/ 返回
组合公式的计算 问题描述: 递归的实现: 采用递归算法具备的条件: 要解决的问题可以转化成另一个问题,解决新问题的方法与原始问题的解决方法相同。 必须具备终止递归的条件。 递归的实现机制: 分配调用过程函数所需要的数据区。 保存返回地址,传递参数信息 。 把控制权转移给被调用函数。
被调用函数运行结束后需完成的工作: 保存返回时的有关信息。 释放被调有函数占用的数据区。 按调用时保存的返回地址,把控制权转移到调用函数中调用语句的下一条语句。 递归工作栈 的变化:
实例1--求n!的算法: int Dg( int n) { long y; int x; x=n-1; if (n<0) return error; else if ( n = =0|| n = =1 ) return(1); else y= Dg(x) return(Dg(x) * n); }
n n=0或n=1 实例3--斐波那齐数列(Fibonacci Number)的递归算法: fib(n)= int fib(int n) { if(n<=1) return( n); Else return(fib(n-1)+fib(n-2)); } fib(n-1)+fib(n-2) n>1
递归转化为非递归的一般过程 转换步骤: 写出问题的递归形式。 转换成模拟形态,包括准备所有栈和临时地址。 除去多余的栈和变量。 得到一有效的非递归程序。
实例--斐波那齐数列的非递归算法: void fib(int n) { int prev,now,next,j; if(n<=1)return(n); else { prev=0; now=1; for(j=2;j<=n;j++) { next=prev+now; prev=now; now=next; } return(next);} }
递归的时间和空间复杂度 实例讨论:非递归的实现6!的算法 Int Dg( ) { int i, result; result=1; for (i= =1; i<6; i++) result=result*i; return result; } 时间复杂度为:T(6)=O(1) 空间空间复杂度:O(1)
6!递归实现的算法: int Dg(n) {/*递归调用函数*/ int f; if (n<0) return error; else if (n= =0|| n= =1) f=1; else f=dg(n-1)*n; return(f ); } 时间复杂度:T(6)=O(f1(6))+O(f2(6)) 空间复杂度比非递归的要大。