ImageVerifierCode 换一换
格式:DOCX , 页数:67 ,大小:132.20KB ,
资源ID:16836067      下载积分:5 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bingdoc.com/d-16836067.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(算法设计与分析+常用方法.docx)为本站会员(b****6)主动上传,冰点文库仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰点文库(发送邮件至service@bingdoc.com或直接QQ联系客服),我们立即给予删除!

算法设计与分析+常用方法.docx

1、算法设计与分析+常用方法常用算法设计方法要使计算机能完成人们预定的工作,首先必须为如何完成预定的工作设计一个算法,然后再根据算法编写程序。计算机程序要对问题的每个对象和处理规则给出正确详尽的描述,其中程序的数据结构和变量用来描述问题的对象,程序结构、函数和语句用来描述问题的算法。算法数据结构是程序的两个重要方面。算法是问题求解过程的精确描述,一个算法由有限条可完全机械地执行的、有确定结果的指令组成。指令正确地描述了要完成的任务和它们被执行的顺序。计算机按算法指令所描述的顺序执行算法的指令能在有限的步骤内终止,或终止于给出问题的解,或终止于指出问题对此输入数据无解。通常求解一个问题可能会有多种算

2、法可供选择,选择的主要标准是算法的正确性和可靠性,简单性和易理解性。其次是算法所需要的存储空间少和执行更快等。算法设计是一件非常困难的工作,经常采用的算法设计技术主要有迭代法、穷举搜索法、递推法、贪婪法、回溯法、分治法、动态规划法等等。另外,为了更简洁的形式设计和藐视算法,在算法设计时又常常采用递归技术,用递归描述算法。一、迭代法迭代法是用于求方程或方程组近似根的一种常用的算法设计方法。设方程为f(x)=0,用某种数学方法导出等价的形式x=g(x),然后按以下步骤执行:(1) 选一个方程的近似根,赋给变量x0;(2) 将x0的值保存于变量x1,然后计算g(x1),并将结果存于变量x0;(3)

3、当x0与x1的差的绝对值还小于指定的精度要求时,重复步骤(2)的计算。若方程有根,并且用上述方法计算出来的近似根序列收敛,则按上述方法求得的x0就认为是方程的根。上述算法用C程序的形式表示为:【算法】迭代法求方程的根 x0=初始近似根; do x1=x0; x0=g(x1); /*按特定的方程计算新的近似根*/ while ( fabs(x0-x1)Epsilon); printf(“方程的近似根是%fn”,x0);迭代算法也常用于求方程组的根,令 X=(x0,x1,xn-1)设方程组为: xi=gi(X) (I=0,1,n-1)则求方程组根的迭代算法可描述如下:【算法】迭代法求方程组的根 f

4、or (i=0;in;i+) xi=初始近似根; do for (i=0;in;i+) yi=xi; for (i=0;in;i+) xi=gi(X); for (delta=0.0,i=0;idelta) delta=fabs(yi-xi); while (deltaEpsilon); for (i=0;in;i+) printf(“变量x%d的近似根是 %f”,I,xi); printf(“n”); 具体使用迭代法求根时应注意以下两种可能发生的情况:(1) 如果方程无解,算法求出的近似根序列就不会收敛,迭代过程会变成死循环,因此在使用迭代算法前应先考察方程是否有解,并在程序中对迭代的次数给

5、予限制;(2) 方程虽然有解,但迭代公式选择不当,或迭代的初始近似根选择不合理,也会导致迭代失败。二、穷举搜索法 穷举搜索法是对可能是解的众多候选解按某种顺序进行逐一枚举和检验,并从中找出那些符合要求的候选解作为问题的解。【问题】 将A、B、C、D、E、F这六个变量排成如图所示的三角形,这六个变量分别取1,6上的整数,且均不相同。求使三角形三条边上的变量之和相等的全部解。如图就是一个解。程序引入变量a、b、c、d、e、f,并让它们分别顺序取1至6的证书,在它们互不相同的条件下,测试由它们排成的如图所示的三角形三条边上的变量之和是否相等,如相等即为一种满足要求的排列,把它们输出。当这些变量取尽所

6、有的组合后,程序就可得到全部可能的解。细节见下面的程序。【程序1】# include void main() int a,b,c,d,e,f; for (a=1;a=6;a+) for (b=1;b=6;b+) if (b=a) continue; for (c=1;c=6;c+) if (c=a)|(c=b) continue; for (d=1;d=6;d+) if (d=a)|(d=b)|(d=c) continue;for (e=1;e=6;e+) if (e=a)|(e=b)|(e=c)|(e=d) continue;f=21-(a+b+c+d+e);if (a+b+c=c+d+e)

