目录
前言
1.循环的嵌套
2.循环和判断相互嵌套
3.易错点
4.思维导图
我们已经知道如何通过循环结构来遍历一个一维数组,访问里面的每一个元素。
我们用循环里面的计数器,来作为数组的下标,就可以简单的遍历数组里面的每一个元素。
那我们怎么遍历一个二维数组呢?可以通过循环的嵌套来实现。
1.1
我们可以用两个for循环嵌套,外层的for循环的计数器是二维数组的第一个下标,内测的for循环的计数器是二维数组的第二个下标。
这里就有两层for循环,来遍历访问一个二维数组:
int doouble_list[3][3]={{1,2,3},{4,5,6},{7,8,9}};
for(int i=0;i<3;i++){
for(int j=0;j<3;j++) {
printf("%d\n",double_list[i][j]) ;
}
}
1.定义一个二维数组 int double_list[3][3] ={{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
2.外层的for循环,里面的i会作为二维数组的第一个下标 for(int i=0;i<3;i++){
3.内层的for循环,里面的j会作为二维数组的第二个下标 for(int j=0;j<3;j++){
int doouble_list[3][3]={{1,2,3},{4,5,6},{7,8,9}};
for(int i=0;i<3;i++){
for(int j=0;j<3;j++) {
printf("%d\n",double_list[i][j]) ;
}
}
4.打印单个二维数组的元素 printf("%d\n",double_list[i][j]);
5.二维数组的第一个下标 [i]
6.二维数组的第二个下标 [j]
1.2
外层for循环一共会执行三次,分别是i = 0
,i = 1
,i = 2
的时候。
当i = 3
的时候,循环条件不符合,就不会执行了。
内层的for循环会执行9次,当i=0
的时候,会执行j=0
,j=1
,j=2
这3次;
i=1
和i=2
的时候也会分别执行3次;
一共9次。
1.3
循环嵌套的代码执行顺序也是一层一层深入,外层循环判断以后,会完整执行内层循环的判断和代码块;
然后再回到外层循环进行判断,以及继续进入内层循环来执行。
1.4
eg:
int double_list[2][2]={{1,2},{3,4}};
for(int i=0;i<2;i++){
for(int j=0;j<2;j++){
printf("%d\n",double_list[i][j])
}
}
1.首先定义二维数组 int double_list[2][2] ={{1, 2}, {3, 4}};
2.执行外层循环的判断,判断条件为真,进入循环内部 for(int i=0;i<2;i++){
3.进入内层循环,判断条件为真,进入printf()代码 for(int j=0;j<2;j++){
4.执行printf()代码 printf("%d\n",double_list[ i ][ j ]);
int double_list[2][2]={{1,2},{3,4}};
for(int i=0;i<2;i++){
for(int j=0;j<2;j++){
printf("%d\n",double_list[i][j])
}
}
5.再进行内层循环的判断,判断为真,继续printf()代码 for(int j=0;j<2;j++){
6.继续printf() printf("%d\n",double_list[ i ][ j ]);
7.再一次进行内层循环的判断,判断条件为假,退回到外层循环 for(int j=0;j<2;j++){
8. i = 1外层循环条件判断为真,继续进入内层循环 for(int i=0;i<2;i++){
int double_list[2][2]={{1,2},{3,4}};
for(int i=0;i<2;i++){
for(int j=0;j<2;j++){
printf("%d\n",double_list[i][j])
}
}
9. j 重新等于0,内层循环重新开始,执行printf() for(int j=0;j<2;j++){
10.执行printf()代码 printf("%d\n",double_list[ i ][ j ]);
11.再一次内层循环的判断 for(int j=0;j<2;j++){
int double_list[2][2]={{1,2},{3,4}};
for(int i=0;i<2;i++){
for(int j=0;j<2;j++){
printf("%d\n",double_list[i][j])
}
}
12.判断条件为真,执行printf()代码 printf("%d\n",double_list[ i ][ j ]);
13.此时j=2,内层判断不成立,退回到外层 for(int j=0;j<2;j++){
14.外层循环判断条件也不成立,循环执行结束 for(int i=0;i<2;i++){
1.5
由于外层循环判断以后,会执行数次内层循环,所以我们又习惯于把外层循环叫做大循环,内层循环叫做小循环。
一个大循环对应多个小循环,而且每次小循环都是从头开始。
我们可以看到,小循环都会重新定义 j,所以每次大循环进入小循环以后,都会从新定义j,也就是从0开始:
int double_list[2][2]={{1,2},{3,4}};
for(int i=0;i<2;i++){
for(int j=0;j<2;j++){
printf("%d\n",double_list[i][j]);
}
}
1.6
while循环也是类似的执行顺序——外层循环到内层循环,只不过在代码的写法上面略有不同。
int double_list[2][4]={{1,2,3,4},{5,6,7,8}};
int i=0;
int j=0;
while(i<2){
j=0;
while(j<4){
printf("%d\n",int double_list[i][j]);
j++;
}
i++;
}
1.定义二维数组double_list和计数器i和j
int double_list[2][4] ={{1, 2, 3, 4}, {5, 6, 7, 8}};
int i = 0;
int j = 0;
2外层循环
while(i<2){
j = 0;
j++;
}
3.内层循环
while(j<4){
printf("%d\n",double_list[i][j]);
j++;
}
4.while循环需要自己实现计数器的清零,和迭代自增
5.打印数组元素
printf("%d\n",double_list[ i ][ j] );
1.7
while循环的嵌套和for循环的嵌套之间的细微差别主要在于,for循环可以在循环框架内实现的变量定义和自增,while循环需要自己实现。
这也是用while循环很容易出错的地方,尤其需要注意。
这里的循环嵌套只有两层,只要你愿意,你可以嵌套无数层循环,但我们不建议嵌套太多。
一来这样会把代码的执行顺序搞得很复杂,二来很容易让循环的次数指数级别的上升,最后导致程序运行时间很长。
除了判断嵌套判断,和循环嵌套循环以外,
我们还可以灵活的让判断和循环相互嵌套,以实现一些复杂的代码逻辑。
2.1
比如我们要输出一个长度为10的数组里面的所有大于0的正数:
int number_list[10] = {4, 5, -1, -5, 0, 2, 10, 8, -2, 9};
for(int i = 0;i < 10; i++){
if(number_list[i] > 0){
printf("%d\n", number_list[i]);
}
}
1.定义一个一维数组 number_list int number_list[10] = {4, 5, -1, -5, 0, 2, 10, 8, -2, 9};
2.在外层我们循环遍历整个数组 for(int i = 0;i < 10; i++){
3.在内层我们对数组的元素进行判断是否大于0 if(number_list[i] > 0){ }
4.大于零的值我们就进行打印输出 printf("%d\n", number_list[i]);
仍然是外层循环先遍历所有的数组元素,然后每个值我们都进行了一次判断,大于0的就进行输出。
2.2
我们看看代码的执行顺序:
int number_list[4]={4,5,-1,-5};
for(int i=0;i<4;i++){
if(number_list[i]>0){
printf("%d\n",number_list[i]);
}
}
1.定义一个数组
number_list int number_list[4] = {4, 5, -1, -5};
2.执行外层的循环
for(int i = 0;i < 4; i++){
3.判断number_list[0]是4,大于0,进行输出
if(number_list[ i ] > 0){
printf ("%d\n", number_list[ i ]);
}
4.执行外层的循环
for(int i = 0;i < 4; i++){
5.判断number_list[1]是5,大于0,进行输出
if(number_list[i] > 0){
printf("%d\n", number_list[i]);
}
int number_list[4]={4,5,-1,-5};
for(int i=0;i<4;i++){
if(number_list[i]>0){
printf("%d\n",number_list[i]);
}
}
6.执行外层的循环
for(int i = 0;i < 4; i++){
7.判断number_list[2]是-1,小于0,不进行输出
if(number_list[i] > 0){
8.执行外层的循环
for(int i = 0;i < 4; i++){
9.判断number_list[3]是-5,小于0,不进行输出
if(number_list[i] > 0){
2.3
我们可以看到代码的执行顺序仍然是从外到内层层递进,然后根据循环结构的执行顺序和判断结构的执行顺序,一步一步的执行。
除了循环嵌套判断,我们同样可以判断来嵌套循环。
bool today_is_sat = true;
if(today_is_sat){
for(int i=0; i<5; i++){
printf("运动一次\n");
}
}else{
for(int i=0;i < 2;i++){
printf("运动一次\n");
}
}
1.定义布尔变量
bool today_is_sat = true;
2.外层的判断
if(today_is_sat){
}else{
}
3.内层的循环,这里会循环执行5次
for(int i=0; i<5; i++){
printf("运动一次\n");
}
4.内层的循环,这里会循环执行2次
for(int i=0;i < 2;i++){
printf("运动一次\n");
}
2.4
同样的,不管怎么嵌套,我们都一层一层按照代码的执行顺序去分析就可以了
理论上,我们可以无限嵌套到无限深,但是同样我们要考虑代码的复杂度和可读性。
所以我们建议最多不要超过两层,这样代码结构会清爽很多。
下面这段代码,会输出什么?
int i = 0, j = 0;
while (i < 3) {
do {
printf("%d, %d\n", i, j);
j++;
} while (j < 2);
i++;
}
在这段代码中,一定要搞清楚do-while是先执行再判断:
第一次输出:
0,0
;第二次输出:
-->
j = 1,小于2,满足条件,继续内层循环,输出0,1
;-->
j = 2,不满足小于2,跳出内层循环;第三次输出:
-->
i = 1,满足外层循环条件i<3,然后进入内层循环,先do,输出1,2
;第四次输出:
-->
i = 2,满足外层循环条件 i<3 ,然后进入内层循环,先do,输出2,3
;-->
j=4,不满足小于2,跳出内层循环;接着 i++ -->
i = 3,不满足外层循环条件,跳出外层循环,整个循环结束。
因此,输出结果为:
0, 0
0, 1
1, 2
2, 3
循环嵌套中,循环的顺序选择是至关重要的。选择正确的循环顺序可以避免逻辑错误和重复计算。
循环嵌套可能导致性能问题,特别是在处理大规模数据集时。要注意避免不必要的重复计算或循环次数过多的情况,可以考虑优化循环结构或使用其他数据结构来提高性能。
嵌套的循环控制变量不能相同;
外层循环可包含两个以上内循环,但不能相互交叉。
在撰写这篇文章时,我参考了《白纸编程》这个app的观点和思想,我要感谢他们对我的启发和帮助。