首页 理论教育算法基本元素、循环结构

算法基本元素、循环结构

【摘要】:算法所具有的确定性、可终止性和可执行性,奠定了用计算机执行算法的基础。要解决算法的表示问题,第一步需要确定算法的基本元素。所谓算法的基本元素包含两个方面的含义,一个方面是描述算法的基本单词,另一个方面是每个基本单词的语义含义。算法中的这种结构称作循环结构。设符号WHILE和DO是算法中表示循环结构的符号,循环语句的格式为WHILEDO activity其中,condition表示条件,activity表示一种处理方法。

算法所具有的确定性、可终止性和可执行性,奠定了用计算机执行算法的基础。但要做到让计算机理解算法,必须解决算法的表示问题。要解决算法的表示问题,第一步需要确定算法的基本元素。所谓算法的基本元素包含两个方面的含义,一个方面是描述算法的基本单词,另一个方面是每个基本单词的语义含义。这就像一种语言由单词和单词的语义两个方面构成一样。

分析算法,我们可以总结出所有算法的基本元素。算法的基本元素主要有以下五类。

1.变量

大多数算法描述的问题求解过程都是高度概括的,适合于求解同类型的各种具体问题的。例如,6.1节讨论的求解两个整数的最大公约数问题的算法,就可以求解任意整数M和整数N的最大公约数。当把该算法用于求解某个具体问题,如求整数48和整数36的最大公约数时,即是要用整数48代表M,用整数36代表N。因此,算法中符号M和符号N是某个具体数值的表示。不仅如此,在算法中,随着算法求解过程的进行,符号M和符号N所代表的数值还可以改变。例如,操作步骤“令M 等于N”后,符号M所代表的数值就发生了改变。我们把算法中代表某个具体数值,并可以改变其数值的符号称作变量。

变量可以用一个或若干个字符符号来表示。例如,在求解两个整数的最大公约数问题的算法中,符号M、N、R就是三个变量。又例如,可以定义符号age为一个表示某个人年龄数值的变量,还可以定义符号sum为表示若干个数值连加和的变量。

2. 赋值

在算法中,赋值是实现给变量赋值,或对变量中的数值进行修改的一种操作。我们用符号ASSIGN表示赋值,赋值语句格式为

ASSIGN name value

或 ASSIGN name valueExpression

前一个赋值语句表示把一个具体的数值value赋给符号名字为name的变量。后一个赋值语句表示把一个表达式valueExpression的运算结果(其值为一个确定的数值)赋给符号名字为name的变量。

例如,若定义age为一个变量,就可以用如下赋值语句把数值20存放在变量age中:

ASSIGN age 20

又如,当要表示某人的年龄要在原来年龄的基础上加一岁时,就可以用如下赋值语句实现:

ASSIGN age age+1

其中,age+1就是一个表达式,当变量age中原来存放的数值是20时,则该表达式的运算结果就是21。该赋值语句执行完后,变量age中的数值就不再是20,而变成了21。

3.分支

在算法描述中,经常要根据不同的情况进行不同的处理。例如,对于一个分段函数,当自变量x满足某种条件时,函数y=f(x)就取某个数学表达式;当自变量x满足另一种条件时,函数y=f(x)就取另一个数学表达式。算法中的这种结构称作分支结构。

设符号IF、THEN和ELSE是算法中表示分支结构的符号,分支语句的格式为:

IF(condition)THEN activityOne

ELSE activityTwo

或 IF(condition)THEN activity

其中,condition表示条件,activityOne表示一种处理方法,activityTwo表示另一种处理方法。前一种语句格式的含义是:当条件condition成立时,执行处理方法activityOne;否则(即条件condition不成立时),执行处理方法activityTwo。前一种语句的执行过程如图6-1(a)所示。后一种语句格式是分支语句的一种简单情况,其含义是:当条件condition成立时,执行处理方法activity;否则,不作任何处理。后一种语句的执行过程如图6-1(b)所示。在分支语句中,一种处理方法既可以是一条语句,也可以是一组语句。

图6-1 分支语句的执行过程

(a)分支类型1;(b)分支类型2

例如,下面例子就描述了x大于0和x小于或等于0两种情况时两个分支的不同处理:

IF(x>0)THEN ASIGN y x+3

ELSE ASIGN y x+5

又例如,下面例子描述了当x大于10时y等于y+1,而当x小于或等于10时不作任何处理的分支处理:

IF(x>10)THEN ASIGN y y+1

分支语句可以嵌套使用,嵌套形式的分支语句可以表示三种或三种以上的不同处理情况。例如,下面例子就描述了当x等于0、x小于0、x大于0三种情况时的分支处理:

IF(x==0)THEN ASIGN y x+3

