计算机编程常用算法.pdf
![资源得分’ title=](/images/score_1.gif)
![资源得分’ title=](/images/score_1.gif)
![资源得分’ title=](/images/score_1.gif)
![资源得分’ title=](/images/score_1.gif)
![资源得分’ title=](/images/score_05.gif)
《计算机编程常用算法.pdf》由会员分享,可在线阅读,更多相关《计算机编程常用算法.pdf(55页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、常用算法要使计算机能完成人们预定的工作,首先必须为如何完成预定的工作设计一个算法,然后再根据算法编写程序。计算机程序要对问题的每个对象和处理规则给出正确详尽的描述,其中程序的数据结构和变量用来描述问题的对象,程序结构、函数和语句用来描述问题的算法。算法数据结构是程序的两个重要方面。算法是问题求解过程的精确描述,一个算法由有限条可完全机械地执行的、有确定结果的指令组成。指令正确地描述了要完成的任务和它们被执行的顺序。计算机按算法指令所描述的顺序执行算法的指令能在有限的步骤内终止,或终止于给出问题的解,或终止于指出问题对此输入数据无解。通常求解个问题可能会有多种算法可供选择,选择的主要标准是算法的
2、正确性和可靠性,简单性利易理解性。其次是算法所需要的存储空间少和执行更快等。算法设计是一件非常困难的工作,经常采用的算法设计技术主要有迭代法、穷举搜索法、递推法、贪婪法、回溯法、分治法、动态规划法等等。另外,为了更简洁的形式设计和藐视算法,在算法设计时又常常采用递归技术,用递归描述算法。一、迭代法迭代法是用于求方程或方程组近似根的一种常用的算法设计方法。设方程为f(x尸0,用某种数学方法导出等价的形式x=g(x),然后按以下步骤执行:(1)选一个方程的近似根,赋给变量xO;(2)将 x0的值保存于变量x l,然后计算g(x l),并将结果存于变量xO;(3)当 xO与 x l 的差的绝对值还小
3、于指定的精度要求时,重复步骤(2)的计算。若方程有根,并且用上述方法计算出来的近似根序列收敛,则按上述方法求得的xO就认为是方程的根。上述算法用C 程序的形式表示为:【算法】迭代法求方程的根 x0=初始近似根;do xl=x0;xO=g(xl);/*按特定的方程计算新的近似根*/while(fabs(xO-x 1 )Epsilon);printf(方 程的近似根是fn,xO);迭代算法也常用于求方程组的根,令X=(xO,x l,,xn-1)设方程组为:xi=gi(X)(1=0,1,n-1)则求方程组根的迭代算法可描述如下:【算法】迭代法求方程组的根 for(i=0;in;i-H-)xi=初始近
4、似根;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)如果方程无解,算法求出的近似根序列就不会收敛,迭代过程会变成死循环,因此在使用迭代算法前应先考察方程是否有解,并在程序中对迭代的次数给予限制;(2)方程虽然有解,但迭代公式选择不当,或迭代的初始近似根选择不合理,
5、也会导致迭代失败。二、穷举搜索法穷举搜索法是对可能是解的众多候选解按某种顺序进行逐一枚举和检验,并从众找出那些符合要求的候选解作为问题的解。【问题】将A、B、C、D、E、F这六个变量排成如图所示的三角形,这六个变量分别取 1,6上的整数,且均不相同。求使三角形三条边上的变量之和相等的全部解。如图就是一个解。程序引入变量a、b、c、d、e、f,并让它们分别顺序取1至6的证书,在它们互不相同的条件下,测试山它们排成的如图所示的三角形三条边上的变量之和是否相等,如相等即为一种满足要求的排列,把它们输出。当这些变量取尽所有的组合后,程序就可得到全部可能的解。细节见下面的程序。【程 序1】#i n c
6、l u d e v o i d m a i n()i n t a,b,c,d,e,f;f o r (a=l;a =6;a-H-)f o r (b=1 ;b=6;b+)i f (b=a)c o n t i n u e;f o r (c=1 ;c =6;c-H-)i f (c=a)|(c=b)c o n t i n u e;f o r (d=1 ;d=6;d+)i f (d=a)1 1(d=b)11(d=c)c o n t i n u e;f o r (e=1 ;e =6;e-H-)i f (e=a)|(e=b)|(e=c)1 1(e=d)c o n t i n u e;f=2 1 -(a+b+c
7、+d+e);i f (a+b+c=c+d+e)&(a+b+c=e+任 a)p r i n t f(4 4%6d,a);p r i n t f(t 4%4 d%4 d,b,f);p r i n t f C4%2 d%4 d%4 d,c,d,e);s c a n f T%*c);按穷举法编写的程序通常不能适应变化的情况。如问题改成有9 个变量排成三角形,每条边有4 个变量的情况,程序的循环重数就要相应改变。对一组数穷尽所有排列,还有更直接的方法。将一个排列看作一个长整数,则所有排列对应着一组整数。将这组整数按从小到大的顺序排列排成一个整数,从对应最小的整数开始。按数列的递增顺序逐一列举每个排列对应
8、的每个整数,这能更有效地完成排列的穷举。从一个排列找出对应数列的下一个排列可在当前排列的基础上作部分调整来实现。倘若当前排列为1,2,4,6,5,3,并令其对应的长整数为124653c要寻找比长整数124653更大的排列,可从该排列的最后一个数字顺序向前逐位考察,当发现排列中的某个数字比它前一个数字大时,如本例中的6 比它的前一位数字4 大,这说明还有对应更大整数的排列。但为了顺序从小到大列举出所有的排列,不能立即调整得太大,如本例中将数字6 与数字4 交换得到的排列126453就不是排列124653的下一个排列。为了得到排列124653的下一个排列,应从已经考察过的那部分数字中选出比数字大,
9、但又是它们中最小的那一个数字,比如数字5,与数字4 交换。该数字也是从后向前考察过程中第一个比4 大的数字。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,&
10、E,&F;int*sideSIDE_NLENGTH=&A,&B,&C,&C,&D,&E,&E,&F,&A;int side_totalSIDE_N;main int i,j,t,equal;for(j=O;jVARIABLES;j+)while(1)for(i=0;iSIDE_N;i4-+)for(t=j=O;jLENGTHg-H-)t+=*sideij;side_totali=t;for(equal=l,i=O;equal&iSIDE_N-l;i+)if(side_totali!=side_totali+l equal=0;if(equal)for(i=l;iO;j-)if(*ptj*ptj
11、-l)break;if(j=0)break;for(i=VARIABLES-l;i=j;i-)if(*pti*pti-l)break;t=*ptj-l;*ptj-l=*pti;*pti=t;fbr(i=VARIABLES-l;ij;i-j+)t=*ptj;*ptj=*pti;*pti=t;从上述问题解决的方法中,最重要的因素就是确定某种方法来确定所有的候选解。下面再用一个示例来加以说明。【问题】背包问题问题描述:有不同价值、不同重量的物品n 件,求从这n 件物品中选取一部分物品的选择方案,使选中物品的总重量不超过指定的限制重量,但选中物品的价值之和最大。设 n 个物品的重量和价值分别存储于数组
12、w 和 v 中,限制重量为tw o考虑一个n元 组(xO,x l,,x n-1),其中xi=0表示第i 个物品没有选取,而 xi=l则表示第i 个物品被选取。显然这个n 元组等价于一个选择方案。用枚举法解决背包问题,需要枚举所有的选取方案,而根据上述方法,我们只要枚举所有的n 元组,就可以得到问题的解。显然,每个分量取值为0 或 1 的 n 元组的个数共为2n个。而每个n 元组其实对应了个长度为n 的二进制数,且这些二进制数的取值范围为02n-l。因此,如果把02n-l分别转化为相应的二进制数,则可以得到我们所需要的2n 个 n 元组。【算法】maxv=0;for(i=0;i2n;i+)B0.
13、n-l=0;把 i 转化为二进制数,存储于数组B 中;temp_w=0;temp_v=0;for(j=O;jn;j+)if(Bj=l)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 的解。这样,程序
14、可从i=0或 i=l出发,重复地,由已知至i-1规模的解,通过递推,获得规模为i 的解,直至得到规模为N的解。【问题】阶乘计算问题描述:编写程序,对给定的n(n=1 0 0),计算并输出k 的阶乘k!(k=l,2,,n)的全部有效数字。由于要求的整数可能大大超出一般整数的位数,程序用一维数组存储长整数,存储长整数数组的每个元素只存储长整数的一位数字。如有m 位成整数N 用数组a存储:N=am x 10m-1+am-1 x 10m-2+.+a2xl01+alxl00并用a0存储长整数N 的位数m,即 a0=m。按上述约定,数组的每个元素存储k 的阶乘k!的一位数字,并从低位到高位依次存于数组的第
15、二个元素、第三个元素。例如,5!=1 2 0,在数组中的存储形式为:3 0 2 1 .首元素3 表示长整数是一个3 位数,接着是低位到高位依次是0、2、1,表示成整数120o计算阶乘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=l;i=m;i+)bi=
16、ai;fbr(j=l;j=k;j+)for(carry=O,i=1 ;i=m;i+)r=(i0;i-)printf(d”,ai);printf(nn);void main()int aMAXN,n,k;printfifEnter the number n:);scanfT%d”,&n);a0=l;al=l;write(a,l);for(k=2;kl 时)。写成递归函数有:int fib(int n)if(n=0)return 0;if(n 1)return 1;if(nl)return fib(n-l)+fib(n-2);)递归算法的执行过程分递推和回归两个阶段。在递推阶段,把较复杂的问题(规
17、模为n)的求解推到比原问题简单一些的问题(规模小于n)的求解。例如上例中,求解fib(n),把它推到求解fib(n-l)和 fib(n-2)。也就是说,为计算fib(n),必须先计算fib(n-l)和 fib(n-2),而计算fib(n-l)和 fib(n-2),又必须先计算fib(n-3)和 fib(n4)。依次类推,直至计算flb(l)和fib(0),分别能立即得到结果1 和 0。在递推阶段,必须要有终止递归的情况。例如在函数fib中,当 n 为 1和。的情况。在回归阶段,当获得最简单情况的解后,逐级返回,依次得到稍复杂问题的解,例如得至I fib 和 fib(O)后,返回得到fib(2)
18、的结果,在得到了 fib(n-l)和 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-l个数中取k-1数的组合。这就将求m 个数中取k 个数的组合问题转化成求m-1个数中取k-l个数的组合问题。设函
20、数引入工作数组a 存放求HI的组合的数字,约定函数将确定的k 个数字组合的第一个数字放在ak中,当一个组合求出后,才将a中的一个组合输出。第一-个数可以是m、m-l.、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(kl)comb(i-l,k-l);else for(j=aO;jO;j-)
21、printfC%4d,aj);printf(“n”);)void main()a0=3;comb(5,3);)【问题】背包问题问题描述:有不同价值、不同重量的物品n 件,求从这n 件物品中选取一部分物品的选择方案,使选中物品的总重量不超过指定的限制重量,但选中物品的价值之和最大。设 n 件物品的重量分别为wO、w l、w n-1,物品的价值分别为vO、v l、v n-L 采用递归寻找物品的选择方案。设前面已有了多种选择的方案,并保留了其中总价值最大的方案于数组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-l)try(i+l,tw+物品 i 的重量,tv);else/*又一个完整方案,因为它比前面的方案好,以它作为最佳方案*/以当前方案作为临时最佳方案保存;恢复物品i 不包含状态;)/*考虑物品i 不包含在当前方案中的可能性*/if(不包含物品i 仅是可男考虑的)if(in-l)try(i+l,tw,tv-物品 i 的价值);else/*又一个完整
24、方案,因它比前面的方案好,以它作为最佳方案*/以当前方案作为临时最佳方案保存;为了理解上述算法,特举以下实例。设有4 件物品,它们的重量和价值见表:物品 0 1 2 3重量 5321价值 4431并设限制重量为7。则按以上算法,下图表示找解过程。由图知,一旦找到一个解,算法就进一步找更好的佳。如能判定某个查找分支不会找到更好的解,算法不会在该分支继续查找,而是立即终止该分支,并去考察下一个分支。按上述算法编写函数和程序如下:【程序】#include#define N 100double limitW,totV,maxV;int optionN,copN;struct double weight
25、;double value;aN;int n;void find(int i,double tw,double tv)int k;/*考虑物品i 包含在当前方案中的可能性*/if(tw+ai.weight=limitW)copi=l;if(in-l)find(i+l,tw+ai.weight,tv);else for(k=0;kmaxV)if(in-l)find(i+1 ,tw,tv-ai.value);else for(k=O;kn;k+)optionk=copk;maxv=tv-ai.value;void main()int k;double w,v;printf(“输入物品种数n”);s
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 计算机 编程 常用 算法
![提示](https://www.taowenge.com/images/bang_tan.gif)
限制150内