7、&(a+b+c=e+f+a) printf(“%6d,a); printf(“%4d%4d”,b,f); printf(“%2d%4d%4d”,c,d,e); scanf(“%*c”); 按穷举法编写的程序通常不能适应变化的情况。如问题改成有9个变量排成三角形,每条边有4个变量的情况,程序的循环重数就要相应改变。 对一组数穷尽所有排列,还有更直接的方法。将一个排列看作一个长整数,则所有排列对应着一组整数。将这组整数按从小到大的顺序排列排成一个整数,从对应最小的整数开始。按数列的递增顺序逐一列举每个排列对应的每个整数,这能更有效地完成排列的穷举。从一个排列找出对应数列的下一个排列可在当前排列的基

8、础上作部分调整来实现。倘若当前排列为1,2,4,6,5,3,并令其对应的长整数为124653。要寻找比长整数124653更大的排列,可从该排列的最后一个数字顺序向前逐位考察,当发现排列中的某个数字比它前一个数字大时,如本例中的6比它的前一位数字4大,这说明还有对应更大整数的排列。但为了顺序从小到大列举出所有的排列,不能立即调整得太大,如本例中将数字6与数字4交换得到的排列126453就不是排列124653的下一个排列。为了得到排列124653的下一个排列,应从已经考察过的那部分数字中选出比数字大,但又是它们中最小的那一个数字,比如数字5,与数字4交换。该数字也是从后向前考察过程中第一个比4大的

9、数字。5与4交换后,得到排列125643。在前面数字1,2,5固定的情况下,还应选择对应最小整数的那个排列,为此还需将后面那部分数字的排列顺序颠倒,如将数字6,4,3的排列顺序颠倒,得到排列1,2,5,3,4,6,这才是排列1,2,4,6,5,3的下一个排列。按以上想法编写的程序如下。【程序2】# include # define SIDE_N 3# define LENGTH 3# define VARIABLES 6int A,B,C,D,E,F;int *pt=&A,&B,&C,&D,&E,&F;int *sideSIDE_NLENGTH=&A,&B,&C,&C,&D,&E,&E,&F,

