1.1.3 算法的特性
算法具有以下5个特性。
(1)确定性:算法中的每个步骤都有确定的定义,不允许出现二义性。例如对于同一个输入,必须保证每次运行能得到相同的结果。
(2)可行性:算法中的每个步骤是实际能够进行的,并且整个算法是能够在可接受时间内完成的。
(3)有限性:算法的执行步骤是有限的,是能够终止的,并且每一步骤都能在有限时间内完成。
(4)输入性:算法可以有零个或多个输入。大多数算法需要接收外界的数据来完成运算,对于一些比较简单的问题,可以不需要输入数据,例如在屏幕上打印文字。
(5)输出性:算法需要有一个或多个输出。算法的目的是求解问题,问题求解的结果应以一定的方式输出。
请阅读下列两个求1000以内能被3整除的数之和的算法,判断其是否满足算法的特性。
【例1.4】算法1。
void try1() { int s=0; int i=0; while(i%3==0) { s=s+i; i=i+3; } printf("%d\n",s); }
分析:在这个算法中,变量i的值会一直增加,将形成一个死循环,不会终止,因此不符合算法的有限性。
【例1.5】算法2。
void try2() { int s=0; int i=1; while(i%3==0&&i<=1000) { s=s+i; i=i+1; } }
分析:在这个算法中,计算完成后没有给出任何有效结果,对此,用户显然是不满意的,因此不符合算法的输出性。
我们再来看下面这个输出一个整数因子的例子,看看是否符合算法的特性。
【例1.6】算法3。
void try3() { int n=15; int i=0; while(n%i==0) printf("%d\n",i); }
分析:在这个算法中,当进行第一轮循环时i=0。i又是除数,出现了除数为零的错误,因此不符合算法的可行性。
由此可见,我们在设计算法时一定要遵循算法的5大特性,这也是评价算法优劣的依据之一。除此之外,在设计算法时,还要遵循算法的5个设计目标。
(1)正确性:算法能够满足需求,完成规定的功能和性能要求,得出正确的结果。
(2)可使用性:对于用户来说算法能够很方便地使用。
(3)可读性:算法具有良好的可读性,便于人的理解。算法的设计要条理清晰、逻辑性强且具有结构化特性。
(4)健壮性:算法要拥有应对不符合规范要求的输入情况的处理能力,对于不符合规范要求的输入,算法能够及时进行判断,并提供妥善的处理方式。
(5)高效率与低存储量:对于同一个问题来说,求解的算法不是唯一的,这就需要我们找到最优算法。当问题的规模逐渐增大时,需要考虑的问题有两个。一是算法的时间效率,执行时间越短效率越高;二是算法执行过程中所需的空间存储量,需要的空间越小越好。
【例1.7】接收用户输入的两个整数,输出它们的商。
void qu() { int a,b,q; scanf("%d,%d",&a,&b); q=a/b; printf("%d\n",q); }
分析:这个算法是存在问题的,当用户输入5和0的时候,算法执行就会出错。所以,该算法不满足健壮性这一设计目标,应修改为以下算法:
void qu1() { int a,b,q; scanf("%d,%d",&a,&b); if(b==0) printf("The divisor cannot be zero!"); else { q=a/b; printf("%d\n",q); } }