完成运算符表达式、流程控制、格式化输入输出后,复合结构程序设计将是第一次利用C/C++去解决实际问题。所谓复合结构程序设计即顺序、分支和循环三大结构相互嵌套配合使用来完成对实际问题的求解,这也是程序员锻炼思维逻辑、掌握计算机解决问题的入口。
循环结构的嵌套
循环里嵌入循环,一般情况下二重、三重循环比较多,再多层的循环嵌套情况比较少见。要注意的是循环嵌套循环次数是乘法计算,而不是加法。比如:两重循环,外循环10次,内循环100次,那么总共执行1000次循环(10行100列),这也是为什么多重循环需要尽量避免的原因。
两重循环经典的题目应该是矩阵输出(上三角、下三角、九九乘法表等)
#include <iostream>
#include <stdio.h>
using namespace std;
int main()
{
int i,j;
for(i=1;i<=9;i++)
{
for(j=1;j<=i;j++)
{
//C语言用printf
//printf("%d*%d=%d ",i,j,i*j);
cout<<i<<"*"<<j<<"="<<i*j<<" ";
}
//printf("\n");
cout<<endl;
}
return 0;
}
注意点:
1、内循环j的终止条件是 j<=i,是因为九九乘法表是上三角,把i看成行,j就是列,第1行j<=1输出1个,第9行 j<=9 输出9个,注意理解这种控制的方法;
2、j 循环后的cout<<endl;是用于换行,第一行输出完毕,换行后再输出第二行等等;
3、每个 i * j 的输出后面带有空格,用来分开后的分割。
循环嵌分支
应该说循环嵌分支的统计类型题是复合结构程序设计的起始点,典型的题目是统计某范围内符合特点的数据的个数或者和,比如统计【1,1000】满足3的倍数或者7的倍数的和:
#include <iostream>
#include <stdio.h>
using namespace std;
int main()
{
int i,sum=0;//统计、累加,要注意清0
for(i=1;i<=1000;i++)
{
if(i%3==0 || i % 7 ==0) sum += i;
}
cout<<sum<<endl;
//printf("%d\n",sum);
return 0;
}
1、统计和累加要注意清0,累乘则是清1;
2、for循环计数循环,一般包含从什么到什么的意义,要掌握好程序的大结构;
3、sum += i;复合赋值运算,用于累加,对计算机而言一般都是简单粗暴:遍历整个范围,满足条件的处理,不满足的忽略(穷举法)
4、i从1 开始还是从 3开始并不重要,在算法上这个称为问题的规模N,一重循环的计算称为算法复杂度N,两重循环(外循环规模N,内循环规模N)复杂度是N*N,想象一下N非常大!那么如果能够把两重循环的问题变成一重循环来解决,效率将得到非常大的提升!
5、复杂度是N的阶乘、N的N次方等等,称为"NP"问题(Non-deterministic Polynomial),解决NP问题是公认的世界级难题。
隐藏条件的循环嵌分支:求水仙花数,水仙花数是这样的三位数:它的百位立方+十位立方+个位立方正好等于它自己。比如:153 = 1 + 125 + 27
#include <iostream>
#include <stdio.h>
using namespace std;
int main()
{
int i,a,b,c;
for(i=100;i<1000;i++)
{
a = i / 100;
b = i /10 % 10;
c = i % 10;
if(a*a*a+b*b*b+c*c*c==i)
cout<<i<<endl;
//printf("%d\n",i);
}
return 0;
}
1、隐含条件“三位数”,从100到999,马上可以确定程序的大结构应该是for计数循环;
2、思路也清晰,针对100到999,每个数判断是否为水仙花数,是则输出;
3、根据水仙花数的定义,每次循环都需要取出i的百位十位个位,联系整除与取余运算即可以解决这个问题;
4、要根据三大结构的特点把对应的功能写在正确的位置,比如取数字的三位操作,要写在循环体内:每个 i 都得取出三位进行判断(不多不少,循环),而输出应该放在循环体的分支下:可能有多个输出(多个肯定是循环,分支和顺序最多一次),不是每个i都是(加上分支条件);
还有方法来解这个问题
#include <iostream>
#include <stdio.h>
using namespace std;
int main()
{
int a,b,c;
for(a=1;a<=9;a++)
{
for(b=0;b<=9;b++)
{
for(c=0;c<=9;c++)
{
if(a*a*a+b*b*b+c*c*c == a*100+b*10+c)
cout<<a*100+b*10+c<<endl;
//printf("%d\n",a*100+b*10+c);
}
}
}
return 0;
}
1、三位数是百位从1到9、 十位从0到9 、 个位从0到9 的数字组合起来的,这样三重循环同样可以遍历所有的三位数,注意百位从1开始;
2、组合成三位数:a*100+b*10+c (乘位权值)
3、解决问题的方法不会只有一种,程序员应该养成尝试多种方法解决问题的习惯;三重循环与一重循环的复杂度一样(900 = 9 * 10 * 10),但是推荐第一种,因为代码行少点!