循环嵌套思路详解 | 一个“在盒子里过家家”的算法 -- 以冒泡排序与打印菱形为例(一)

简介: 本文介绍了编程中的一种思想,通过菱形打印问题来阐述如何理解和使用循环嵌套。文章提到,初学者在面对循环结构时,可以通过先识别代码块的结束括号来理解整体结构,提高阅读效率。作者提出了“在盒子里过家家”的理解思路,将外层循环看作一个个盒子,内层循环视为盒子里的操作,弱化循环嵌套的概念,强调以盒子为单位思考问题。此外,文章还通过示例解释了内外循环的关系,帮助读者更好地理解循环控制和执行过程。

前言


本文中,我将详细介绍该思想,以菱形打印为引例加以说明,希望能把我的这个经验讲述给大家,对大家学习编程语言有所帮助,对二维数组的理解也相辅相成。


不需要引例的朋友可以直接跳转到讲解部分。

 

以下即为正文内容。


一、引例 -- 菱形打印


1. 题干要求


打印实心菱形,菱形的大小由输入决定。


效果展示


当输入为9(或10,菱形只能是奇数行)时,打印9行菱形;


当输入为5时,打印5行菱形;




这是在循环结构部分的一道经典编程题。它的核心就是恰当地使用循环嵌套。对于入门编程有些时日的朋友,这自然是非常基础。但以我自身经历来说,第一次写这道题,我用了将近一个半小时,打印出了各种奇奇怪怪的歪瓜裂枣……最后甚至开凑(当然,凑是没用的)。


在讲循环嵌套之前,我先介绍一种阅读循环的技巧,在讲解循环时,大家能理解地更加清晰。


2. 如何阅读循环结构?


在网上或各种编程辅导书中,我们能看到各种各样的代码展示与解析:



网上截取的解法展示 1



网上截取的解法展示 2


上面两张图中的菱形解法是从网络上截取的,相信很多人都看过。


这些代码都是正确的,确实可以实现菱形的打印。但我认为,如果是这样的答案——那么它们仅能算是合格的答案,并不能算合格的讲解。这样的解答贴出“第一步xxx”“第二步xxxx”,我们看完这些答案后,能顺着其中的注释从头到尾看一遍,也许能明白每一步是干什么的,知道这代码是可行的,但这对于“举一反三”是远远不够的。


因为我们很难从其中形成对循环结构和“为什么这样就能打印出菱形”原理的系统的认知。就好像高中读文言文,将每一句话的释义抄得很细,也明白它大体讲的是什么,可是却忽略了作者安排行文结构的良苦用心。


我们要理解为什么代码会是这样的——在读循环结构的代码时,我们就应当调整一下习惯。通俗的来说,在读带有 for 、while、switch、函数等带有 { } 的代码块时,第一眼不要按照习惯从上向下读,而最好先找到后括号 } ,确认代码块在哪里结束,粗略地浏览整体结构。


这样做的目的,是为了明确(可以手动用笔划,熟练后也可以之间在心里画)层次。像这样:



一眼看上去就知道这个循环里面干了什么


非常清晰,也能提高阅读代码的效率。


