C程序设计(第五版)整理 第二章 算法——程序的灵魂


一、程序=算法+数据结构

一个程序主要包括以下两方面的信息:
(1)对数据的描述。程序中要指定用到的数据以及数据类型和组织形式。这就是数据结构。
(2)对操作的描述。要求计算机进行操作的步骤,也就是算法。

著名计算机科学家沃思提出一个公示:算法+数据结构=程序。直到今天,这个公式对于过程化程序依然适用。

此外,一个过程化程序除了以上两个主要要素外,还应当采用结构化程序设计方法进行程序设计。并用一种计算机语言表示。因此算法、数据结构、程序设计方法和语言工具4方面是我们应具备的知识。


二、什么是算法

做任何事情都需要一定的步骤。广义地说,为解决一个问题而采取的方法和步骤,就称为算法。狭义来讲,是对于计算问题的计算方法。算法有优劣之分。

计算机算法可分为两大类别:数值运算算法和非数值运算算法。数值运算的目的是求数值解,例如求方程的根;非数值运算涉及十分广泛,如图书检索、人事管理等。目前计算机在非数值运算方面的应用远远超过了数值运算方面。

数值运算往往有现成的模型,算法比较成熟,使用方便;非数值运算的种类繁多,只有一些典型的非数值运算有现成成熟的算法可供使用,许多问题需要设计特定问题的专门算法。


三、简单的算法举例

【例2.1】求1×2×3×4×5

最原始的方法:1×2的结果再乘以3,最后得到120。一旦数字变多,就要写很多步骤。
如果这样考虑,设置两个变量p为被乘数,i为乘数。算法可为:

S1:令p=1,i=2
S2:使p与i相乘,乘积放在变量p中
S3:是i的值加1
S4:如果i<=5,返回重新执行S2及之后的步骤;否则算法结束。

如果1×3×5×7×9×11,只需将算法中的i加1改为加2,判断i<=11即可。这样的算法具有一般性、通用性和灵活性。

【例2.2】有50个学生,要求输出成绩在80分以上的学生和成绩。

S1:i=1
S2:如果gi>=80,则输出ni和gi,否则不输出
S3:i=i+1
S4:如果i<=50,返回步骤2继续执行;否则算法结束。

【例2.3】判定2000-2500年中的每一年是否为闰年,并将结果输出。

闰年的条件:被4整除但不被100整除的年份或被400整除的年份都是闰年。

S1:year=2000
S2:若year不能被4整除,则输出year的值和“不是闰年”。然后转到S6,检查下一个年份。
S3:若year能被4整除但不能被100整除,则输出year的值和“是闰年”。然后转到S6,检查下一个年份。
S4:若year能被400整除,则输出year的值和“是闰年”。然后转到S6,检查下一个年份。
S5:否则输出year的值和“不是闰年”
S6:year=year+1
S7:year<=2500时,转S2继续执行,否则算法停止。

【例2.4】求1-1/2+1/3-1/4+…+1/99-1/100

S1:sign=1
S2:sum=1
S3:deno=2
S4:sign=(-1)*sign
S5:term=sign*(1/deno)
S6:sum=sum+term
S7:deno=deno+1
S8:如果deno<=100返回S4;否则算法结束。

【例2.5】给出一个大于或等于3的正整数,判断它是不是一个素数。

判断一个数n(n>=3)是否为素数,即出了1和该数本身之外,不能被其他任何整数整除的数。例如13是素数,所以不能被2,3,…,12整除。将n作为被除数,将2~(n-1)的各个整数先后作为除数,如果都不能被整除,则为素数。

S1:输入n的值
S2:i=2
S3:n被2除,得余数r
S4:如果r=0,表示能被i整除,则输出“n不是素数”,算法结束;否则执行S5
S5:i=i+1
S6:如果i<=n-1,返回S3;否则输出n的值以及“是素数”,算法结束。

