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);  
        }  }