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

加入VIP,免费下载
 

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

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

下载须知

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

版权提示 | 免责声明

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

算法设计基础.docx

1、算法设计基础第1章算法设计基础本章讨论如何评价一个算法,常见的基本的算法设计方法。算法在C语言程序设计中具有如此重要的位置,以至于我们不得不用单独一章来讨论算法。仅仅掌握C语言程序设计语法规则并不能保证写出一个好的程序。好与坏的标准在计算机科学中有特定的含义,它是程序的执行过程花费的时间代价和空间代价的少与多的度量。好的算法给我们带来经济上的好处,可以使得我们设计出更优秀的操作系统,提高计算机的运行效率;或者使得我们可以提高机密数据的安全性,不被别人窃取;或者可以提供给我们更好的影音效果,让我们能享受生活的乐趣;或者使得我们在搜索引擎上更快的搜索到需要的数据。好的算法能在有限时间和有限空间条件

2、下得到问题的解,而不好的算法可能终生都得不到解。历史上有许多著名科学家都提出了针对特定问题的著名算法。伟大的智者Don E. Knuth(1938-),他是算法和程序设计技术的先驱者。Knuth的经典著作计算机程序设计艺术更是被誉为算法教材中“真正”的圣经。Bill Gates说:“如果能作对书里所有的习题,就直接来微软上班吧!”。首席算法官Udi Manber世界上还有如此奇特的职位?但是对于Amazon 乃至Google来说,这一点也不奇 怪。Udi Manber,这位前Amazon 的“首席算法官”,现在是Google 负责工程事务的副总裁。Udi 还因为他所著Introduction

3、to AlgorithmsA Creative Approach 而被大家称道。谦逊的长者Edsger Wybe Dijkstra,1930 年出生于荷兰阿姆斯特丹,2002 年逝世于荷兰纽南。他在祖国荷兰获得数据和物理学学士,理论物理博士学位,2000 年退休前 一直是美国Texas 大学的计算机科学和数学教授。因他发现了图论中的最短路径算法(Dijkstra 算法)而闻名于世,1972 年因发明ALGOL 第二代编程语言而获得图灵奖。运筹学大师George Dantizig,在大学时代就解决了两个统计学悬而未决的难题。George 后来在运筹学建树极高,获得了包括“冯诺伊曼理论奖”在内的诸

4、多奖项。他在Linear programming and extensions 一书中研究了线性编程模型,为计算机语言的发展做出了不可磨灭的贡献。推动时代前进的人James Cooley(1926-)是美国数学家,哥伦比亚大学的数学博士,因为发明快速傅立叶变换(FFT)而著名。FFT 的数学意义不光在于使大家明白了傅立叶(Fourier)变换计算起来是多么容易,而且使得数字信号处理技术取得了突破性的进展,对于现在的网络通信,图形图像处理等等领域的发展与前进奠定了基础。FORTRAN 之父John Backus。在IBM,Backus 的才华得到了施展,发明了人类历史上前所未有第一个高级语言FO

5、RTRAN,对计算机科学计算和程序语言做出了杰出贡献。1977 年John Backus 被授予图灵奖。实践探索先锋Jon Bentley。他的著作中,最著名的莫过于涵盖从算法理论到软件工程各种主题的Programming Pearls(编程珠玑),这其实是他发表过的论文的合集。在这些文章里,Jon从工程实现的角度出发,为程序员们提供了一个个艰难问题的解决方案, 犹如一颗颗闪闪发亮的珍珠。Bentley 的珍珠超出了可靠工程学的范畴,利用他的洞察力和创造力为那些恼人的算法问题提供了巧妙解决方案。Pascal 之父Nicklaus Wirth,如果说有一个人因为一句话而著名,那么这个人就是Nic

6、klaus Wirth,这句话就是他提出的著名公式“算法+数据结构=程序”。他创建与实现了Pascal 语言当时世界上最受欢迎的语言之一。算法的讲解者Robert Sedgewick 是普林斯顿大学的计算机科学教授。他还是Adobe Systems 的一名主管,也曾作为访问学者在Xerox PARC、IDA 和INRIA 工作。他在斯坦福大学获得博士学位。他的著作包括Algorithm in C、Algorithm in C+、Algorithm in Java 等系列书籍,这些都再版多次。计算机领域的爵士Tony Hoare,1934 年出生于英国,1959 年博士毕业于俄罗斯莫斯科国立大学

7、,获得语言机器翻译专业学士学位。1960 年发布了使他闻名于世的快速排序算法(Quick Sort),这个算法也是当前世界上使用最广泛的算法之一。中国历史上也有著名算法,如圆周率PI的计算方法。近代诞生的遗传算法对处理相当广泛的大规模问题有突出效果。这些算法都是人类智慧的结晶。要写出好的程序,应该向这些优秀的算法学习,阅读大师的著作,掌握这些算法的精髓,在应用开发中才能做到融会贯通。1 1.1 算法的基本概念算法是对特定问题求解步骤的一种描述,算法是指令的有限序列,其中每一条指令表示一个或多个操作。算法具有以下五个特征:1)有穷 一个算法必须总是在执行有穷步骤之后结束,且每一步都在有穷的时间内

