收藏 分享(赏)

计算机常用算法与程序设计教程 第3章 递归与分治.ppt

上传人:hwpkd79526 文档编号:4667509 上传时间:2019-01-06 格式:PPT 页数:38 大小:322.50KB
下载 相关 举报
计算机常用算法与程序设计教程 第3章 递归与分治.ppt_第1页
第1页 / 共38页
计算机常用算法与程序设计教程 第3章 递归与分治.ppt_第2页
第2页 / 共38页
计算机常用算法与程序设计教程 第3章 递归与分治.ppt_第3页
第3页 / 共38页
计算机常用算法与程序设计教程 第3章 递归与分治.ppt_第4页
第4页 / 共38页
计算机常用算法与程序设计教程 第3章 递归与分治.ppt_第5页
第5页 / 共38页
点击查看更多>>
资源描述

1、常用算法与程序设计,1,第 3 章,递归与分治,常用算法与程序设计,2,3.1 递归及其应用 3.2 分治法概述 3.3 分治法的基本应用 3.4 消除递归,主要内容,常用算法与程序设计,3,3.1 递归及其应用,3.1.1 递归与递归调用一个函数在它的函数体内调用它自身称为递归(recursion) 调用。使用递归要注意以下几点: (1) 递归就是在过程或函数里调用自身;(2) 在使用递增归策略时,必须有一个明确的递归结束条件,称为递归出口递归和分治是相统一的,递归算法中含有分治思想,分治算法中也常用递归算法。,常用算法与程序设计,4,例如有函数r如下: int r (int a) b=r(

2、a-1); return b; 这个函数是一个递归函数。但是运行该函数将无休止地调用其自身,这显然是不正确的。为了防止递归调用无终止地进行,必须在函数内有终止递归调用的手段。常用的办法是加条件判断,满足某种条件后就不再作递归调用,然后逐层返回。,常用算法与程序设计,5,3.1.2 递归应用,【例3.1】 用递归法计算n!。 分析 n!的计算是一个典型的递归问题。使用递归方法来描述程序,十分简单且易于理解。 步骤1 描述递归关系 递归关系是这样的一种关系。设U1,U2,U3,Un是一个序列,如果从某一项k开始,Un和它之前的若干项之间存在一种只与n有关的关系,这便称为递归关系。 注意到,当n=1

3、时,n!=n*(n-1)!(n=0时,0!=1),这就是一种递归关系。对于特定的k!,它只与k与(k-1)!有关。 步骤2 确定递归边界 在步骤1的递归关系中,对大于k的Un的求解将最终归结为对Uk的求解。这里的Uk称为递归边界(或递归出口)。在本例中,递归边界为k=0,即0!=1。对于任意给定的N!,程序将最终求解到0!。,常用算法与程序设计,6,确定递归边界十分重要,如果没有确定递归边界,将导致程序无限递归而引起死循环。例如以下程序: #include int f(int x)return(f(x-1); main()printf(f(5); 它没有规定递归边界,运行时将无限循环,会导致错

4、误。 步骤3 写出递归函数并译为代码 将步骤1和步骤2中的递归关系与边界统一起来用数学语言来表示,即n*(n-1)! 当n=1时 n!= 1 当n=0时 再将这种关系翻译为代码,即一个函数: long ff(int n) long f;if(n0) printf(“n0,input error“); else if(n=0|n=1) f=1;else f=ff(n-1)*n;return(f);,常用算法与程序设计,7,步骤4 完善程序 主要的递归函数已经完成,将程序依题意补充完整即可。 #include long ff(int n) long f;if(n0) printf(“n0,inpu

