为啥我们在冒泡排序算法的内循环中使用 `length-i-1`

Posted

技术标签:

【中文标题】为啥我们在冒泡排序算法的内循环中使用 `length-i-1`【英文标题】:Why do we use `length-i-1` in the inner loop of bubble sort algorithm为什么我们在冒泡排序算法的内循环中使用 `length-i-1` 【发布时间】:2018-11-10 21:32:43 【问题描述】:

使用 javascript,它被编程为按 asc 顺序对数组中的元素进行排序。我尽力理解为什么内部循环使用length-i-1,但不能。谁能帮我理解我们为什么要使用它?

function bubbleSort(arr) 

    for(let i=0; i<= arr.length; i++) 
        for(let j=0; j< arr.length-i-1; j++) 
            if(arr[j] > arr[j+1]) 
                let lesser = arr[j+1];
                arr[j+1] = arr[j];
                arr[j] = lesser;
            
        
    

    return arr;

【问题讨论】:

索引大于length-i-1 的所有内容都已排序。 【参考方案1】:

就像丹尼尔在他的评论中所说,这是因为这些项目已经被排序(例如,在第一次迭代中以最高索引结束的最大元素)

看下面的 gif,注意 8 是如何在最右边结束的,然后被黑框包围,表示它不再需要移动,因此不再需要检查 (它大于长度-i-1)。

不检查这些已经“锁定”的元素有助于提高算法速度。

Gif 来自:Bubble Sort on Wikipedia

【讨论】:

使用 gif 比使用文字更容易:D 有时我认为这是学习这类东西的最简单方法! 是的,但也有的时候你需要每个字都流汗才能理解!【参考方案2】:

让我们从步骤的角度来考虑它: 假设您有一个包含 10 个元素的数组,只是为了举例。

第一步

i = 0, j goes from 0 to 9( = 10 - 0 - 1)

所以它遍历整个数组。 现在,每次我们发现当前元素大于下一个元素时,我们都会切换它们(if(arr[j] &gt; arr[j+1])),所以在第一次迭代结束时,在最后一个位置,我们将拥有数组的最大元素。

第二步

i = 1, j goes from 0 to 8( = 10 - 1 - 1)

现在,我们可以注意到我们省略了最后(第 9 个)位置,但我们知道它已经是上一步的最大值,所以它位于正确的位置。在本次迭代结束时,我们将在第 8 个位置获得第二个最大元素,并且该过程继续进行..

【讨论】:

【参考方案3】:

编辑:电话太慢:P

在每次外部迭代之后,第 i 个最大的元素都在正确的位置。所以在第一次迭代之后,最大的元素在最右边。现在我们知道了,我们不必在下一轮比较这个元素。 第二次迭代后,第二大元素位于最右侧 -1 的位置。所以最大的两个Element已经排序好了,下一轮就不用考虑了。

通过一个简单的示例尝试您的算法,然后手动逐步完成。那你应该看清楚了。

【讨论】:

以上是关于为啥我们在冒泡排序算法的内循环中使用 `length-i-1`的主要内容,如果未能解决你的问题,请参考以下文章

冒泡算法

经典算法学习——非循环双向链表实现冒泡排序(不带头结点)

为啥冒泡排序需要嵌套循环?

最容易懂得冒泡排序

常见14种经典排序算法(Java代码实现)

三个基本排序算法的效率比较(冒泡,选择和插入)