(如果一时还没有找到好的阅读方法,推荐尝试。


在介绍完如何阅读循环结构代码后,接下来咱们就来探讨“在盒子里过家家”到底是怎样一种思路。


By the way, 我们以常规的代码来解析菱形打印这道引例。而在文末也将附上优化版本的代码。优化版本的代码不作过多解析,感兴趣的朋友们可以copy下来试一试,加深理解。


二、“在盒子里过家家”的理解思路


1. 什么叫“在盒子里过家家”?


卖关子到此为止。“在盒子里过家家”自然是比喻的说法。这个思路提供的,是思考的切入点:以盒子为单位进行思考。


假设眼前有两层 for 循环,外层的for循环每循环一次,就创造出一个盒子(就像流水线上的快递箱),盒子内部就是外层for循环的内部。


盒子内部要装很多东西,干它自己的事情,这就是盒子里面的“过家家”。


内层for循环就是盒子里面普通的一员它根据需要摆放着相应的位置。


我们要有意识地弱化“循环嵌套”这个概念,而把使用循环作为和使用输入输出函数一样自然的事情。不必紧张于,某个题目要考所谓的“循环嵌套”而我不会之类的事情。


在循环里面再写一个循环,就和在盒子里面随手放一个东西一样自然。


记住,以盒子为单位进行思考。类似于二维数组,不过我们也并不强调“列”的概念。行是最重要的,因为它恰代表着外层for循环。列的概念却并不在所有循环嵌套中都具象。



有一些同学搞不清外循环和内循环的关系和一些循环次数的问题。其实不要刻意地想要将内外循环联系起来:内循环没什么特别的关系,它只不过是外循环里面的一个代码块,相当于盒子里面一个普通的元素。


当外层for循环写好后,往里面填代码,就相当于是向盒子里面塞东西。进入盒子之后,视野变小,就不要想着盒子了(进入外层for循环之后,没必要再纠结外层for循环了,就当它没有,按从上到下的顺序阅读/填写内部的代码即可)


可以尝试一下理解“视野变小”。


这样还是很抽象,我们直接用代码来理解:


for(int i = 0; i < 5; i++){
 
    cout << "hello!box!" << " ";
 
    for(int j = 0; j < 3; j++){
        cout << "good" << " ";
    }
 
    cout << "end" << endl;
 
}


盒子就相当于每一行代码。


盒子 ---- 行


每个盒子里面有什么内容 ---- 每行要做什么事


每行要做什么事啊?每行会先打印一个"hello!box!  ",再打印一个3个"good  ",再打印一个''end"


这个盒子结束了 ---- 这行结束了(该换下一行了)


下一行要做什么事啊?会先打印一个"hello!box!  ",再打印一个3个"good  ",再打印一个''end"


……


一共有5个盒子 ---- 一共有5行


每个盒子都一样 ---- 每一行的内容都一样


一个小例子 -- 到底打印多少个"*"?


看一看下面的代码:


int i = 0;
int j = 0;
 
//1-这里打印多少个*?
for(i=0;i<10;i++){
    for(j=0;j<10;j++){
       cout << "*"; 
    }
}
 
//---------------------------------------------------
 
int i = 0;
int j = 0;
 
//这里打印多少个*?
for(  ;i<10;i++){
    for(  ;j<10;j++){
       cout << "*"; 
    }
}


第一题打印100个"*",因为每个盒子里面都打印10个"*",而一共有10个盒子(或者直接理解为二维数组,轻轻松松)。


第二题打印10个"*" ,因为虽然一共还是有10个盒子,但只有第一个盒子里面,打印了10个"*",第一个盒子之后,j 的值始终是10,剩下盒子里面的小for循环就都进不去啦!



循环嵌套思路详解 | 一个“在盒子里过家家”的算法 -- 以冒泡排序与打印菱形为例(二)

+https://developer.aliyun.com/article/1518301?spm=a2c6h.13148508.setting.15.16ee4f0ewLnn61

相关文章
|
1月前
|
搜索推荐 Java
经典排序算法---冒泡排序
这篇文章详细介绍了冒泡排序算法的基本思想、比较轮数和次数,并提供了Java语言实现冒泡排序的代码示例,展示了如何通过相邻元素的比较和交换来达到排序的目的。
经典排序算法---冒泡排序
|
2月前
|
算法 PHP
【php经典算法】冒泡排序,冒泡排序原理,冒泡排序执行逻辑,执行过程,执行结果 代码
【php经典算法】冒泡排序,冒泡排序原理,冒泡排序执行逻辑,执行过程,执行结果 代码
24 1
|
3月前
|
机器学习/深度学习 算法 搜索推荐
数据结构算法--2 冒泡排序,选择排序,插入排序
**基础排序算法包括冒泡排序、选择排序和插入排序。冒泡排序通过相邻元素比较交换,逐步将最大值“冒”到末尾,平均时间复杂度为O(n^2)。选择排序每次找到剩余部分的最小值与未排序部分的第一个元素交换,同样具有O(n^2)的时间复杂度。插入排序则类似玩牌,将新元素插入到已排序部分的正确位置,也是O(n^2)复杂度。这些算法适用于小规模或部分有序的数据。**
|
3月前
|
算法 搜索推荐
数据结构与算法-冒泡排序
数据结构与算法-冒泡排序
24 2
|
3月前
|
搜索推荐 算法 大数据
​【数据结构与算法】冒泡排序:简单易懂的排序算法解析
​【数据结构与算法】冒泡排序:简单易懂的排序算法解析
|
3月前
|
机器学习/深度学习 搜索推荐 算法
【C/排序算法】:快速排序和冒泡排序
【C/排序算法】:快速排序和冒泡排序
29 0
|
3月前
|
搜索推荐 算法
排序算法之冒泡排序
排序算法之冒泡排序
24 0
|
3月前
|
搜索推荐
排序算法---冒泡排序----详解&&代码
排序算法---冒泡排序----详解&&代码
|
3月前
|
算法 搜索推荐 Java
JavaSE——算法(1/2):认识、冒泡排序、选择排序及优化(介绍、详细图解、代码)
JavaSE——算法(1/2):认识、冒泡排序、选择排序及优化(介绍、详细图解、代码)
28 0
|
3月前
|
人工智能 算法 C语言
数据结构与算法——简单排序-冒泡排序、插入排序,时间复杂度下界(图示、代码、时间复杂度、定理)
数据结构与算法——简单排序-冒泡排序、插入排序,时间复杂度下界(图示、代码、时间复杂度、定理)
31 0