1初识算法
用计算机解决一个现实中的问题步骤:
1. 问题分析
2. 数学模型建立
3. 算法设计与选择
4.算法表示
5.算法分析
6.算法实现
7.程序调试
8.结果整理文档编制
1. 问题分析
准确、完整地理解和描述问题是解决问题的第一步。要做到这一点,必须注意以下一些问题:在未经加工的原始表达中,所用的术语是否都明白其准确定义?题目提供了哪些信息?这些信息有什么用?题目要求得到什么结果?题目中作了哪些假定?是否有潜在的信息?判定求解结果所需要的中间结果有哪些?等等。必须认真审查表达问题的有关描述,深入分析,以加深对问题的了解。
2、数学模型建立
用计算机解决实际问题必须有合适的数学模型,因为在现实问题面前,计算机是无能为力。对一个实际问题建立数学模型,可以考虑这样两个基本问题:最适合于此问题的数学模型是什么?是否有已经解决了的类似问题可借鉴?
如果上述第二个问题的答复是肯定的,那么通过类似的问题的分析、比较和联想,可加速问题的解决。
3、算法设计与选择
算法设计是指设计求解某一特定类型问题的一系列步骤,并且这些步骤是可以通过计算机的基本操作来实现的。算法设计要同时结合数据结构的设计,简单说数据结构的设计就是选取存储方式。算法的设计与模型的选择更是密切相关的,但同一模型仍然可以有不同的算法,而且它们的有效性可能有相当大的差距。
4、算法分析
算法分析的目的,首先为了对算法的某些特定输入,估算该算法所需的内存空间和运行时间;其次是为了建立衡量算法优劣的标准,用以比较同一类问题的不同算法。通常将时间和空间的增长率作为衡量的标准。另参见1.1.4算法及其设计的评价
5、算法表示
对于复杂的问题,确定算法后可以通过图形准确表示算法。算法的表示方式很多如:算法流程图、盒图、PAD图和伪码(类似于算法设计语言)等。
6、算法实现
根据选用的算法设计语言,要解决下列一些问题:有哪些变量,它们是什么类型?需要多少数组,规模有多大?用什么结构来组织数据?需要哪些子算法?等等。
算法的实现方式,对运算速度和所需内存容量都有很大影响。
7、程序调试
算法测试的实质是对算法应完成任务的实验证实,同时确定算法的使用范围。测试方法一般有两种:白盒测试对算法的各个分支进行测试;黑盒测试检验对给定的输入是否有指定输出。
如何选择算法测试中的输入,还没有一般答案。通常采用的方法是,对输入数据做有代表性的采样,使之对被测试算法的各个语句、分支和路径尽可能都被检查到。对输入集中的边界点也要进行测试。经测试验证是否正确的算法,在较大程度上是可以相信它的正确性。
8、结果整理文档编制
编制文档的目的是让人了解你编写的算法。首先要把代码编写清楚。代码本身就是文档。同时还要采用注释的方式,另外还包括算法的流程图,自顶向下各研制阶段的有关记录,算法的正确性证明(或论述),算法测试结果,对输入/输出的要求及格式的详细描述等。
算法的要素
算法由操作、控制结构、数据结构三要素组成。
操作
算术运算:加、减、乘、除
关系比较:大于、小于、等于、不等于
逻辑运算:与、或、非
数据传送:输入、输出, 赋值
控制结构 —— 各操作之间的执行次序。
顺序结构:各操作依次执行
选择结构:由条件是否成立来选择 执行
循环结构:有些操作要重复执行,直到功能满 足某个条件时结束。又称重复或迭 代结构。
数据结构
算法操作的对象是数据,数据间的逻辑关系、数据的存储方式及处理方式就是数据的数据结构。它与算法设计是紧密相关的。
在算法的表示中要满足以下的性质:
目的性 算法有明确的目的,能完成赋予它的功能
分步性 算法为完成其复杂的功能,由一系列计算机可执行的步骤组成
有序性 算法的步骤是有序的,不可随意改变算法步骤的执行顺序
有限性 算法是有限的指令序列,所包含步骤也是有限的
操作性 算法是有限的指令序列,算法所包含的步骤是有限的
算法的基本特征
有穷性
一个算法在执行有穷步之后必须结束。也就是说一个算法它所包含的计算步骤是有限的而且每个步骤都能在有限时间内完成。
确定性
对于每种情况下所应执行的操作,在算法中都有确切的规定,使算法的执行者或阅读者都能明确其含义及如何执行。并且在任何条件下,算法都只有一条执行路径。
可行性
算法中描述的操作都可以通过已经实现的基本操作运算有限次实现。
算法有零个或多个的输入
有些输入量需要在算法执行过程中输入,而有的算法表面上可以没有输入,实际上已被嵌入算法之中。
算法有一个或多个的输出
它是一组与输入有确定关系的量值,是算法进行信息加工后得到的结果。
算法设计应注意的问题
1)正确性(Correctness)
一切合法的输入数据都能得出满足要求的结果;典型、苛刻的几组输入数据也能够得出满足要求的结果
2)可读性(Readability)
算法应该易于人的理解;晦涩难读的算法易于隐藏较多错误而难以调试。
3)健壮性(Rubustness)
算法的异常情况。处理出错的方法是返回一个表示错误或错误性质的值,以便在更高的抽象层次上进行处理。
4)高效率与低存储量需求
效率指的是算法执行时间;存储量指的是算法执行过程中所需的最大存储空间。
问题求解的步骤可以简化为三步:
具体(问题的现实领域)
(1)问题分析建立模型 抽象(逻辑结构、模型建立、功能确认)
(2)算法设计 具体(计算机世界)
(3)算法分析 抽象(性能及算法文档)。
数学建模是在对问题的认真分析加上必要的数学知识来确定问题的解决方法。对一般的问题,我们把这一步称为“问题分析”,是确认问题和问题的基本运算的。运算只描述处理功能,第二步“算法设计”是对处理功能的求精,即找出问题的处理步骤。第三步“算法分析”是对数学模型的建立、数据结构的选择及算法设计工作的评价、总结。
【例】求二个正整数的最大公约数。
问题分析:此题只需有小学知识,就可有以下建立以下的数学模型。
数学模型:a,b>0 的整数,求c,c能整除a,b,且a/c与b/c互质。
算法设计:这个方法首先基于人能“宏观”地“看出”所求两数的公约数才能继续的。计算机虽没有“宏观”能力来“看出”公约数,但通过“枚举尝试”(逐个尝试)就可以“试出”a,b有哪些是公约数,并将这些公约数“累乘”,就能得到最大公约数。
具体算法设计:
1)用for循环枚举可能的因数,并用变量累乘求出的因数。
2)注意到2因数在“4,8”两个数据中出现两次,所以,测试某因数是否所给数据的因数时,应该用循环语句而不是条件语句。
算法描述如下: zdgys( ) {int a,b,c,i; input a,b; c=1; //变量c是为累乘因数而设置的; for (i=2; i<=a and i<=b; i++) //“枚举”可能的公约数 while (a mod i==0 and b mod i==0 ) //“试”i是否为公约数 {c=c*i; a=a/i; b=b/i;} print(“%d is maximal common divisor”,c); }
算法说明:若是则进入内层循环累乘因数,并且除掉这个因数,避免下次重复处理该因数。
算法分析:通过以上算法设计过程应该看到,可以依赖以前学到的解决问题方法,改进有关步骤以便能通过机械的计算机操作(准确地说是通过算法设计语言)来实现。