ELSE

IF(x<0)ASIGN y x+5

ELSE ASIGN y x-5

4.循环

在算法描述中,经常要在满足某种条件的情况下,连续不断地执行某个相同的处理方法。例如,要完成1到100的累加运算,就可以令变量sum初始为数值0,令变量x初始为数值1,然后判断变量x是否小于或等于100,当x小于或等于100时,令变量sum等于sum+x,并且令变量x等于x+1;当x大于100时,结束这种处理过程。算法中的这种结构称作循环结构。

设符号WHILE和DO是算法中表示循环结构的符号,循环语句的格式为

WHILE(condition)DO activity

其中,condition表示条件,activity表示一种处理方法。循环语句的含义是:当条件condition成立时,执行处理方法activity。这里所说的处理方法既可以是一条语句,也可以是一组语句。为了使循环过程在有限步后结束,在处理方法activity中一定要对条件condition作某种改变,并要使这种改变每次都更逼近条件condition不成立。循环语句的执行过程如图6-2所示。

图6-2 循环语句的执行过程

例如,求1到100的累加和问题的算法就可以描述如下:

ASIGN sum 0

ASIGN x 1

WHILE(x<=100)DO

{

ASIGN sum sum+x

ASIGN x x+1

}

上述算法中语句ASIGN sum sum+x完成累加运算,语句ASIGN x x+1既完成变量数值增1,又完成对条件x<=100作某种改变,并使这种改变每次都更逼近条件x<=100不成立。由于上述循环结构的循环体部分有两条语句,所以在书写时要用一对花括号括起来。(www.chuimin.cn)

如果算法中没有对变量x的改变,或没有使这种改变每次都更逼近条件x<=100不成立(若语句为ASIGN x x-1,就不会更逼近条件x<=100不成立),则上述算法就永远不会结束。永远不会满足循环结束条件的循环结构称为死循环。我们知道,算法的定义限制算法必须具有有穷性,所以,算法设计要避免出现死循环。

循环语句也可以嵌套使用,由于嵌套结构的循环语句例子对初学者来说过于复杂,这里我们不做讨论。

5.过程

一个算法可以在许多地方使用,若要把一个算法表示成许多地方都能使用的形式,就需要规定一种固定格式,这就是过程。设符号PROCEDURE是算法中表示过程的符号,过程语句的格式为:

PROCEDURE Name(ParameterList)

{

过程体

}

其中,Name是过程名,一对花括号括起来的部分是过程体。过程体可以是任意语句序列。ParameterList是过程的参数表,一个过程通常有若干个参数,这若干个参数称为该过程的参数表。参数是一个数值未定的变量,这样就可以用一个带参数表的过程表示一个范围很宽的算法。

例如,求1~100的累加和问题的算法是一个使用范围较窄的算法,具体算法如前所述;而求1~n(n为任意的整数)的累加和问题的算法就是一个使用范围较宽的算法,可以把后一个问题表示成带一个参数的过程。求1~n的累加和问题的过程如下:

PROCEDURE Sum1(n)

{

ASIGN sum 0

ASIGN x 1

WHILE(x<=n)DO

{

ASIGN sum sum+x

ASIGN x x+1

}

}

其中,符号Sum1是过程名,n是该过程的参数。

一个过程可以有若干个参数。例如,求n1~n2的累加和问题就可以表示成如下过程:

PROCEDURE Sum2(n1,n2)

{

ASIGN sum 0

ASIGN x n1

WHILE(x<=n2)DO

{

ASIGN sum sum+x

ASIGN x x+1

}

}

其中,符号Sum2是过程名,n1和n2是该过程的两个参数,n1表示要累加的起始数值, n2表示要累加的结束数值。

一个过程也可以没有一个参数。例如,求1~100的累加和问题就可以表示成不带参数的如下过程:

PROCEDURE Sum3

{

ASIGN sum 0

ASIGN x 1

WHILE(x<=100)DO

{

ASIGN sum sum+x

ASIGN x x+1

}

}

其中,符号Sum3是过程名,该过程没有参数。

过程使我们可以把一个复杂问题的大算法表示成若干个简单问题的小的过程模块的合成,这就像我们可以把制造一个汽车的过程,分解成先分别制造发动机轮胎车灯等部件,然后再把这些部件组装起来一样。从这个意义上说,过程是构造复杂问题的大算法的小的单元,所以过程也称作单元。另外,过程还有其他名字,如函数、子程序、子例程等,这是不同的高级程序设计语言在实现过程时使用不同术语的缘故。

一个过程既可以调用另一个过程,也可以调用自身过程。我们把过程中存在调用自身过程的过程称为递归过程。我们将在6.4.2节讨论递归过程。