实际上除数范围可以是2 ~ (n/2),甚至只需2 ~ n \sqrt n n 即可。因为因数的两个因子的范围在1~(n/2),而两个因子必然分别在根号n左右。当然还有更高效的方法。步骤6可改为

S6:如果i<=sqrt(n) ,返回S3,否则算法结束。

四、算法的特性

一个有效的算法应具备以下特点:
(1)有穷性。一个算法应包含有限的操作步骤,而不能是无限的。
(2)确定性。算法中的每一个步骤必须是确定的,不能是含糊的模棱两可的。算法的含义应当是唯一的,不应产生歧义
(3)有零个或多个输入。输入就是从外界获取必要信息。
(4)有一个或多个输出。算法的目的是为了求解,解就是输出,但算法的输出不一定是打印输出或者屏幕输出,得到的结果就是输出。没有输出的算法是没有意义的。
(5)有效性。算法当中的每一个步骤都应当能有效地执行,并得到确定的结果。若b=0,则执行a/b是不能有效执行的。


五、怎样表示一个算法

5.1 用自然语言表示算法

第三部分的五个例子中的算法是用自然语言来表示的,自然语言就是人们日常使用的语言。用自然语言表示通俗易懂,但文字冗长,容易出现歧义,往往表示的含义不严格,要根据上下文判断其正确含义。如张先生对李先生说他的孩子考上大学了。此外自然语言描述分支和循环的算法不大方便。因此除简单问题外,一般不用自然语言表示算法。

5.2 用流程图表示算法

流程图是用一些图框来表示各种操作。用图形表示算法直观形象、易于理解。美国国家标准化协会(ANSI)规定了一些常用的流程图符号,已为世界各国程序工作者普遍采用。

在这里插入图片描述
通过以上几个例子可以看出,流程图是表示算法的较好的工具。一个流程图包括以下几部分。
(1)表示相应操作的框;
(2)带箭头的流程线;
(3)框内外必要的文字说明;
需要提醒的是流程线不要忘记画箭头,因为箭头反应流程的先后。流程图有段时期广泛使用,但是流程图占用篇幅较多,尤其算法比较复杂时,画流程图既费时又不方便,很多时候用N-S结构流程图代替传统流程图。

5.3 三种基本结构和改进的流程图

5.3.1 传统流程图的弊端

传统流程图用流程线指出各框的执行顺序,对流程线的使用没有严格限制,因此使用者可以不受限制地使用流程转来转去,使流程图变得毫无规律,阅读不便。如图2.13所示的算法称为BS型算法,意为一碗面条(a bowl of spaghetti),毫无头绪。
在这里插入图片描述
所以为了提高算法的质量,设计和阅读方便,必须顺序执行下去,不能随意转向。但是算法难免会有一些分支和循环,不可能全部顺序执行,所以需要规定几种基本结构,然后用这些基本结构按一定规律组成一个算法结构,这样算法的质量就能得到保证和提高。

5.3.2 三种基本结构

1966年,Bohra和Jacopini提出了以下三种基本结构,用这三种基本结构作为表示一个良好算法的基本单元。
(1)顺序结构。如图2.14所示,虚线框内是一个顺序结构。其中A和B两个框是顺序执行的。即:在执行完A框所指定的操作后,必然接着执行B框所指定的操作。顺序结构是最简单的一种基本结构。
(2)选择结构。选择结构又称为选取结构或分支结构,如图2.15所示。虚线框里是一个选择结构。此结构必包含一个判断框。根据给定的条件p是否成立而选择执行A框或B框。例如p条件可以是x>=0或x>y,a+b<c+d等。
注意:无论p条件是否成立,都只执行A框或B框之一,不可能都执行,在执行完后,都经过b点,然后脱离本选择结构。A或B可以有一个是空的,不执行任何操作。
在这里插入图片描述
(3)循环结构。又称重复结构,即反复执行某一部分操作。有两类循环结构。
①当型(while型)循环结构。当给定条件成立,执行A框操作,执行完A后在判断条件是否成立,如果成立再执行A,直到某一次p1条件不成立,此时不再执行A,从b点脱离循环结构。
②直到型(until型)循环结构。先执行A框,然后判断给定的p2条件是否成立,如果p2条件不成立,则再执行A,如此反复直到条件成立,此时不在执行A,从b点脱离循环结构。
在这里插入图片描述
图2.18和图2.19的作用都是输出5个数:1 2 3 4 5。对于同一个人问题既可以用当型循环也可以用直到型循环。