10、&A;int side_totalSIDE_N;main int i,j,t,equal; for (j=0;jVARIABLES;j+) *ptj=j+1; while(1) for (i=0;iSIDE_N;i+) for (t=j=0;jLENGTH;j+) t+=*sideij; side_totali=t; for (equal=1,i=0;equal&iSIDE_N-1;i+) if (side_totali!=side_totali+1 equal=0; if (equal) for (i=1;i0;j-) if (*ptj*ptj-1) break; if (j=0) brea

11、k; for (i=VARIABLES-1;i=j;i-) if (*pti*pti-1) break; t=*ptj-1;* ptj-1 =* pti; *pti=t; for (i=VARIABLES-1;ij;i-,j+) t=*ptj; *ptj =* pti; *pti=t; 从上述问题解决的方法中,最重要的因素就是确定某种方法来确定所有的候选解。下面再用一个示例来加以说明。【问题】 背包问题问题描述:有不同价值、不同重量的物品n件,求从这n件物品中选取一部分物品的选择方案,使选中物品的总重量不超过指定的限制重量,但选中物品的价值之和最大。设n个物品的重量和价值分别存储于数组w 和v

12、 中,限制重量为tw。考虑一个n元组(x0,x1,xn-1),其中xi=0 表示第i个物品没有选取,而xi=1则表示第i个物品被选取。显然这个n元组等价于一个选择方案。用枚举法解决背包问题,需要枚举所有的选取方案,而根据上述方法,我们只要枚举所有的n元组,就可以得到问题的解。显然,每个分量取值为0或1的n元组的个数共为2n个。而每个n元组其实对应了一个长度为n的二进制数,且这些二进制数的取值范围为02n-1。因此,如果把02n-1分别转化为相应的二进制数,则可以得到我们所需要的2n个n元组。【算法】maxv=0;for (i=0;i2n;i+) B0.n-1=0; 把i转化为二进制数,存储于数

13、组B中; temp_w=0; temp_v=0; for (j=0;jn;j+) if (Bj=1) temp_w=temp_w+wj; temp_v=temp_v+vj; if (temp_wmaxv) maxv=temp_v; 保存该B数组; 三、递推法 递推法是利用问题本身所具有的一种递推关系求问题解的一种方法。设要求问题规模为N的解,当N=1时,解或为已知,或能非常方便地得到解。能采用递推法构造算法的问题有重要的递推性质,即当得到问题规模为i-1的解后,由问题的递推性质,能从已求得的规模为1,2,i-1的一系列解,构造出问题规模为I的解。这样,程序可从i=0或i=1出发,重复地,由已知

14、至i-1规模的解,通过递推,获得规模为i的解,直至得到规模为N的解。【问题】 阶乘计算问题描述:编写程序,对给定的n(n100),计算并输出k的阶乘k!(k=1,2,n)的全部有效数字。由于要求的整数可能大大超出一般整数的位数,程序用一维数组存储长整数,存储长整数数组的每个元素只存储长整数的一位数字。如有m位成整数N用数组a 存储: N=am10m-1+am-110m-2+ +a2101+a1100并用a0存储长整数N的位数m,即a0=m。按上述约定,数组的每个元素存储k的阶乘k!的一位数字,并从低位到高位依次存于数组的第二个元素、第三个元素。例如,5!=120,在数组中的存储形式为:3021

15、首元素3表示长整数是一个3位数,接着是低位到高位依次是0、2、1,表示成整数120。 计算阶乘k!可采用对已求得的阶乘(k-1)!连续累加k-1次后求得。例如,已知4!=24,计算5!,可对原来的24累加4次24后得到120。细节见以下程序。# include # include # define MAXN 1000void pnext(int a ,int k) int *b,m=a0,i,j,r,carry; b=(int * ) malloc(sizeof(int)* (m+1); for ( i=1;i=m;i+) bi=ai; for ( j=1;j=k;j+) for ( carr

16、y=0,i=1;i=m;i+) r=(i0;i-) printf(“%d”,ai);printf(“nn”);void main() int aMAXN,n,k; printf(“Enter the number n: “); scanf(“%d”,&n); a0=1; a1=1; write(a,1); for (k=2;k1时)。写成递归函数有:int fib(int n) if (n=0) return 0; if (n=1) return 1; if (n1) return fib(n-1)+fib(n-2); 递归算法的执行过程分递推和回归两个阶段。在递推阶段,把较复杂的问题(规模为

17、n)的求解推到比原问题简单一些的问题(规模小于n)的求解。例如上例中,求解fib(n),把它推到求解fib(n-1)和fib(n-2)。也就是说,为计算fib(n),必须先计算fib(n-1)和fib(n-2),而计算fib(n-1)和fib(n-2),又必须先计算fib(n-3)和fib(n-4)。依次类推,直至计算fib(1)和fib(0),分别能立即得到结果1和0。在递推阶段,必须要有终止递归的情况。例如在函数fib中,当n为1和0的情况。 在回归阶段,当获得最简单情况的解后,逐级返回,依次得到稍复杂问题的解,例如得到fib(1)和fib(0)后,返回得到fib(2)的结果,在得到了fi

18、b(n-1)和fib(n-2)的结果后,返回得到fib(n)的结果。 在编写递归函数时要注意,函数中的局部变量和参数知识局限于当前调用层,当递推进入“简单问题”层时,原来层次上的参数和局部变量便被隐蔽起来。在一系列“简单问题”层,它们各有自己的参数和局部变量。 由于递归引起一系列的函数调用,并且可能会有一系列的重复计算,递归算法的执行效率相对较低。当某个递归算法能较方便地转换成递推算法时,通常按递推算法编写程序。例如上例计算斐波那契数列的第n项的函数fib(n)应采用递推算法,即从斐波那契数列的前两项出发,逐次由前两项计算出下一项,直至计算出要求的第n项。【问题】 组合问题问题描述:找出从自然

19、数1、2、n中任取r个数的所有组合。例如n=5,r=3的所有组合为: (1)5、4、3 (2)5、4、2 (3)5、4、1 (4)5、3、2 (5)5、3、1 (6)5、2、1 (7)4、3、2 (8)4、3、1 (9)4、2、1 (10)3、2、1 分析所列的10个组合,可以采用这样的递归思想来考虑求组合函数的算法。设函数为void comb(int m,int k)为找出从自然数1、2、m中任取k个数的所有组合。当组合的第一个数字选定时,其后的数字是从余下的m-1个数中取k-1数的组合。这就将求m个数中取k个数的组合问题转化成求m-1个数中取k-1个数的组合问题。设函数引入工作数组a 存放

