1、第二章 程序设计的灵魂算法,清华大学 自动化系 刘连臣2009年9月15日,计算机语言与程序设计基础,1,主要内容,目标:以计算机能执行的算法特征为线索,了解计算机的模型与结构,掌握程序设计基本理念,为程序设计语言的学习奠定基础。提纲 2.1 算法与计算机算法 2.2 图灵机模型 2.3 程序设计的灵魂算法 2.4 计算机算法的表示 2.5 算法结构化分析,2,2.1 算法与计算机算法,程序设计的目的是什么?从计算机解决问题的过程出发,设计出计算机能够执行的算法,并且实现该算法。,3,2.1 算法与计算机算法,算法:为解决一个问题而采取的方法和步骤,或者说是解题步骤的精确描述。“a set o
2、f rules that must be followed when solving a particular problem ”“算法”即演算法的中文名称最早出自周髀算经。 英文名称 Algorithm 来自于9世纪波斯数学家花拉子密(比阿勒霍瓦里松)。“算法”原为“algorism”(阿拉伯数字的运算法则),18世纪演变为“algorithm“。,4,2.1 算法与计算机算法,对同一个问题,可有不同的解题方法和步骤,好的算法:方法简单、运算步骤少、能迅速得出正确结果的算法。对于算法的优劣评价可以用空间复杂度与时间复杂度来衡量。,5,2.1 算法与计算机算法,计算机算法:计算机能执行的算法。
3、 是计算机处理信息的本质,因为计算机程序本质上是一个算法来告诉计算机确切的步骤(well-defined procedure)来执行一个指定的任务。计算机算法的特点 输入:一个算法必须有零个或以上输入量。 输出:一个算法应有一个或以上输出量,输出量是算法计算的结果。 明确性:算法的描述必须无歧义,以保证算法的实际执行结果是精确地符合要求或期望,并且要求实际执行结果是确定的。 有限性:(计算机只有有限个状态、有限个输入符号和有限个指令)规定算法必须在有限个步骤内完成任务。 有效性:又称可行性。算法中描述的操作都是可以通过已经实现的基本运算执行有限次来实现。,6,2.1 算法与计算机算法,算盘有二
4、五珠算盘 、一五珠算盘 、九珠算盘等用算珠来表示数字。 有对应四则运算的珠算法则。 有操作指法。思考 输入? 输出? 明确性? 有限性? 有效性?,7,2.2 图灵机模型,什么是“确切的步骤” 精确的定义?20世纪的英国数学家图灵提出了著名的图灵论题,并提出一种假想的计算机的抽象模型,这个模型被称为图灵机。,1912年6月23日1954年6月7日,图灵机的艺术表示 (1936年提出),8,2.2 图灵机模型,图灵的基本思想是用机器来模拟人们用纸笔进行数学运算的过程 在纸上写上或擦除某个符号; 把注意力从纸的一个位置移动到另一个位置; 而在每个阶段,人要决定下一步的动作,依赖于 (a) 此人当前
5、所关注的纸上某个位置的符号。 (b) 此人当前思维的状态。,9,2.2 图灵机模型,图灵机组成构造出一台假想的机器,该机器由以下几个部分组成:一条无限长的纸带 TAPE。 一个读写头 HEAD。 一套控制规则 TABLE。 一个状态寄存器。 注意这个机器的每一部分都是有限的,但它有一个潜在的无限长的纸带,因此这种机器只是一个理想的设备。图灵认为这样的一台机器就能模拟人类所能进行的任何计算过程。,10,2.2 图灵机模型,图灵机工作原理从读写头在纸带上读出一个方格的信息 并且根据它当前的内部状态开始对控制规则进行查寻。然后得出一个输出动作,也就是是否往纸带上写信息,还是移动读写头到下一个方格。程
6、序也会告诉它下一时刻内部状态转移到哪一个。具体的控制规则就是一个列表,其实就是程序,样子如右侧表。,11,2.2 图灵机模型,图灵机只要根据每一时刻读写头读到的信息和当前的内部状态进行查表就可以确定它下一时刻的内部状态和输出动作。图灵机就是这么简单!而只要你变化它的程序(也就是上面的规则表),那么它就可能为你做任何计算机能够完成的工作。可以说,图灵机就是一个最简单的计算机模型!,12,2.3 程序设计的灵魂算法,一个程序应包括两个方面的内容对数据的描述:数据结构(data structure) 对操作的描述:算法(algorithm)完整的程序设计应该是:,著名计算机科学家沃思提出一个公式 数
7、据结构 + 算法 = 程序,程序程序语言,13,2.3 程序设计的灵魂算法,例2.1: 求12345步骤1:先求12,得到结果2 步骤2:将步骤1得到的乘积2再乘以3,得到结果6 步骤3:将6再乘以4,得24 步骤4:将24再乘以5,得120如果要求121000,则要写999个步骤应该怎么办呢?,太繁琐,14,2.3 程序设计的灵魂算法,可以设两个变量:一个变量代表被乘数,一个变量代表乘数。不另设变量存放乘积结果,而直接将每一步骤的乘积放在被乘数变量中。设p为被乘数,i为乘数。用循环算法来求结果, 算法可改写:S1:使p=1。 S2:使i=2。 S3:使pi,乘积仍放在变量p中,可表示为:pi
8、 p S4:使i的值加1,即i+1 i。 S5:如果i不大于5,返回重新执行步骤S3以及其后的步骤S4和S5;否则,算法结束。最后得到p的值就是5!的值。,15,2.3 程序设计的灵魂算法,如果题目改为:求1357911算法只需作很少的改动:S1: 1p S2: 3 i S3: pi p S4: i+2 p S5:若i11,返回S3。否则,结束。 用这种方法表示的算法具有通用性、灵活性。S3到S5组成一个循环,在实现算法时 要反复多次执行S3,S4,S5等步骤,直到某一时刻,执行S5步骤时经过判断,乘数i已超过规定的数值而不返回S3步骤为止。此时算法结束,变量p的值就是所求结果。,算法简练,1
9、6,2.3 程序设计的灵魂算法,例2.2 判定20002500年中的每一年是否闰年,输出结果。分析:闰年的条件是: 能被4整除,但不能被100整除的年份都是闰年,如1996,2004年是闰年; 能被100整除,又能被400整除的年份是闰年。如1600,2000年是闰年。 不符合这两个条件的年份不是闰年。,17,2.3 程序设计的灵魂算法,设y为被检测的年份,算法可表示如下 :S1:2000 y S2:若y不能被4整除,则输出y “不是闰年”。然后转到S6。 S3:若y能被4整除,不能被100整除,则输出y “是闰年”。然后转到S6。 S4:若y能被100整除,又能被400整除,输出y“是闰年”
10、,否则输出“不是闰年”。 然后转到S6。 S5: 输出y “不是闰年”。 S6:y+1 y S7:当y2500时,转S2继续执行,如y2500,算法停止。,18,以上算法中每做一步都分别分离出一些范围(巳能判定为闰年或非闰年),逐步缩小范围,直至执行S5时,只可能是非闰年。“其它” 包括能被4整除,又能被100整除,而不能被400整除的那些年份(如1990) 是非闰年。,2.3 程序设计的灵魂算法,19,2.3 程序设计的灵魂算法,算法的三种基本结构 Bohra和Jacopini于1966年提出了以下三种基本结构: 顺序执行结构 选择执行结构 循环执行结构由三种基本结构顺序组成的算法结构,可以
11、解决任何复杂问题。 由基本结构所构成的算法属于“结构化”的算法,它不存在无规律的转向,只在本基本结构内才允许存在分支和向前或向后的跳转。,20,2.4 计算机算法的表示,2.4.1 用自然语言表示算法自然语言就是人们日常使用的语言,可以是汉语或英语或其它语言。用自然语言表示通俗易懂,但文字冗长,容易出现“歧义性”。自然语言表示的含义往往不大严格,要根据上下文才能判断其正确含义,描述包含分支和循环的算法时也不很方便。因此,除了那些很简单的问题外,一般不用自然语言描述算法。,21,2.4 计算机算法的表示,2.4.2 用流程图表示算法 美国国家标准化协会ANSI(American National
12、 Standard Institute)1985年发布并规定了一些常用的流程图符号。(国际标准化组织公布的标准ISO5807-85) 国家标准局批准的国家标准(GB1525-89),22,2.4 计算机算法的表示,三种基本结构的图示:,顺序结构,选择结构,23,2.4 计算机算法的表示,循环结构的图示:,当型(While型)循环结构,直到型(Until型)循环结构,24,2.4 计算机算法的表示,三种基本结构的共同特点: 只有一个入口。 只有一个出口。(请注意:一个菱形判断框有两个出口,而一个选择结构只有一个出口。不要将菱形框的出口和选择结构的出口混淆。) 结构内的每一部分都有机会被执行到。
13、结构内不存在“死循环”(无终止的循环)。,25,2.4 计算机算法的表示,流程图是表示算法的较好的工具。包括以下几部分 : 表示相应操作的框; 带箭头的流程线; 框内外必要的文字说明。将例2.1求5!的算法用流程图表示。,26,2.4 计算机算法的表示,将例2.2判定闰年的算法用流程图表示,用流程图表示算法要比用文字描述算法逻辑清晰、易于理解。,27,2.4 计算机算法的表示,2.4.2 用N-S流程图表示算法 1.传统流程图的弊端流程线的使用没有严格限制 占用太多地方2 . 1973年, I.Nassi和B.Shneiderman进行改进。 完全去掉了带箭头的流程线。 全部算法写在一个矩形框
14、内,在该框内还可以包含其它的从属于它的框,或者说,由一些基本的框组成一个大的框。 这种流程图又称N-S结构化流程图。,28,N-S流程图用以下的流程图符号:,(1)顺序结构,(2)选择结构,(3)循环结构,2.4 计算机算法的表示,29,将例2.1的求5!算法用 N-S图表示,2.4 计算机算法的表示,30,将例2.3判定闰年的算法用N-S图表示,31,2.4.3 用伪代码表示算法概念:伪代码是用介于自然语言和计算机语言之间的文字和符号来描述算法。 特点:它如同一篇文章一样 ,自上而下地写下来。每一行(或几行)表示一个基本操作。它不用图形符号,因此书写方便 、格式紧凑,也比较好懂,也便于向计算
15、机语言算法(即程序)过渡。 用处:适用于设计过程中需要反复修改时的流程描述。,2.4 计算机算法的表示,32,IF x is positive THENprint xELSEprint -x 也可以用汉字伪代码表示:若 x为正打印 x否则打印 -x 也可以中英文混用,如:IF x 为正print xELSEprint -x,例: “打印x的绝对值”的算法可以用伪代码表示为:,2.4 计算机算法的表示,33,开始置t的初值为1置i的初值为2当i=5,执行下面操作:使t=ti使i=i+1循环体到此结束输出t的值结束,也可以写成以下形式: BEGIN算法开始1t2 iwhile i5ti t i+1
16、 iprint tEND算法结束,例求5!。用伪代码表示算法:,2.4 计算机算法的表示,34,2.4 计算机算法的表示,2.4.4 用计算机语言表示算法概念:用计算机实现算法。计算机是无法识别流程图的。只有用计算机语言编写的程序才能被计算机执行。因此在用流程图描述出一个算法后,还要将它转换成计算机语言程序。 程序设计语言特点:用计算机语言表示算法必须严格遵循所用的语言的语法规则。,提供了一种表达数据与处理数据的功能 程序的执行过程实际上是对程序所表达的数据进行处理的过程。,35,9种控制语句: if( )else for( ) while( ) dowhile( ) continue bre
17、ak switch goto return,34种运算符: 算术运算符:+ - * / % + - 关系运算符: = != 逻辑运算符:! & | 位运算符 : | & 赋值运算符:= 及其扩展 条件运算符:?: 逗号运算符:, 指针运算符:* & 求字节数 :sizeof 强制类型转换:(类型) 分量运算符:. - 下标运算符: 其它 :( ) -,32个关键字:(由系统定义,不能重作其它定义) auto break case char const continue default do double else enum extern float for goto if int long r
18、egister return short signed sizeof static struct switch typedef unsigned union void volatile while,2.4 计算机算法的表示,36,2.4 计算机算法的表示,例 将例2.1表示的算法(求5!)用C语言表示。,#include void main( )int i,t;t=1;i=2;dot=t*i;i=i+1;while (i=5)printf(%dn,t);,变量定义,循环结构,输出语句,应当强调说明:写出了C程序,仍然只是描述了算法,并未实现算法。只有运行程序才是实现算法。应该说,用计算机语言表
19、示的算法是计算机能够执行的算法。,37,2.5 结构化程序设计方法,一个结构化程序 就是用高级语言表示的结构化算法。用三种基本结构组成的程序必然是结构化的程序,这种程序便于编写、便于阅读、便于修改和维护。结构化程序设计强调程序设计风格和程序结构的规范化,提倡清晰的结构。结构化程序设计方法的基本思路是:把一个复杂问题的求解过程 分阶段进行,每个阶段处理的问题都控制在人们容易理解和处理的范围内。,38,采取以下方法来保证得到结构化的程序: 自顶向下; 逐步细化; 模块化设计; 结构化编码。,两种不同的方法: 自顶向下,逐步细化; 自下而上,逐步积累。,2.5 结构化程序设计方法,39,用这种方法逐
20、步分解,直到作者认为可以直接将各小段表达为文字语句为止。这种方法就叫 做“自顶向下,逐步细化”。,40,自顶向下,逐步细化方法的优点:考虑周全,结构清晰,层次分明,作者容易写,读者容易看。如果发现某一部分中有一段内容不妥,需要修改,只需找出该部分修改有关段落即可,与其它部分无关。我们提倡用这种方法设计程序。这就是用工程的方法设计程序。,模块设计的方法: 模块化设计的思想实际上是一种“分而治之”的思想,把一个大任务分为若干个子任务,每一个子任务就相对简单了。 在拿到一个程序模块以后,根据程序模块的功能将它划分为若干个子模块,如果这些子模块的规模还嫌大,还再可以划分为更小的模块。这个过程采用自顶向
21、下方法来实现。 子模块一般不超过50行。 划分子模块时应注意模块的独立性,即:使一个模块完成一项功能,耦合性愈少愈好。,2.5 结构化程序设计方法,41,模块设计的方法: 模块化设计的思想实际上是一种“分而治之”的思想,把一个大任务分为若干个子任务,每一个子任务就相对简单了。 在拿到一个程序模块以后,根据程序模块的功能将它划分为若干个子模块,如果这些子模块的规模还嫌大,还再可以划分为更小的模块。这个过程采用自顶向下方法来实现。 子模块一般不超过50行。 划分子模块时应注意模块的独立性,即:使一个模块完成一项功能,耦合性愈少愈好。,2.5 结构化程序设计方法,42,2.5 结构化程序设计方法,43,小结与要求,小结 算法与计算机算法 (可执行的算法) 图灵机模型 (理想化的计算机) 程序设计的灵魂算法 (算法决定程序设计内容) 计算机算法的表示 (流程图或语言是程序设计的形式) 体会结构化设计方法要求 掌握计算机算法主要特征 理解图灵机结构与工作原理 理解“数据结构 + 算法 = 程序”的含义 熟悉程序流程图表示法 深入理解结构化分析方法,谢谢各位同学!,请提宝贵意见。,