循环多层嵌套
多层循环:多层循环就是在一个循环里还存在一个循环,甚至在内层循环里存在循环,三层,四层······对于嵌套的循环执行步骤,每执行一次外层循环时执行完一次内层循环,若内层循环内还有嵌套循环,则执行步骤依次类推。对于循环的嵌套执行逻辑与单个循环相比更绕,但多层循环可以做到一些更加复杂的操作。下面通过一些例题来体现多层循环可以实现的复杂操作。
1. 输入一个大小为10的整数型数组,数组中一个或连续多个整数组成一个数组。求所有的和的最大值。
例子:
输入一个数组:1 5 6 2 3 4 9 2 1
子数组的最大值:18
代码:
#include<stdio.h>
int main()
{
int num[10];
printf("请输入10个数:");
for (int i = 0; i < 10; i++) //输入10个数
scanf_s("%d", &num[i]);
int max = 0, temp = 0; //max表示子数组和最大值,temp表示子数组的和
max = num[0];
for (int i = 0; i < 10; i++) //暂时假设数组最大值为子数组和最大值
if (num[i] > max)
max = num[i];
for (int i = 0; i < 9; i++)
{
temp = 0;
if (num[i] > num[i + 1]) //降序子数组开始
{
temp += num[i];
for (int j = i + 1; j != 10 && num[j] <= num[j - 1]; j++) //开始升序及到达最后一个数则循环结束
temp += num[j];
}
else if(num[i]<num[i+1]) //升序子数组开始
{
temp += num[i];
for (int j = i + 1; j != 10 && num[j] >= num[j - 1]; j++) //开始降序及到达最后一个数循环结束
temp += num[j];
}
if (temp > max) //当前子数组和大于最大值保留
max = temp;
}
printf("子数组的最大值为:%d\n", max);
return 0;
}
运行结果:
思路:首先······你得理解题目意思,子数组指的时连续的几个整数或一个整数,连续几个整数一定要是连续递增或连续递减。知道了子数组的定义,就要想如何找到子数组,如果找到了所有子数组我就可以计算所有的子数组和,将他们进行比较就可以找到所有子数组和的最大值。那问题有来了,如何找到子数组,子数组的性质时要么一直递增要么一直递减,那我们就可以以数组开始递增为子数组开始,以递增后开始递减为结束;或以数组开始递减为子数组开始,以递减后开始递增为结束。但注意的是有可能没有递增或递减的子数组,那单个最大的整数就是所有子数组和的最大值。当然也有可能单个最大整数大于递增或递减的子数组,这就要进行比较了。
流程步骤:
1. 先将单个整数最大值找到并赋值给max
2. 在循环数组,使数组元素依次循环
3. (1).递增子数组:以当前数组元素num[i]小于后一个数组元素num[i+1]作为子数组开始,外循环在内嵌一个内循环,内循环从i+1开始,检查是否递增,直到开始递减或循环到最后一个数结束
(2)递减子数组:以当前数组元素num[i]大于后一个数组元素num[i+1]作为子数组开始,内循环从i+1开始,检查是否递减,直到开始递增或循环到最后一个数结束
4. 将每次找到的子数组和与当前max值比较
5. 输出max
注意!!!:逻辑与的表达式运算顺序
本题示例代码中判断子数组结束条件:j!=10&&num[j]<=num[j-1]
那如果写成:num[j]<=num[j-1]&&j!=10,结果以一样吗?当然这两个写法是不一样的。首先要了解逻辑与运算符对表达式运算顺序,逻辑与运算符先计算左值,如左值为真才会计算右值,若左值为假则不会计算右值,整个逻辑表达式直接为假。如果写成num[j]<=num[j-1]&&j!=10且子数组的最后一个是数组的最后一个,此时虽然有j!=10条件来退出循环但是计算机会先计算num[j]<=num[j-1]的值,但此时j=10,数组中没有num[10]这一元素,那如何进行比较,这里就会出错。所以写成j!=10&&num[j]<=num[j-1],先判断j是否为10,为10直接退出循环,不会再计算num[j]<=num[j-1]。
2.输入大小为10的两个数组(没有重复),实现一个求两个数组交集的行数。
代码:
#include<stdio.h>
int main()
{
int num1[10], num2[10];
printf(" 数组1:");
for (int i = 0; i < 10; i++) //输入数组1
scanf_s("%d", &num1[i]);
printf(" 数组2:");
for (int i = 0; i < 10; i++) //输入数组2
scanf_s("%d", &num2[i]);
int count = 0; //count记录交集的个数
for (int i = 0; i < 10;i++) //使每个数组1中的数与数组2检查是否相等
for (int j = 0; j < 10; j++) //使每个数组1第i+1个数与数组2每一个数检查是否相等
if (num1[i] == num2[j])
{
count++; //相等计数器加一
if (count == 1)
printf(" 交集:");
printf("%4d", num1[i]); //输出交集
}
if (!count) //没有交集
printf(" 无交集");
putchar('\n');
return 0;
}
运行结果:
思路:要找到数组1和数组2同时有的元素,想到的是只要我将数组1的每个元素和数组2的每一个元素比较就可以得到相同的元素了。
流程步骤:
1. 输入数组1,数组2
2. 两层循环,外层循环数组1的每个元素,内层循环将单次外循环数组1的一个元素和数组2的每一个元素比较,找到相同元素
3. 输出相同元素
3.输入一个大小为10的数组,对数组进行升序和降序排列并输出。
例子:
大小为10的数组:6 7 1 5 4 3 9 1 10 15
升序排列:1 1 3 4 5 6 7 9 10 15
降序排列:15 10 9 7 6 5 4 3 1 1
示例代码:
#include<stdio.h>
int main()
{
int num[10];
printf("原数组:");
for (int i = 0; i < 10; i++) //输入原数组
scanf_s("%d", &num[i]);
int k,temp; //k,temp表示中间变量
for (int i = 0; i < 9; i++)
{
k = i; //开始使k=i
for (int j = i+1; j < 10; j++)
if (num[j] < num[k])k = j; //找到比num[k]小的数,记录下标给k
temp = num[i]; //将num[i]与num[k]数值交换
num[i] = num[k];
num[k] = temp;
}
printf("升序排列:"); //输出升序
for (int i = 0; i < 10; i++)
printf("%4d", num[i]);
putchar('\n');
printf("降序排列:"); //反序输出则位降序
for (int i = 9; i >= 0; i--)
printf("%4d", num[i]);
putchar('\n');
return 0;
}
运行结果:
思路:对于数组排序这里介绍选择排序法。选择排序法,简单讲就是要找到相应次序的数并将它放在相应的位置上。对于升序排列,两层循环,外循环表示排序后的次序,内循环找到相应次序的数;如数组第一个数排序后应该是最小的数,那外循环从0开始,同时定义一个变量k记录当前检查最小的数下标,开始先认定num[0]最小,内循环从1开始,如果num[1]小于num[0]则将1记录在k中,内循环再检查num[2],如果num[2]小于num[1],则有刷新k的值,依次类推直到内循环检查到num[9],找到最小数,将它和数组num[0]数值交换,现在就排好了一个数,接下来的顺序则类推。
流程步骤:
1. 输入数组
2. 对数组升序排列,找到第i大的数将它放在第i个数组元素中
3. 输出升序数组
4. 反序输出升序数组即为降序数组(降序排列和升序原理相同)。
总结
多层循环可以实现许多操作如下:
1. 对于一个一维数据,在单次当前循环进行时再在里层进行向下循环。主要功能有排,找一维数据中的某一特定的一维数据。
2. 对于两个一维数据,在第一个一维数据循环里进行第二个一维数据循环。主要功能有找两个一维数据的相同数据,对两个一维数据各数据比较。
3. 对于一个二维数据。主要是的是实现行和列的循环。
4. 对于许多单个数据,每个数据各自有有限个可能数值,每层循环为一个数据的不同可能存在的数值取值。主要功能实现求多个数据有多个不同可能而形成的整体不同组合情况的数量以及也可以在所以组合中找到某一特定组合。