1、第二章 基本控制结构程序设计,C+程序设计,结构化程序设计的特点是任何程序都可由三种基本结构及其组合来描述。本章将介绍C+分支结构和循环结构的设计方法。还将介绍一些常用算法。,2.2 分支结构程序设计,2.7 枚举类型,2.6 常用算法的应用实例,2.4 转向语句,2.3 循环结构程序设计,2.8 输入输出文件简介,2.5 结构化程序设计思想(选读),2.1 算法的概念与表示方法,2.1 算法的概念与表示方法,2.1.1 算法的概念 2.1.2 算法的表示 2.1.3 算法描述的三种基本结构,算法: 算法是解决问题的步骤。计算机算法的特征:可执行性确定性有穷性可输入输出信息算法是程序设计学习的
2、重点。,2.1.1 算 法 的 概 念,2.1.2 算法的表示,流程图:算法的图形化表示方法 矩形框 : 表示要执行的指令,在框内标注指令内容; 菱形框 : 表示要判断其中表达式的值是真还是假; 箭头线 : 标示指令的流程方向。 伪码: 伪码是介于自然语言和程序设计语言之间的一种类自然语言的表示方法,书写形式自由,容易转换为程序。,2.1.2算法的表示,活动图: UML活动图(activity diagram)用于计算流程和工作流程建模。通常使用活动图来表达顺序程序的流程,这点与传统的流程图很相似,仅仅图示方法上有所不同。 活动图要素: 1)活动(activity):用一个上下为直线两侧为圆弧
3、的框表示,并在框内写明活动的名称。 2)转移(transition):采用箭头表示。 3)分支(branch):采用菱形符号。 4)注解(note):采用右上角折叠的矩形表示,说明UML图中符号的意义,它与被说明的符号间用虚线连接。 5)起点:起始标志,采用黑色实心圆点表示。 6)终点:结束标志,采用实心的小同心圆表示。,任何算法的描述都可以分解为三种基本结构或它们的组合,顺序结构分支结构循环结构,2.1.3算法描述的三种基本结构,num115;,【例21】 求两数之和。,显示结果:35,num220;,sumnum1+num2;,输出sum;,顺序结构,活动图,问题提出,从键盘上输入一个十进
4、制数正整数,若输入正确,将其转换成对应的二进制数。否则输出“输入有错误”。,1、解决问题的步骤(算法) 2、流程图 3、编写程序 4、上机调试,验证结果,顺序结构,no,yes,余数,97,2,48, 1,2,24, 0,2,12, 0,2,6, 0,2,3, 0,2,1, 1,2,0, 1,高位,低位,yes,no,顺序结构,【例22】 输入三个数,输出其中的最大数。,x7;,y12;,z10;,if(xy) maxx; else max y;,if (zmax) maxz;,输出max;,显示结果:12,演示算法执行过程,分支结构,【例23】求4个整数的和。,显示结果:60,演示算法执行过
5、程,12,3,14,26,2,16,42,1,18,60,0,count4; /整数个数 sum0; /累加和的初值 while (count0) x输入一个整数;sumsum+x; countcount-1; 输出sum;,循环结构,2.2 分支结构程序设计,2.2.1 if语句 2.2.2 if语句的嵌套 2.2.3 条件运算符 2.2.4 switch语句,分支结构,对程序的运行流程进行控制,主要 通过执行专门用来控制流程的语句来实现。分支语句是基本流程控制语句之一,2.2.1 if 语句,if (表达式) 语句1; if (表达式) 语句1; else 语句2;,执行流程,if (表达
6、式) 语句1;,2.2.1 if 语句,执行流程,2.2.1 if 语句,if (表达式) 语句1; else 语句2;,分析:读入三个数,先求出两个数中较大者,再将该大数与第三个数比较,求出最大数。 int main()int a, b, c, max;coutabc;cout=b) max=a; else max=b;if (cmax) max=c; cout “最大数为:”maxendl; return 0; ,【例2.5】 从键盘上输入三个整数,输出其中的最大数。,例2.4 输入一个年份,判断是否为闰年,#include using namespace std; int main ()
7、 int year; cout year ; if (year%4=0 ,逻辑运算: 用于判断分析,运算符包括关系和逻辑运算符。 关系运算符: 包括:(大于)、(大于等于)、(小于)、(小于等于);= =(等于)和!=(不等于) 。关系运算符完成两个操作数大小的比较,结果为逻辑值true(真)或false(假)。,在C+中这两个逻辑值与整数之间有一个对应关系,真对应1,假对应0;反过来,0对应假,非0整数对应真。所以逻辑运算结果可以作为整数参与算术运算、关系运算、逻辑运算及其他运算。,逻辑运算、逻辑表达式及其求值优化,例如: a+bc+d /*等同于(a+b)(c+d),结果为0或1*/ y=
8、ab /*计算ab的值0或1赋给y,y的值为0或1*/ abc /*等同于(ab)c,先求ab 的值,再将结果0或1与c比较大小*/,注意:数学式abc ,应表达为ab&bc,参见后文的内容。,逻辑运算、逻辑表达式及其求值优化,关系表达式 由关系运算符连接的表达式。是一种简单的逻辑表达式。值为true或false。,设有定义 float a=3.2;int b=5;则: 3ab /结果是?,根据右结合 原则其运算 过程如下:,a,5,b,3.2,3,F,即0,F即0,逻辑运算、逻辑表达式及其求值优化,:,逻辑运算、逻辑表达式及其求值优化,逻辑运算符,逻辑表达式 由逻辑运算符连接的表达式,其操作
9、数和运算结果均为逻辑量。操作数可以是表达式,只要其值是逻辑量,如关系表达式。,:,由于逻辑值和整数之间的对应关系,也允许整型和字符型操作数进行逻辑运算: 21&0 /逻辑与,21与0,结果为假:0 21|0 /逻辑或,21或0,结果为真:1 !21 /逻辑非,21的非,结果为假:0 运算结果同样可以作为一个整数参与其他运算。,逻辑运算、逻辑表达式及其求值优化,已知: int a=10, b=20, c=30;float x=1.8, y=2.4;,ay|ay)|(a(b-(!c),t1=1,t2=0,t4=0,-,&,t3=0,t5=b,t6=1,|,得整个表达式的值为:,1,逻辑表达式计算时
10、,逻辑“非”优先级最高,关系运算其次,逻辑“与”和逻辑“或”最低。,逻辑表达式求值的优化:,在求逻辑表达式值的过程中,一旦表达式的值能够确定,就不再逐步进行下面的运算。称为“求值优化”。,已知: int a=10, b=20, c=30; 求: ab | c+ /结果以及a,b,c的值,t1=1,整个表达式的值为 1,可见: 表达式 c+ 已不需要计算所以: c不变仍为 30,编程人员在使用逻辑运算时应当加以小心,优化计算固然提高了运算效率,但可能产生副作用。所谓副作用,就是出乎设计人员的意料,得到预想不到的结果。,2.2.2 if 语句的嵌套,嵌套if语句: if 语句中,如果内嵌语句又是i
11、f语句,就构成了嵌套if语句。if 语句可实现二选一分支,而嵌套if语句则可以实现多选一的多路分支情况。,嵌套在else分支中:if (表达式1) 语句1;else if (表达式2) 语句2;else if else 语句n;,嵌套在if分支中:if () if () ;else;,2.2.2 if 语句的嵌套,配对关系实例: /语句1: if(n%3=0) if(n%5=0) coutn是15的倍数endl; else cout n是3的倍数但不是5的倍数endl; /语句2: if(n%3=0) if(n%5=0) coutn是15的倍数endl; else cout n 不是3的倍数
12、两个语句的差别只在于一个“”,但表达的逻辑关系却完全不同。,else和if的配对关系 ”就近配对“原则,相距最近且还没有配对的一对if和else首先配对,【例2.8】 求一元二次方程ax2+bx+c=0 的根。 其中系数a(a0)、b、c的值由键盘输入。 分析:输入系数a(a0)、b、c后,令delta= b24ac,结果有三种情况: *若delta=0,方程有两个相同实根; *若delta0,方程有两个不同实根; *若delta0,方程无实根。,【例2.8】 求一元二次方程的根。,#include #include using namespace std; int main()float a
13、,b,c;float delta,x1,x2;coutabc;cout“a=“at“b=“bt“c=“cendl;delta=b*b-4*a*c;,求一元二次方程的根源程序,if 语句【例28】,if(delta=0) cout0)delta=sqrt(delta);x1=(-b+delta)/(2*a);x2=(-b-delta)/(2*a);cout“方程有两个不同实根:“;cout“x1=“x1t“x2=“x2endl;else cout“方程无实根!“endl; /delta0 return 0; 请在VC+平台上运行,输入不同的系数,使程序所有分支都可以被执行一次。,if 语句【例2
14、8】,2.2.3 条件运算符“?:”,三元运算符“?:”可以用来简化if语句表达。其构成的表达式格式为: 表达式1 ? 表达式2 : 表达式3,2.2.3 条件运算符“?:”,表达式1 ? 表达式2 : 表达式3,例如:int a=6,b=7; min=ab? a:b; /min=6min=ab? +a:+b; /min=7 a=7 b=7min=ab? a+:b+; /min=6 a=7 b=7,#include using namespace std; int main() char ch;cout ch ;if ( ch = A ,改写为条件表达式 ch = ( ch = A ,把输入字
15、符转换为小写字母。对输入字符进行判断,如果是大写字母,则转换为小写字母;否则,不转换。,条件运算符“?:”,switch ( 表达式 ) case 常量表达式 1 : 语句 1case 常量表达式 2 : 语句 2case 常量表达式 n : 语句 ndefault : 语句 n+1,注: 表达式类型为非浮点型 各常量表达式类型要与之匹配 各常量表达式要求各不相等 default子句可选。缺省时,没有匹配值switch 语句为空,语句标号,2.2.4 switch语句,根据一个整型表达式的值决定程序分支,执行流程,2.2.4 switch语句,例题根据考试成绩的等级打印出百分制分数段。,# i
16、nclude using namespace std; int main () char grade ;cout grade ;switch ( grade ) case a : cout “ 85_100 n “ ;case b : cout “ 70_84 n “ ;case c : cout “ 60_69 n “ ;case d : cout “ 60 n “ ;default : cout “ error n “ ;return 0; ,观察不同输入时的输出结果,switch语句,# include using namespace std; int main () char grad
17、e ;cout grade ;switch ( grade ) case a : cout “ 85_100 n “ ;case b : cout “ 70_84 n “ ;case c : cout “ 60_69 n “ ;case d : cout “ 60 n “ ;default : cout “ error n “ ;return 0; ,2.1.2 switch 语句,例题 根据考试成绩的等级打印出百分制分数段。,switch语句,# include using namespace std; int main () char grade ;cout grade ;switch (
18、 grade ) case a : cout “ 85_100 n “ ;case b : cout “ 70_84 n “ ;case c : cout “ 60_69 n “ ;case d : cout “ 60 n “ ;default : cout “ error n “ ;return 0; ,2.1.2 switch 语句,例题 根据考试成绩的等级打印出百分制分数段。,switch语句,例题 根据考试成绩的等级打印出百分制分数段。,# include using namespace std; int main () char grade ;cout grade ;switch (
19、 grade ) case a : cout “ 85_100 n “ ;case b : cout “ 70_84 n “ ;case c : cout “ 60_69 n “ ;case d : cout “ 60 n “ ;default : cout “ error n “ ;return 0; ,switch语句,# include int main () char grade ;cout grade ;switch ( grade ) case a : cout “ 85_100 n “ ; break;case b : cout “ 70_84 n “ ; break;case
20、c : cout “ 60_69 n “ ;break;case d : cout “ 60 n “ ; break;default : cout “ error n “ ;return 0; ,跳出switch语句,switch语句,例题 根据考试成绩的等级打印出百分制分数段。,例题 根据考试成绩的等级打印出百分制分数段。,# include int main () char grade ;cout grade ;switch ( grade ) case a : cout “ 85_100 n “ ; break;case b : cout “ 70_84 n “ ; break;case
21、 c : cout “ 60_69 n “ ;break;case d : cout “ 60 n “ ; break;default : cout “ error n “ ;return 0; ,switch语句,讨论: 1)csae 和 default 仅起语句标号作用,不能控制程序流程 2)一旦选中一个case分支后,将继续往下顺序执行语句序列 3)添加 break 语句可以跳出 switch 语句体,达到控制流程作用,根据以上特点,可以写出多个 case 共执行一个语句的形式,2.1.2 switch 语句,2.2.4 switch语句,例 根据考试成绩的等级打印出百分制分数,允许输入
22、大写或小写字母。,# include int main () char grade ;cout grade ;switch ( grade ) case a :case A : cout “ 85_100 n “ ; break ;case b :case B : cout “ 70_84 n “ ; break ;case c :case C : cout “ 60_69 n “ ; break ;case d :case D : cout “ 60 n “ ;break ;default : cout “ error n “ ;retrun 0; ,a 或 A 共同执行一个语句,switc
23、h语句,if 语句 switch 语句 形成分支控制流程 不形成程序控制流程 用于复杂条件判断 表达式的值为数值集合时作多分支控制,可读性较好,与 if 语句比较:,2.2.4 switch语句,【例2.10】 设计一个计算器程序,实现加、减、乘、除运算。 分析:读入两个操作数和运算符,根据运算符完成相应运算。#include using namespace std; int main( ) float num1,num2; char op; coutnum1opnum2;switch(op)case +: coutnum1opnum2“=“num1+num2endl; break;case
24、-: coutnum1opnum2“=“num1-num2endl; break;case *: coutnum1opnum2“=“num1*num2endl; break;case /: coutnum1opnum2“=“num1/num2endl; break;default : coutop“是无效运算符!“; return 0;,2.3 循环结构程序设计,2.3.1 while语句 2.3.2 do-while 语句 2.3.3 for语句 2.3.4 循环的嵌套,注意: 1)循环开始前对循环条件进行初始化; 2)在循环体语句中要包含修改循环条件的语句,否则循环将不能终止而陷入死循环。
25、,2.3.1 while语句,while语句也称为当循环,语句格式为: while (表达式)循环体语句;,# include using namespace std; int main () int i = 1 , sum = 0 ;while ( i = 100 ) sum = sum + i ;i + ;cout “ sum = “ sum endl ;return 0; ,想一想: 循环条件是什么? 循环结束条件是什么? 哪一个语句修改循环条件?,一个简单的循环跟踪: 求,while语句,2.3.1 while 语句,while (i=n) sum+=i+; while (sum+=i
26、+, i=n) ;/循环体为空语句 这两种表达方式与例2.11中的循环语句从执行结果看是完全等价的。需要说明的是,虽然C+可以让代码最大限度优化,但往往造成可读性降低,因此程序设计者只需理解这种表达方法的意义,而设计时主要追求的目标应是可读性。,2.3.2 do-while 语句,do-while语句称为直到循环,格式为: do 循环体语句 while(表达式);,2.3.2 do-while 语句,do/while语句和while语句的区别: do/while语句至少执行一次循环体后再判断循环条件是否满足; while语句先判断条件是否满足,然后才执行循环体。可能一次也不执行。 多数情况下可
27、以互相替代。,【例2.12】 用迭代法求a的平方根近似值。求平方根的迭代公式为:要求前后两个迭代根之差小于10- 5。,do-while 语句,迭代法求解:a是已知正数,x 0是迭代初值,给x 0一个值,假定 x 0 = a/2;则用迭代公式依次计算: x1=(x0+a/x0)/2;x2=(x1+a/x1)/2; xk+1=(xk+a/xk)/2; 当|xk+1 xk|(是一个较小的正数)时,迭代终止,取xk+1的值为a的平方根近似值。,1、输入a(a0)及较小正数delta(也可用常变量); 2、x 0 = a/2; 用迭代公式算 x1=(x0+a/x0)/2; 3、while(|x1 x0
28、|=delta) x 0 = x 1 ;/把最近的值给x 0 x1=(x0+a/x0)/2; /求xk+1时只需要知道xk的值,所以只需2个变量 4、取x1的值为a的平方根近似值,输出。,和迭代法对应的程序算法是递推算法:,do-while 语句,int main( )float x0,x1,a;couta;if(a=1e-5);cout a“的平方根为:“x1endl;return 0; ,do-while 语句,2.3.3 for 语句,for循环语句的格式 for ( 表达式1;表达式2; 表达式3 ) 循环体语句,关键字,初始表达式,循环控制 逻辑表达式,循环后置表达式,例如,用 fo
29、r 语句的求和式 的程序,# include using namespace std; int main () int i , sum = 0 ;for ( i =1 ; i = 100 ; i + )sum + = i ;cout “ sum = “ sum endl ; return 0; ,# include using namespace std; int main () int i = 1 , sum = 0 ;while ( i = 100 ) sum = sum + i ;i + ;cout “ sum = “ sum endl ;return 0; ,for循环语句,for语句
30、、while语句、do/while语句比较:,int i=1,sum=0;/循环初始条件 while(i=4)sum+=i;i+; /修改循环条件,int i=1,sum=0; /循环初始条件 dosum+=i;i+;/修改循环条件 while(i=4);,int i,sum=0; for( i=1; i=4; i+ )sum+=i; /*习惯上:表达式1:循环初始条件;表达式2:循环终止条件;表达式3:修改循环条件*/,(1) for语句属于先判断型,与while语句完全等同。 (2) for语句中的三个表达式都是包含逗号表达式在内的任意表达式。如【例2.11】中的循环部分用for语句可描述
31、为:for (i=1, sum=0; i=100; i+) sum+=i; (3) for语句中的三个表达式可部分或全部省略,但两个分号不能省略。如上述语句还可写为:i=1; sum=0;for ( ;i=100; ) sum+=i; i+; 实际上,表达式2也可省略,形如for (; ;) 这种情况下,约定表达式2的值为1,即等同for (; 1;) 死循环,用break跳出。,For循环语句,for语句的几点说明:,【例2.14】运行结果: 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181,【例2.14】 设计程
32、序输出Fibonacii数列的前20项,要求每行输出5个数据。,2.3.3 for 语句,Fibonacii数列定义如下:,算法分析:除了第0项和第1项外,每一项都是由类似方法产生,即前两项之和;所以求当前项时,只需要记住前两项;程序不需要为每一项设置专用变量; 属递推算法。,For循环语句,算法: 1、设置变量n表示第几项,变量 f 1和 f 2用来记住当前项f 3之前的两项 ;变量初始化n=0; 2、第0项 f 1=0; 第1项 f 2=1; 输出第0项和第1项; while (当前项不到第20项) 当前项等于前两项之和:f 3=f 1+f 2; 按要求输出当前项 f 3 ;修改最前两项:
33、 f 1=f 2; f 2=f 3; ,For循环语句,程序如下: /文件名:Ex2_14.cpp int main() int fib0=0,fib1=1,fib2,n;coutsetw(5)fib0setw(5)fib1endl;for(n=3;n=20;n+)fib2=fib0+fib1;coutsetw(5)fib2;if(n%5=0) coutendl; /控制每行5个数据fib0=fib1; fib1=fib2; return 0; ,For循环语句,【例2.15】 输入一个不超过9位的整数,将其反向后输出。例如输入247,变成742输出。 算法分析: 1、将整数的各个数位逐个分开
34、,用一个数组保存各位的值,然后反向组成新的整数。 2、将整数各位数字分开的方法是,通过求余得到个位数,然后将整数缩小十倍,再求余,并重复上述过程,分别得到十位、百位,直到整数的值变成0为止。,2.3.3 for 语句,数据处理: 1、设置变量num表示输入的整数,整型数组digit9用来存放num 的各个位;变量i用来表示数组的当前下标; 算法: 1、输入num; 变量初始化:i=0; 2、while (num!=0) num对10取余,得num的当前个位数放入digiti;num整除10,即去掉个位数,十位变个位,百位变十位,;i+; /数组digit准备记录下一位; 3、将数组元素按下标从
35、低到高的顺序反向组合;,For循环语句,程序如下: int main()int i,num,subscript;int digit9;coutnum;cout0);for(i=0;isubscript;i+) /整数的反向组合num=num*10+digiti;cout“反向后整数为:“numendl;return 0;,For循环语句,2.3.4 循环的嵌套,嵌套循环: 当循环语句中的循环体中又有循环语句时,就构成了嵌套循环。 嵌套层次一般不超过3层,以保证可读性。,【例2.16】 打印九九表。打印格式为: * 1 2 3 4 5 6 7 8 91 1 2 2 4 3 3 6 9 9 9 1
36、8 27 36 45 54 63 72 81,2.3.4 循环的嵌套,算法: 1、输出表头,用一个循环语句即可; 2、输出表体: for (i=1; i10; i+) couti; /输出行号输出第i行数据; /Acoutendl; /准备输出下一行 3、A行细化:for (j=1; j=i; j+) coutsetw(4)i*j;,2.3.4 循环的嵌套,int main()int i,j;coutsetw(3)*setw(4) ;for(i=1;i10;i+)coutsetw(4)i; /输出表头(乘数)coutendlendl;for(i=1;i10;i+)coutsetw(3)iset
37、w(4) ; /输出行号(被乘数)for(j=1;j=i;j+)coutsetw(4)i*j; /输出表中数据(乘积)coutendl; /准备输出下一行return 0; ,循环嵌套【例2.16】 _打印九九表,循环嵌套,2.4 转向语句,break & continue goto return,break & continue,break语句 无条件地结束switch语句,或循环语句,转向执行语句块的后续语句 continue语句 用于循环体中,终止当前一次循环,while ( E1 ) 语句 1if ( E2 ) break ;语句 2 ,while ( E1 ) 语句 1if ( E2
38、 ) continue ;语句 2 ,break,continue,break 与 continue 语句比较,break & continue,for (I=1;I=100;I+) if ( I%3!=0) continue;/I不是3的倍数,不输出,继续下一个I;输出I的值;/I是3的倍数才输出,例:输出1100内3的倍数。 分析:设置整型变量I从1变化到100,依次测试I是否3的倍数,算法属于穷举法。,break & continue,【例2.18】 给定正整数m,判定其是否为素数。 分析:如果m2,m是素数的条件是不能被2,3,,(m的平方根取整)整除。因此可以用2,3,k(k为m的平
39、方根取整)逐个去除m,如果被其中某个数整除了,则m不是素数,否则是素数。 算法属于穷举法。,int main()int m,i,k;coutm;if(m=2) coutk) cout m“是素数“endl; /循环提前终止表示是非素数else cout m“不是素数“endl;return 0;,break & continue,goto语句,goto语句和标号语句一起使用,所谓标号语句是用标识符标识的语句,它控制程序从goto语句所在的地方转移到标号语句处。 goto语句会导致程序结构混乱,可读性降低,而且它所完成的功能完全可以用算法的三种基本结构实现,因此一般不提倡使用goto语句。 但在
40、某些特定场合下goto语句可能会显出价值,比如在多层循环嵌套中,要从深层地方跳出所有循环,如果用break语句,不仅要使用多次,而且可读性较差,这时goto语句可以发挥作用。,return语句,return语句用于结束函数的执行,返回调用者,如果是主函数,则返回至操作系统。 利用一个return语句可以将一个数据返回给调用者。通常,当函数的返回类型为void时, return语句可以省略,如果使用也仅作为函数或程序结束的标志。,2.6 常用算法的应用实例,筛选法,枚举法,穷举法 各种尝试,【例2.20】中国古代数学史上著名的“百鸡问题”,【例2.21】用欧基里德算法(也称辗转法) 求两个整数的
41、最大公约数,【例2.23】输入一个8位二进制数,将其转换为十进制数输出。,【例2.19】 用筛选法求100之内的所有素数,【例2.22】输入一个小于1的数x,求sinx的近似值,1、判断一个数是否素数? 2、100之内的所有素数?方法:一个个试; 综上所述,得到一个循环嵌套的算法:for(m=2;m=100;m+)/穷举法if(m是素数)按要求的格式输出m;,k= sqrt(m); for(i=2;ik) m是素数; /刚才的for不是由break结束的,直接法,【例2.19】 求100之内的所有素数,并将这些素数输出,每行输出 2个数据。,【例2.19】 求100之内的所有素数,并将这些素数
42、输出,每行输出 2个数据。,一个数如果是其他数的倍数,则这个数肯定不是素数; 在由 多个大于1的数 组成的集合中,剔除所有的非素数,剩下的就都是素数了;,筛选法,算法二(及所需的相应数据): 1、将100之内的整数映射到一个集合。可以采用一个数组a来表示,数组元素值为各个整数; 2、在数组a中,从素数2开始剔除掉新找到的素数的整数倍的元素值(置0,非素数); 3、输出数组a中数组元素值非0的元素,他们都是素数。,第 2步 的细化:,筛选法,for (i=0; i=99; i+) /数组下标099,元素值1100 2.1、 if (ai=0) continue; / ai已被定为非素数,并已被筛
43、掉2.2、将数组中所有是ai倍数的元素置0;for( j=i+1;j=99;j+) if(aj%ai=0) aj=0;,算法二: 2、在数组a中,从素数2开始剔除掉新找到的素数的整数倍的元素值(置0,非素数);,#include #include #include using namespace std; const int n=100; int main() int an; int i,j; for(i=0;in;i+) ai=1+i; /用数组保存整数1-100 a0=0; /1不是素数,置0 for(i=1;in;i+)if(ai=0) continue; /该数已经置0,判断下一个fo
44、r(j=i+1;jn;j+) if(aj%ai=0) aj=0;/是ai倍数的元素置0; ,【例2.19】 求100之内的所有素数,并将这些素数输出,每行输出 2个数据。,筛选法,int count=0; cout“1“ n“之间的素数:“endl; for(i=0;in;i+) /输出所有素数if(ai!=0)coutsetw(6)ai;count+;if(count%10=0) coutendl;/每行10个coutendl; return 0; 运行结果:1100之间的素数: 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71
45、73 79 83 89 97,筛选法,枚举法,枚举法也称穷举法,基本思想是,在有限范围内列举所有可能的结果,找出其中符合要求的解。 枚举法适合求解的问题是:可能的答案是有限个且答案是可知的,但又难以用解析法描述。这种算法通常用循环结构来完成。,设鸡翁、母、雏分别为i,j,k,根据题意可得: i*5+j*3+k/3=100;i+j+k=100; 两个方程无法解出三个变量,只能将各种可能的取值代入,其中能满足两个方程的就是所需的解,因此这是枚举算法(也叫穷举法)的应用。i、j、k可能的取值有哪些?分析可知,百钱最多可买鸡翁20,鸡母33,鸡雏300。,【例2.20】 中国古代数学史上著名的“百鸡问
46、题”:鸡翁一,值钱五,鸡母一,值钱三,鸡雏三,值钱一。百钱买百鸡,问鸡翁、母、雏各几何?,枚举法,这个算法使用三重循环,执行时间函数是立方阶,循环体将执行20*33*300=198000次。 我们希望在算法上改进一下,如能减少一重循环,将大大缩短运行时间。,for (i=0; i=20;i+)for (j=0; j=33;j+)for (k=0; k=300;k+)if (i+j+k=100),枚举法,算法:,枚举法,实际上,当i、j确定时,k就可由题目要求确定为100-i-j,因此实际上只要用i、j去测试,用钱数检测就可以了。循环体将执行:20*33=660次。 算法改进为:for (i=0
47、; i+=20;)for (j=0; j+=33;)if ( 5*i+3*j+(100-i-j)/3=100 )coutijk;,#include #include using namespace std; int main() int i,j,k; cout“ 公鸡 母鸡 小鸡“endl; for(i=0;i=20;i+)for(j=0;j=33;j+)k=100-i-j;if(5*i+3*j+k/3=100),枚举法,【例2.20】 鸡翁一,值钱五,鸡母一,值钱三,鸡雏三,值钱一。百钱买百鸡,问鸡翁、母、雏各几何?,递推法,递推算法是通过问题的一个或多个已知解,用同样的方法逐个推算出其他解,如数列问题,近似计算问题等,通常也要借助于循环结构完成。,假定两个整数分别为num1和num2,最大公约数应当是不超过其中较小数的一个整数。 辗转法:用num1除以num2,求出余数resd,如果resd=0,则当前num2就是最大公约数,如果resd!=0,令num1=num2, num2=resd, 重复以上过程,直到resd=0为止。,