以上三种基本结构有以下共同特点:
(1)只有一个入口。
(2)只有一个出口。一个判断框有两个出口,而选择结构只有一个出口。
(3)结构里每一部分都有机会被执行到。每一个框都应当有一条从入口到出口的路径通过。图2.20没有
(4)结构内不存在死循环。图2.21是死循环。
在这里插入图片描述
由以上3种基本结构顺序组成的算法结构可以解决任何复杂问题。由基本结构组成的算法属于结构化的算法,不存在无规则的转向,只在本基本结构内才允许存在分支和跳转。其实基本结构并不一定只限于上面3中,只要符合上述4个特点的都可以作为基本结构。人们可以自己定义基本结构。可以认为下图这样的结构是由三种基本结构派生出来的。
在这里插入图片描述

5.4 用N-S流程图表示算法

既然按基本结构的顺序组合构成结构化的算法,那么基本结构之间就不需要流程线了。1973年,美国学者I.Nassi和B.Shneiderman提出了一种新的流程图形式,完全去掉了带箭头的流程线。全部算法写在一个矩形框内,在该框内还可以包含其他从属于它的框或者说由一些基本的框组成一个大的框。这种流程图又称为N-S结构化流程图,适用于结构化程序设计。
(1)顺序结构。图2.24。
(2)选择结构。图2.25。
(3)循环结构。图2.26和图2.27。
在这里插入图片描述
图中的A框和B框可以是一个简单的操作,也可以是3种基本结构之一。如图2.28所示的顺序结构。
在这里插入图片描述
N-S图如同一个多层的盒子,又称盒图(box diagram)。

5.5 用伪代码表示算法

流程图直观易懂,但是不便于反复修改,适合于表示一个算法,但在设计的时候是不理想的。在设计时常用一种称为伪代码(pseudo code)的工具。

伪代码是用介于自然语言和计算机语言之间的文字和符号来描述算法。它不使用图形符号,便于向计算机语言过渡。伪代码写算法并无固定的、严格的语法规则,可用英文也可用中英混用。只要意思表达清楚,便于书写和阅读即可。
在这里插入图片描述

5.6 用计算机语言表示算法

用计算机语言表示算法必须严格遵循所用语言的语法规则,这和伪代码是不同的。下面是C语言表示。
在这里插入图片描述
在这里插入图片描述
写出了C程序,仍然只是描述了算法,并未实现算法。只有运行程序才是实现算法。


六、结构化程序设计方法

一个结构化程序就是用计算机语言表示的结构化算法,用三种基本结构组成的程序必然是结构化的程序。这样的程序便于编写、阅读、修改和维护,减少了程序出错的机会,提高了程序的可靠性,保证了程序的质量。

结构化程序设计强调程序设计风格和程序结构的规范化,提倡清晰的结构。基本思路是:把一个复杂的问题求解过程分阶段进行,每个阶段处理的问题都控制在人们容易理解和处理的范围内。

具体说,采取以下方法保证得到结构化的程序:
(1)自顶向下
(2)逐步细化
(3)模块化设计。模块的独立性。
(4)结构化编码。3种基本结构。

接受一个任务并着手进行有两种不同方法,一种是自顶向下,逐步细化;一种是自下而上,逐步积累。
在这里插入图片描述


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

正在輸入......

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值