1. 什么是算法
从图1中可以看到,在抽象数据类型中,数据元素之间还是处于一个逻辑关系,仍然还是在逻辑结构上的操作功能,并不涉及到具体的实现细节。而当我们在用高级程序语言去做具体的功能实现的设计时就需要去确定数据的存储结构才能做,那么必须基于数据元素之间的物理关系(即存储结构)来确定具体存储结构上的操作实现。
图1-数据表示和功能实现
平时我们所说的算法就是在基于具体存储结构上的操作,去设计如何具体实现的细节,因此对于算法的定义就是在具体存储结构上,实现某个抽象运算。
对算法更为普遍的定义是:对特定问题求解方法(步骤)的一种描述,是指令的有限序列,其中每一条指令表示一个或多个操作。当我们把这一系列的指定执行完毕后,就能去解特定的问题。
2. 算法的重要特性
1. 有穷性:在有穷步之后结束,也就是说一个算法总是在执行有穷的步骤之后就会结束,每个步骤必须在有穷的时间内完成,对于违反了有穷性的算法是永远不能完成的,也就不能解决问题的,也就不能看做是一个算法。
2. 确定性:算法在各种情况下,执行的每个步骤都是非常明确的,没有二义性。计算机在执行这样的算法过程中能够按照确定的步骤去完成规定的工作。
3. 可行性:可通过基本运算有限次执行来实现,所有的基本操作都是能够去完成的,比如在算法中把除数取值为0是没有意义的。
4. 有输入,有输出:对于一个算法来说,有输入的数据,能够对应输入的数据产生确定的结果,进行输出。
下面来看两个算法的例子:
示例1:
void exam1()
{
int n = 2;
while (n%2 == 0)
n=n+2; /* 然后在循环内部每次+2,循环条件永远满足,因此这是一个死循环 */
printf("%d\n",n);
}
在例1中,while循环中的条件永远都能满足,这是一个死循环,所以在这个程序中违反了算法的有穷特性,该程序不能在执行有限的步骤后就结束,也就是说它不是一个算法了。
示例2:
void exam2()
{
int x,y;
y=0;
x=5/y; /* 除数y为0 */
printf("%d,%d\n",x,y);
}
在例2中,由于除数y = 0,而计算机不能去处理这样的运算,会产生除0错误,所以在这个程序中违反了算法的可行性特征,也就不是一个算法。
虽然在上面这两个例子中都不是算法,但它们都是程序。那么现在我们可以总结下算法和程序之间的关系:一个计算机程序是对一个算法使用某种程序设计语言的具体实现,通常我们在设计程序之前,都是要先设计算法的,根据算法用高级程序语言去设计程序,但是它们的区别在于算法必须可终止,可行的,有穷的,那么这意味着并不是所有的计算机程序都是算法,也就是说,对于某些程序不符合算法特征的,就不能算是一个算法
。
3. 好算法具备的特性
1. 正确性(Correctness ): 算法应满足具体问题的需求。比如我们要设计一个解决x问题的算法,但最终设计出的算法并不能解决x问题,那么这个算法不能满足好算法应该具有的特性。
2.可读性(Readability): 算法应容易供人阅读和交流。可读性好的算法有助于对算法的理解和修改
3. 健壮性(Robustness): 算法应具有容错处理。当输入非法或错误数据时,算法应能适当地作出反应或进行处理,而不会产生莫名其妙的输出结果。
4. 通用性(Generality): 算法应具有一般性 ,即算法的处理结果对于一般的数据集合都成立。
5. 效率与存储量需求: 效率指的是算法执行的时间;存储量需求指算法执行过程中所需要的最大存储空间。一般这两者与问题的规模有关。