数据结构-第五部分.ppt
《数据结构-第五部分.ppt》由会员分享,可在线阅读,更多相关《数据结构-第五部分.ppt(82页珍藏版)》请在三一办公上搜索。
1、1,第15章 算法设计技术,枚举法贪婪法分而治之法动态规划回溯法随机算法,介绍通用的算法设计模式,2,枚举法,枚举法适合于解的候选者是有限、可枚举的场合。枚举法就是对可能是解的众多候选者按某种顺序进行逐一枚举和检验,从中找出符合要求的候选解作为问题的解。基于枚举法的算法一般都比较直观,容易理解。但由于要检查所有的候选解,因此时间性能较差,3,枚举法实例,用50元钱买了三种水果:西瓜、苹果和桔子。各种水果加起来一共100个。假如,西瓜5元一个,苹果1元一个,桔子1元3个,设计一算法输出每种水果各买了几个。,4,约束条件,三种水果一共100个;买三种水果一共花了50元。如果西瓜有mellon个,苹
2、果有apple个,桔子有orange个,那么:mellon+apple+orange 等于100 5*mellon+1*apple+orange/3等于50。,5,直观的枚举,For(mellon=1,mellon 99;+mellon)For(apple=1,apple 99;+apple)For(orange=1;orange 99;orange)If(mellon+apple+orange 等于100 并且 5*mellon+1*apple+orange/3等于50)输出此方案;,列出所有的情况,检查是否满足两个约束条件,6,改进的方案,int main()int mellon,appl
3、e,orange;for(mellon=1;mellon10;+mellon)for(apple=1;apple 50-5*mellon;+apple)orange=3*(50-5*mellon-apple);if(mellon+apple+orange=100)cout mellon:mellon;cout apple:apple;cout orange:orange endl;return 0;,按一个约束条件列出所有可行的情况,然后对每个可能解检查它是否满足第二个约束条件。,7,执行结果,Mellon:1 apple:18 orange:81Mellon:2 apple:11 orang
4、e:87Mellon:3 apple:4 orange:93,8,第15章 算法设计技术,枚举法贪婪法分而治之法动态规划回溯法随机算法,介绍通用的算法设计模式,9,贪婪法,贪婪法适合于分阶段完成的工作。在每一阶段都选择当前最好的答案,而不管将来如何。Dijkstra算法,prim算法和Kruskal算法都是贪婪算法贪婪法不一定能得到最优解,但是一个可行的、较好的解。,10,最少背包问题,假设有许多盒子,每个盒子能保存的总重量为1.0。有N个项i1,i2,iN,它们的重量分别是w1,w2,wN。目的是用尽可能少的盒子放入所有的项,任何盒子的重量不能超过他的容量。例如,如果项的重量为0.4,0.4
5、,0.6和0.6,最佳的方案是用两个盒子。但要得到最佳方案,必须尝试所有种组合情况。当n很大时,这是不可能的。一种解决方案使用贪婪法,11,解决策略,按给定的次序扫描每一个项,把每一个项放入能够容纳他而不至于溢出的最满的盒子。如果项的重量为0.4,0.4,0.6和0.6,贪婪法的方案是用三个盒子。其装载的重量分别为0.8,0.6,0.6,12,第15章 算法设计技术,枚举法贪婪法分而治之法动态规划回溯法随机算法,介绍通用的算法设计模式,13,分而治之法,分而治之法的思想分:递归解决若干个较小的问题治:从子问题的答案中形成原始问题的解分治法的的算法至少有两个递归调用已见过的分治法算法:快速排序,
6、树的遍历,14,分治法实例,最长连续子序列问题最近点问题数学计算问题,15,最长连续子序列问题,假设输入是4,3,5,2,1,2,6,2。我们把这个输入划分成两部分,前四个和后四个。这样最大连续子序列的和可能出现在下面三种情况中。情况1:整个位于前半部,可递归计算。情况2:整个位于后半部,可递归计算。情况3:从前半部开始但在后半部结束。,16,情况3的解决方法,从两半部分的边界开始,通过从右到左的扫描来找到左半段的最长序列。类似地,从左到右的扫描找到右半段的最长序列。把这两个子序列组合起来,形成跨越分割边界的最大连续子序列。在这个实例中,结果序列是从第一部分的第一个元素到第二部分的其余元素。总
7、和是两个子序列的和,即4+7=11.,17,算法总结,递归地计算整个位于前半部的最大连续子序列。递归地计算整个位于后半部的最大连续子序列。通过两个连续循环,计算从前半部开始但在后半部结束的最大连续子序列的和。选择三个和中的最大值。,18,Int maxSum(int a,int left,int right)int maxLeft,maxRight,center;int leftSum=0,rightSum=0;int maxLeftTmp=NEGMAX,maxRightTmp=NEGMAX;center=(left+right)/2;if(left=right)return aleft 0?
8、aleft:0;maxLeft=maxSum(a,left,center);maxRight=maxSum(a,center+1,right);,19,for(int i=center;i=left;-i)leftSum+=ai;if(leftSum maxLeftTmp)maxLeftTmp=leftSum;for(int i=center+1;i maxRightTmp)maxRightTmp=rightSum;return max3(maxLeft,maxRight,maxLeftTmp+maxRightTmp);,20,分治法实例,最长连续子序列问题最近点问题数学计算问题,21,最近点
9、问题,在二维平面上有N个点,试找出距离最短的两个点。蛮力算法:计算两两之间的距离,从中找出最小的一个。N个点有N(N-1)/2对距离,因此时间复杂度为O(N2),22,分治法解法,将所有的点按x值排序。取一个合适的x值,把所有点分成两半PL和PR。距离最近的两个点可能出现在PL中(dL),也可能出现在PR(dR)中,也可能一个点在PL,一个点在PR(dC)dL和dR可用递归得到dC的计算:设=min(dL,dR)如果dC比大,则没必要计算。因此用于计算dC的点必须落在分界线 的范围内,计算此范围中点对的距离中的最小值,23,24,优化,在最坏的情况下,所有的点都落在分界线以内。但此时不一定要计
10、算所有点对的距离。只要两点的y坐标大于,这两点之间的距离也不用算了。假设该区间中的点按y坐标排序,则可得下列算法,25,for(i=0;i=)break;else if(dist(pj,pj+1)=dist(pj,pj+1);,26,分治法实例,最长连续子序列问题最近点问题数学计算问题,27,数学计算问题,设X和Y是两个N位的整数,假如一位乘法花费一个单位时间,那么计算 X*Y 的时间复杂性为O(N2)分治法计算将X和Y均分成两半,分别称为XL,XR,YL,YR。则 X=XL10N/2+XR,Y=YL10N/2+YR。那么,XY=XLYL10N+(XLYR+XRYL)10N/2+XRYR时间复
11、杂度:T(N)=4T(N/2)+O(N)=O(N2),28,进一步改进,上述算法的问题是需要太多次(4次)的递归调用。如果能减少递归调用,则能提高时间性能注意:XLYR+XRYL=(XL XR)(YR YL)+XLYL+XRYR 代入前式,XY=XLYL10N+(XLYR+XRYL)10N/2+XRYR=XLYL10N+(XL XR)(YR YL)+XLYL+XRYR)10N/2+XRYR 可见只需3次递归调用时间复杂性:,29,第15章 算法设计技术,枚举法贪婪法分而治之法动态规划回溯法随机算法,介绍通用的算法设计模式,30,动态规划,用表代替递归例:斐波那契函数f(n)=f(n-1)+f(
12、n-2)。计算f(n)需要计算f(n-1)和f(n-2)。当计算f(n-1)时要计算f(n-2)和f(n-3)。因此在计算f(n)中f(n-2)被计算了两次。为了减少重复的递归调用,我们可以反过来计算。先计算f(2),有了f(2)再计算f(3),以此类推,计算到f(n)。在此过程中不需要任何递归,31,动态规划,硬币找零问题最优二叉查找树,32,找零问题,对于一种货币,有面值为C1,C2,CN(分)的硬币,最少需要多少个硬币来找出K分钱的零钱。,33,贪婪法解法,我们不断使用可能的最大面值的硬币 如:美元的硬币有1、5、10和25分的面值(忽略流通频率很低的50分硬币)。我们可以通过使用2个2
13、5分、一个10分的硬币以及三个1分来找出63分钱,一共是6个硬币。如果美元中包含一个21分硬币时,贪心算法仍然给出一个用六个硬币的解,但是最佳的解是用三个硬币(三个都是21分的硬币。),34,解法1分治法,如果我们可以用一个硬币找零,这就是最小的。否则,对于每个可能的值i,我们可以独立计算找i分钱零钱和K-i分钱需要的最小硬币数。然后选择这个和最小的i。,35,怎样找出63分钱零钱,找出1分钱零钱和62分钱零钱分别需要的硬币数是1和4。因此,63分钱需要使用五个硬币。找出2分钱和61分钱分别需要2和4个硬币,一共是六个硬币。我们继续尝试所有的可能性。我们看到一个21分和42分的分解,它可以分别
14、用一个和两个硬币来找开,因此,这个找零问题就可以用三个硬币解决。我们需要尝试的最后一种分解是31分和32分。我们可以用两个硬币找出31分零钱,用三个硬币找出32分零钱,一共是五个硬币。因此最小值是三个硬币。,36,int coin(int k)int i,tmp,int coinNum=k;if(能用一个硬币找零)return 1;for(i=1;ik;+i)if(tmp=coin(i)+coin(k-i)coinNum)coinNum=tmp;return coinNum;,37,上述解法分析,此算法的效率很低事实上63分钱找零的问题是不会在一个合理的时间内解决的。就如Finbonacci
15、函数一样,38,解法2,通过指定其中的一个硬币来递归地简化问题。例如,对于63分钱,我们可以给出以下找零的办法。一个1分的硬币加上递归地分派62分钱一个5分的硬币加上递归地分派58分钱一个10分的硬币加上递归地分派53分钱一个21分的硬币加上递归地分派42分钱一个25分的硬币加上递归地分派38分钱该算法的问题仍然是效率问题,39,动态规划解,效率低下主要是由于重复计算造成的。因此,可把已有子问题的答案存放起来,当再次遇到此子问题时就不用重复计算了。在本例中,我们用coinsUsedi代表了找i分零钱所需的最小硬币数。,40,算法思想,先找出一分钱的找零方法,把最小硬币数存入coinUsed1
16、依次找出2分钱、3分钱的找零方法,知道到达要找零的钱为止:对每个要找的零钱i,可以把i分解成某个coinsj和 i-coinsj,所需硬币数为coinUsedi-coinsj+1。对所有的j,取最小的coinUsedi-coinsj+1作为i元钱找零的的答案。,41,函数原型,Void makechange(int coins,int differentCoins,int maxChange,int coinUsed)Coins存放所有不同的硬币值,不同的硬币个数为differentCoins。maxChange为要找的零钱数,42,void makechange(int coins,int
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 数据结构 第五 部分
链接地址:https://www.31ppt.com/p-6050242.html