JavaScript冒泡排序内层循环为何使用length-i-1?
为啥冒泡排序内层循环要用
length-i-1? 嘿,我来给你把这个点讲透,其实本质就是每一轮冒泡都会把当前最大的元素“送”到它该待的位置,后面就不用再搭理这些已经排好的元素了~
先拆解下逻辑:
- 外层循环的
i,代表我们已经完成了多少轮冒泡。每完成一轮,数组末尾就会多一个已经排好序的最大元素——比如第一轮结束,整个数组最大的元素会被推到最后;第二轮结束,第二大的元素会被推到倒数第二的位置,以此类推。 - 内层循环的作用,是在还没排好序的前面部分,两两比较相邻元素,把大的往后挪。这时候我们完全没必要再去碰后面已经排好的
i个元素。
举个具体的例子,假设数组长度是4:
- 当
i=0(第一轮):还没有任何元素排好,我们需要把最大的元素推到最后一位。这时候内层循环的j要满足j < 4-0-1(也就是j<3),j能取0、1、2——因为j要和j+1比较,j+1最多到3(数组最后一个索引),刚好覆盖整个数组的比较。 - 当
i=1(第二轮):已经有1个元素(最后一位)排好序了,我们只需要处理前面3个元素。这时候j < 4-1-1(也就是j<2),j取0、1——j+1最多到2,刚好是未排序部分的最后一位,不会碰已经排好的最后一个元素。 - 当
i=2(第三轮):已经有2个元素排好,处理前面2个元素,j < 4-2-1(也就是j<1),只需要比较第0和第1位就够了。
如果不用length-i-1,而是每次都让j循环到length-1,会有两个问题:
- 做无用功:反复去比较后面已经排好序的元素,比如第二轮还去比较倒数第二和最后一位,但最后一位已经是最大的了,完全没必要。
- 潜在的多余操作:如果
j到了length-1,j+1就是length,这时候访问arr[j+1]得到的是undefined,虽然你的代码里的if判断不会触发交换,但这种多余的比较完全可以避免。
另外提一嘴,你的外层循环条件i<=arr.length其实可以优化成i<arr.length-1——因为当i到arr.length-1的时候,前面只剩一个元素,已经是有序的了,没必要再循环啦。
内容的提问来源于stack exchange,提问作者Prem
相关产品推荐
相关产品推荐