5、t error“); else if(n=0|n=1) f=1;else f=ff(n-1)*n;return(f); void main() int n;long y;printf(“n input a integer number:n“); scanf(“%d“,常用算法与程序设计,8,3.2 分治法概述,3.2.1 分治法基本思想在算法设计中,首先对求解问题进行系统的分析,之后将其分解成若干性质相同的子问题,所得结果称为求解子集,再对这些求解子集分别处理。如果某些子集还需分而治之,再递归的使用上述方法,直到求解子集不需要再细分为止。最后归并子集的解即得原问题的解。,常用算法与程序设计,9

6、,常用算法与程序设计,10,因而对分治法算法设计过程可以如下描述: 设原问题输入为an,简记为(1,n); 子问题为apaq,1pqn,简记为(p,q)。 已知: SOLUTION; int divide (int, int); int small (int, int); SOLUTION conquer (int, int); SOLUTION combine (SOLUTION, SOLUTION);,常用算法与程序设计,11,分治法的抽象控制算法为: SOLUTION DandC(p,q) /* divide and conquer */ if(small(p,q) return con

7、quer(p,q);elsem=divide(p,q);return combine( DandC(p,m), DandC(m+1,q) ); ,常用算法与程序设计,12,3.2.2 分治算法设计方法和特点,分治算法设计的两个基本特征: (1) 分治法求解子集是规模相同、求解过程相同的实际问题的分解。 (2) 求解过程反复使用相同的求解子集来实现的,这种过程可以使用递归函数来实现算法,也可以使用循环。用分治法设计出来的程序一般是一个递归算法,因而例3.4中是用递归来来实现的。,常用算法与程序设计,13,【例3.4】 在含有n个不同元素的集合an中同时找出它的最大和最小元素。 不妨设。 对求n个

8、数的最大和最小,可以设计出许多种算法,这里使用分治法设计求解。 1. 直接搜索 StraitSearch(n, 则有: 最好情况比较次数:n-1 最坏情况比较次数:2(n-1) 平均情况比较次数:3/2(n-1),常用算法与程序设计,14,2. 分治法 集合只有一个元素时:*max=*min=ai; 集合只有两个元素时:if(aiaj) *max=aj; *min=ai;else *max=ai; *min=aj; 集合中有更多元素时: 将原集合分解成两个子集, 分别求两个子集的最大和最小元素, 再合并结果。 算法如下: typedef struct ElemType max;ElemType

9、 min; SOLUTION; SOLUTION MaxMin(i, j) SOLUTION s, s1, s2;if(i=j) s.max=s.min=ai; return s; if(i=j-1) if(aiaj) s.max=aj; s.min=ai;else s.max=ai; s.min=aj; return s;,常用算法与程序设计,15,k=(i+j)/2; s1=MaxMin(i, k); s2=MaxMin(k+1, j); (s1.max=s2.max) ? (s.max=s1.max):( s.max=s2.max); (s1.min=s2.min) ? (s.min=s

10、1.min):( s.min=s2.min);return s; 输入一组数a=22,10,60,78,45,51,8,36,调用MaxMin函数,划分区间,区间划分将一直进行到只含有1个或2个元素时为止,然后求子解,并返回。,常用算法与程序设计,16,3.3 分治法的基本应用,3.3.1 数据查找与排序 【例3.5】 二分检索:已知n个按非降次序排列的元素an,查找元素x是否在表中出现,若找到,返回其下标值,否则返回一负数。 二分检索是数据查找中典型使用分治法的实例,常用算法与程序设计,17,原问题: (n, a0,an-1, x),数据分组: a0ak-2 ak-1 akan-1,三个子问

11、题: (k-1, a0,ak-2, x) (1, ak-1, x) (n-k, ak,an-1, x),常用算法与程序设计,18,递归算法int BinSearch1(p, q, x) int k=(p+q)/2;if(qak) return BinSearch1(k+1, q, x);,常用算法与程序设计,19,二元比较树,左子树上所有元素不比父节点元素值大,以有序表的中间元素为根节点的二分树,右子树上所有元素不比父节点元素值小,常用算法与程序设计,20,内节点: 成功检索 外节点: 不成功检索,二分检索树的深度,二元比较树的深度,常用算法与程序设计,21,3.3.2 计数逆序排名问题,一个

12、核心问题是对两个排名进行比较的问题。你对一组n个电影排名,然后一个协同过滤系统向他的数据库咨询来找有着“类似”排名的其他人。但是从数量上说什么嗜好的方式来度量两个人的排名由多相似呢?显然一个相等的排名是非常相似的,一个完全相反的排名是非常不同的;我们想要的是介于整个中间区域的东西。,常用算法与程序设计,22,先放下这个定义,考虑一个例子,其中的序列是1,4,1,3,5.在这个序列中有三个逆序:(2,1),(4,1),(4,3)。也存在一个几何方法把它形象化,如图3.6所示。我们把输入数的序列按照它们被提供的次序画出来,而下面的序列处于上升次序。然后我们在顶部表格中的每个数与下面表各种相同的数之

13、间划一条线段。每对交叉线段于在两个表格中相反次序的一对数即一个逆序对应。,常用算法与程序设计,23,注意逆序个数怎样作为一个度量使得他平滑的介于完全一致(当序列是上升的次序,那么没有逆序)与完全不一致(如果序列是下降的次序,那么每对数构成一个逆竖,并且因此存在个序列)之间。,常用算法与程序设计,24,3.3.3 投资问题,有一个高计算的投资公司咨询员,有下面类型的问题想要一次又一次的求解,这个问题的一个典型实例如下所述。他们正在做一项模拟,在这项模拟中他们从过去的某点开始对一支给定的股票连续看天,让我们把这些天的纪录为数;对每天,他们有当天这支股票每股的价格(为简单起见,假设这个价格在每一天之

14、内是固定的)。假设在这个时间区间内,某天他们想买1000股并且在以后的某天卖出所有的这支股。他们想知道:为了挣到最多的钱,他们应该什么时候买并且应该什么时候卖?,常用算法与程序设计,25,举例,假设那么你应该返回“2买,3卖”。 通过分治策略我们可以把在元素对上的蛮力搜索减少到时间。这里由于面对的是类似情况,让我们考虑可以怎样应用分治策略。,常用算法与程序设计,26,一种简单的方法将是分别考虑前天和后天,对这两个集合中的每一个问题递归的求解,然后指出怎样从这些用时间得到一个全局的解。这将给出常用的递推式,因此得到。 此外,为了使得事情更容易,将使用n是2的幂,这个通常的假定,这并不减少一般性:

15、如果是比n大的下一个2的幂,我们可以对在n与之间的所有i,令,以这种方式,我们不用改变答案,至多使输入的规模加倍。,常用算法与程序设计,27,3.4 消除递归,3.4.1消除递归 递归算法的特点符合人的递推求解问题的自然思维习惯算法的结构简单,代码精炼,可读性好效率低,常用算法与程序设计,28,消除递归的一般步骤例1:写一个递归函数 reverse (char * s),按逆序输出一个字符串,并将此递归算法改写成相应的迭代算法。,常用算法与程序设计,29,递归算法void reverse (char * s) if( *s!=0 ) reverse(s+1);putchar (*s);retu

16、rn;,常用算法与程序设计,30,输出s=”abc”的递归过程,常用算法与程序设计,31,改写的迭代算法void reverse (char * s) extern ElemType stack2*n+1, top=0;L1: if( *s!=0 ) stack+top=s; stack+top=L2; s=s+1;goto L1;L2: putchar(*s); / 接下来处理返回语句if(top=0 ) return; / 栈为空else addr=stacktop-; / 恢复地址s=stacktop-; / 恢复参数if(addr = L2) goto L2;,常用算法与程序设计,32

17、,优化后的迭代算法void reverse(char * s) int top=0;while(*s!=0) top+; s+; while (top!=0) putchar(*s);s-; top-;,常用算法与程序设计,33,例2:写一个求数组an中的最大元素的递归算法并将其改写成迭代算法。,分治的思路递归:,int max (int i) int j=i, k;if(iaj) k=i;else k=j;else k=n-1;return k; ,常用算法与程序设计,34,常用算法与程序设计,35,常用算法与程序设计,36,优化后的迭代算法int max (int i) int j, k=

18、n-1;for (j=n-2; j=i; j-)if (ajak) k=j;return k;,常用算法与程序设计,37,3.4.2 分治算法中的递归转化,抽象控制递归算法:SOLUTION DandC (p, q) /* divide and conquer */ int m; SOLUTION s1, s2, s; if( small (p, q) ) s=conquer (p, q);else m=divide (p, q);s1=DandC (p, m);s2=DandC (m+1, q);s=combine (s1, s2);return s;,常用算法与程序设计,38,抽象控制迭代

19、算法: SOLUTION DandC (p, q) extern ElemType stack5*n+1, top=0;int m; SOLUTION s1, s2; L1: if(small(p,q) s=conquer(p,q);else m=divide(p,q);stack+top=p; stack+top=q;stack+top=m; stack+top=L2;p=p; q=m;goto L1;L2: s1= stacktop-;stack+top=p; stack+top=q;stack+top=m; stack+top=L3;p=m+1; q=q;goto L1;L3: s2=stacktop-; s=combine(s1,s2);,if(top=0) return s;else addr=stacktop-;m=stacktop-;q=stacktop-;p=stacktop-;stack+top=s;if(addr=L2) goto L2;else goto L3; ,

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 实用文档 > 简明教程

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报