20、求出的组合的数字,约定函数将确定的k个数字组合的第一个数字放在ak中,当一个组合求出后,才将a 中的一个组合输出。第一个数可以是m、m-1、k,函数将确定组合的第一个数字放入数组后,有两种可能的选择,因还未去顶组合的其余元素,继续递归去确定;或因已确定了组合的全部元素,输出这个组合。细节见以下程序中的函数comb。【程序】# include # define MAXN 100int aMAXN;void comb(int m,int k) int i,j; for (i=m;i=k;i-) ak=i; if (k1) comb(i-1,k-1); else for (j=a0;j0;j-) p

21、rintf(“%4d”,aj); printf(“n”); void main() a0=3; comb(5,3);【问题】 背包问题问题描述:有不同价值、不同重量的物品n件,求从这n件物品中选取一部分物品的选择方案,使选中物品的总重量不超过指定的限制重量,但选中物品的价值之和最大。设n件物品的重量分别为w0、w1、wn-1,物品的价值分别为v0、v1、vn-1。采用递归寻找物品的选择方案。设前面已有了多种选择的方案,并保留了其中总价值最大的方案于数组option ,该方案的总价值存于变量maxv。当前正在考察新方案,其物品选择情况保存于数组cop 。假定当前方案已考虑了前i-1件物品,现在要

22、考虑第i件物品;当前方案已包含的物品的重量之和为tw;至此,若其余物品都选择是可能的话,本方案能达到的总价值的期望值为tv。算法引入tv是当一旦当前方案的总价值的期望值也小于前面方案的总价值maxv时,继续考察当前方案变成无意义的工作,应终止当前方案,立即去考察下一个方案。因为当方案的总价值不比maxv大时,该方案不会被再考察,这同时保证函数后找到的方案一定会比前面的方案更好。对于第i件物品的选择考虑有两种可能:(1) 考虑物品i被选择,这种可能性仅当包含它不会超过方案总重量限制时才是可行的。选中后,继续递归去考虑其余物品的选择。(2) 考虑物品i不被选择,这种可能性仅当不包含物品i也有可能会

23、找到价值更大的方案的情况。按以上思想写出递归算法如下:try(物品i,当前选择已达到的重量和,本方案可能达到的总价值tv) /*考虑物品i包含在当前方案中的可能性*/ if(包含物品i是可以接受的) 将物品i包含在当前方案中; if (in-1) try(i+1,tw+物品i的重量,tv); else /*又一个完整方案,因为它比前面的方案好,以它作为最佳方案*/以当前方案作为临时最佳方案保存; 恢复物品i不包含状态; /*考虑物品i不包含在当前方案中的可能性*/ if (不包含物品i仅是可男考虑的) if (in-1) try(i+1,tw,tv-物品i的价值); else /*又一个完整方

24、案,因它比前面的方案好,以它作为最佳方案*/以当前方案作为临时最佳方案保存; 为了理解上述算法,特举以下实例。设有4件物品,它们的重量和价值见表:物品0123重量5321价值4431并设限制重量为7。则按以上算法,下图表示找解过程。由图知,一旦找到一个解,算法就进一步找更好的佳。如能判定某个查找分支不会找到更好的解,算法不会在该分支继续查找,而是立即终止该分支,并去考察下一个分支。按上述算法编写函数和程序如下:【程序】# include # define N 100double limitW,totV,maxV;int optionN,copN;struct double weight; do

25、uble value; aN;int n;void find(int i,double tw,double tv) int k; /*考虑物品i包含在当前方案中的可能性*/ if (tw+ai.weight=limitW) copi=1; if (in-1) find(i+1,tw+ai.weight,tv); else for (k=0;kmaxV) if (in-1) find(i+1,tw,tv-ai.value); else for (k=0;kn;k+) optionk=copk; maxv=tv-ai.value; void main() int k; double w,v; pr

26、intf(“输入物品种数n”); scanf(“%d”,&n); printf(“输入各物品的重量和价值n”); for (totv=0.0,k=0;kn;k+) scanf(“%1f%1f”,&w,&v); ak.weight=w; ak.value=v; totV+=V; printf(“输入限制重量n”); scanf(“%1f”,&limitV); maxv=0.0; for (k=0;kn;k+) copk=0; find(0,0.0,totV); for (k=0;kn;k+) if (optionk) printf(“%4d”,k+1); printf(“n总价值为%.2fn”,maxv); 作为对比,下面以同样的解题思想,考虑非递归的程序解。为了提高找解速度,程序不是简单地逐一生成所有候选解,而是从每个物品对候选解的影响来形成值得进一步考虑的候选解,一个候选解是通过依次

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2