8、完成。2)确定 算法中每一条指令必须有确切的含义,不应该存在二义性。且算法只有一个入口和一个出口。3)可行 一个算法是可行的。即算法描述的操作都是可以通过已经实现的基本运算执行有限的次数来实现。4)输入 一个算法有0个或多个输入,这些输入取自于某个特定的对象的数据集合。5)输出 一个算法有一个或多个输出,这些输出是同输入有着某些特定关系的数据。评价一个好的算法有以下几个标准:1)正确性(Correctness ) 算法应满足具体问题的需求,得到问题的解。2)可读性(Readability) 算法应该好读。以有利于阅读者对程序的理解。3)健壮性(Robustness) 算法应具有容错处理。当输入

9、非法数据时,算法应该能有适当反应,而不是产生莫名其妙的输出结果或者程序崩溃。4)效率与存储量的需求 效率指的是算法执行所需要的CPU时间;存储空间需求量是指算法执行过程中所需要的最大存储空间。一般,这两者与问题的数据规模有关。1.2 算法分析算法的效率和优劣的客观判断和明确分析准则,是由美国人霍泼克洛夫特提出的。他提出了一种称为“最坏情况渐近分析法”(Worst-case asymptotic analysis of algorithm),这种方法先确定问题的大小尺度或者数据规模,然后把CPU计算时间当作问题大小尺度的一个函数去算出CPU计算时间的增长率,以此衡 量算法的效率和优劣。由于这个方

10、法与机器性能及所用语言无关,成为衡量算法好坏的客观的数学准则,被科学界所广泛接受。1.2.1 算法评价标准 算法时间复杂度的数学定义从数学上定义,给定算法A,如果存在函数F(n),当输入数据规模n=k 时,F(k)表示算法A 在输入规模为k 的情况下的运行时间,则称F(n)为算法A 的时间复杂度。首先要定义输入规模的概念。输入规模是指算法A所接受输入的基本类型数据的个数。例如,对于排序算法来说,输入规模一般就是待排序元素的个数,而对于求两个同型方阵乘积的算法,输入规模可以看作是单个方阵的维数。为了简单起见,在下面的讨论中,我们总是假设算法的输入规模是用大于零的整数表示的,即1,2,3,k,n。

11、我们还知道,对于同一个算法,每次执行的时间不仅取决于输入规模,还取决于输入的特性和具体的硬件环境在某次执行时的状态。所以想要得到一个统一精确的F(n)是不可能的。为了解决这个问题,我们作两个假设:1.硬件及环境因素,假设每次执行时硬件条件和环境条件是完全一致的。2.对于输入数据集特性的差异,假设不同情况的出现概率是相同的。 算法时间复杂度的分析示例为了便于理解,使用一个十分简单的算法作为示例。我们先来定义问题。问题定义:输入此问题输入为一个有序序列,其元素个数为 n,n 为大于零的整数。序列中的元素为从 1到n 。这n 个整数排列次序为完全随机。要求输出元素n 所在的位置,第一个元素位置为0。

12、这个问题非常简单,下面用伪代码直接给出其解决算法之一:LocationN(A)for(int i=0 i=n i+) / t1if(Ai = n) / t2 return i /t3我们来看看这个算法。其中t1、t2 和t3 分别表示此行代码执行一次需要的时间。很明显,t1、t2 和t3是和具体的硬件环境和语言有关。首先,输入规模n 是影响算法执行时间的因素之一。在n 固定的情况下,不同的输入序列也会影响其执行时间。最好情况下,n 就排在序列的第一个位置,那么此时的运行时间为“t1+t2+t3”。最坏情况下,n 排在序列最后一位,则运行时间为F(n)=n*t1+n*t2+t3=(t1+t2)*

13、n+t3可以看到,最好情况下运行时间是一个常数,而最坏情况下运行时间是输入规模的线性函数。那么,平均情况如何呢?问题定义说输入序列完全随机,即n 出现在1.n 这n 个不同位置上可能性是相等的,即概率均为1/n。而平均情况下的执行次数即为执行次数的数学期望,其解为:E= p(n=1)*1+p(n=2)*2+.+p(n=n)*n= (1/n)*(1+2+.+n)= (1/n)*(n/2)*(1+n)= (n+1)/2即在平均情况下for 循环要执行(n+1)/2 次,则平均运行时间为F(n) =(t1+t2)*(n+1)/2+t3由此我们得出分析结论:t1+t2+t3 = F(n) =n0 时,

14、0c1g(n)=f(n)=n0 时,0=f(n)=n0 时,0=cg(n)n0 时,0c1*n=F(n)=c2*n 即 0(t1+t2)*n=(t1+t2)*n+t3=(t1+t2+t3)*n 恒成立。所以 F(n)属于(n)所以 n 是F(n)的渐近确界证毕在实际应用中,我们一般都是使用渐近时间复杂度代替实际时间复杂度来进行算法效率分析。我们把这个时间复杂度记为O(n)。时间复杂度O(n)说明了最坏情况下的计算时间随着数据规模变化的函数关系是数据规模的线性函数。我们用这个函数关系作为算法的评价标准,来评价一个算法的优劣。注意这时时间复杂度与具体的计算机硬件环境和计算机语言没有关系了,只是算法

15、本身时间复杂程度的一个客观评鉴标准。一般认为,一个渐近复杂度为O(n)的算法要优于渐近复杂度为O(n2) 的算法。O(1)时间复杂度的算法计算时间与数据规模没有关系,是一个常量。以下6种计算算法时间复杂度的多项式函数是最常用的。其关系为: O(1)O(logn)O(n)O(nlogn) O(n2)O(n3)指数时间复杂度的关系为: O(2n)O(n!)Epsilon); printf(“方程的近似根是%fn”,x0);迭代算法也常用于求方程组的根,令 X=(x0,x1,xn-1)设方程组为: xi=gi(X) (i=0,1,n-1)则求方程组根的迭代算法可描述如下:例XX:迭代法求方程组的根s

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

17、对迭代的次数给予限制;2) 方程虽然有解,但迭代公式选择不当,或迭代的初始近似解选择不合理,也会导致迭代失败。迭代法用于工程数值计算需要考虑算法的收敛性问题和稳定性问题。简单地讲,只有收敛的算法才可以用计算机计算,稳定性与迭代计算的步长有关。比如微分方程组和偏微分方程组的数值求解都需要考虑这个问题。详细内容请参看数值计算方面资料。递推法是利用问题本身所具有的一种递推关系求解问题的一种方法。设要求问题规模为N的解,当N=1时,解或为已知,或能非常方便地得到。能采用递推法构造算法的问题有重要的递推性质,即当得到问题规模为i-1的解后,由问题的递推性质,能从已求得的规模为1,2,i-1的一系列解,构

18、造出问题规模为i的解。这样,程序可从i=0或i=1出发,重复地,由已知至i-1规模的解,通过递推,获得规模为i的解,直至得到规模为N的解。考虑使用迭代算法计算阶乘的问题。要求编写程序,对给定的n(n100),计算并输出k的阶乘k!(k=1,2,n)的全部有效数字。由于要求的整数可能大大超出C语言整型变量的有效位数,程序用一维数组存放长整数,存放长整数数组的每个元素只存放长整数的一位数字。如有m位成整型量N用数组a 存储: N=am10m-1+am-110m-2+ +a2101+a1100并用a0存储长整型量N的位数m,即a0=m。按上述约定,数组的每个元素存储k的阶乘k!的一位数字,并从低位到

19、高位依次存于数组的第二个元素、第三个元素。例如,5!=120,在数组中的存储形式为:3 0 2 1 首元素3表示长整数是一个3位数,接着是从低位到高位依次是0、2、1,表示成整数120。计算阶乘k!可采用对已求得的阶乘(k-1)!连续累加k-1次后求得。例如,已知4!=24,计算5!,5!=4!*(1+1+1+1+1)。原来的24累加4次24后得到120。一般地,k!可以由(k-1)!累加k-1次得到。反过来讲,知道(k-1)!值,累加k-1次即可得到k!的值。这就是递推的思想。例XX:递推算法求超过类型长的大数的阶乘。# include # include # define MAXN 100

20、0void 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 ( carry=0,i=1;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;k=n;k+

21、) pnext(a,k); write(a,k); getchar(); 1.5.1 穷举法穷举法的思想是对可行解空间众多候选解按某种顺序进行逐一枚举和检验,并从中找出那些符合要求的候选解作为问题的解。枚举过程中要穷尽所有可能,即遍历整个可行解解空间。穷举法虽然在数据规模较大时效率不高,但是在数据规模较小时还是可行的。它的主要优点是思路很简单。考虑这个问题: 将A、B、C、D、E、F这六个变量排成如图所示的三角形,这六个变量分别取1,6上的整数,且均不相同。求使三角形三条边上的变量之和相等的全部解。如图就是一个解。程序引入变量a、b、c、d、e、f,并让它们分别顺序取1至6的整数,在它们互不相

22、同的条件下,测试由它们排成的如图所示的三角形三条边上的变量之和是否相等,如相等即为一种满足要求的排列,把它们输出。当这些变量取尽所有的组合后,程序就可得到全部可能的解。例XX:三角形边长整数排列问题伪代码。TriangleP() int a,b,c,d,e,f; int TriangleIsTrue=0,isTrue1,isTrue2,isTrue3; 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;ec)&(a+cb)&(b+ca); isTrue2=(c+de)&(e+cd)&(d+ec); isTrue3=(a+ef)&(a+fe)&(e+fa); TriangleIsTru

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1