菜单
×
   ❮   
HTML CSS JAVASCRIPT SQL PYTHON JAVA PHP 如何 W3.CSS C C++ C# BOOTSTRAP REACT MYSQL JQUERY EXCEL XML DJANGO NUMPY PANDAS NODEJS R TYPESCRIPT ANGULAR GIT POSTGRESQL MONGODB ASP AI GO KOTLIN SASS VUE DSA GEN AI SCIPY AWS CYBERSECURITY DATA SCIENCE
     ❯   

DSA 冒泡排序


冒泡排序

冒泡排序是一种将数组从最小值排序到最大值的算法。

速度

{{ msgDone }}

运行模拟以查看冒泡排序算法如何对一组值进行排序。数组中的每个值都由一个列表示。

“冒泡”这个词来源于这种算法的工作方式,它使最高值“冒”到顶部。

工作原理

  1. 逐个检查数组中的值。
  2. 对于每个值,将其与下一个值进行比较。
  3. 如果该值高于下一个值,则交换它们,使最高值排在最后。
  4. 遍历数组的次数等于数组中值的数量。

继续阅读以完全理解冒泡排序算法以及如何自行实现它。


手动演练

在我们用编程语言实现冒泡排序算法之前,让我们先手动遍历一个短数组一次,只是为了了解其思想。

步骤 1:我们从一个未排序的数组开始。

[7, 12, 9, 11, 3]

步骤 2: 我们看前两个值。最小值在前吗?是的,所以我们不需要交换它们。

[7, 12, 9, 11, 3]

步骤 3: 向前一步,看看值 12 和 9。最小值在前吗?不是。

[7, 12, 9, 11, 3]

步骤 4: 所以我们需要交换它们,使 9 排在前面。

[7, 9, 12, 11, 3]

步骤 5: 向前一步,看看 12 和 11。

[7, 9, 12, 11, 3]

步骤 6: 我们必须交换,使 11 在 12 之前。

[7, 9, 11, 12, 3]

步骤 7: 看看 12 和 3,我们需要交换它们吗?是的。

[7, 9, 11, 12, 3]

步骤 8: 交换 12 和 3,使 3 排在前面。

[7, 9, 11, 3, 12]

运行下面的模拟以查看上述 8 个步骤的动画

{{ msgDone }}
[
{{ x.dieNmbr }}
]

手动运行:发生了什么?

我们必须理解第一次遍历中发生的事情,才能完全理解该算法,从而可以用编程语言实现它。

您能看出最高值 12 发生了什么吗?它已经冒到数组的末尾,也就是它所属的位置。但数组的其余部分仍未排序。

因此,冒泡排序算法必须一次又一次地遍历数组,每次下一个最高值都会冒到其正确位置。排序一直持续到最小值 3 留在数组的开头。这意味着我们需要遍历数组 4 次,才能对 5 个值的数组进行排序。

每次算法遍历数组时,数组中剩余的未排序部分都会变短。

这就是一次完整的手动遍历的样子

{{ msgDone }}
[
{{ x.dieNmbr }}
]

我们现在将利用所学知识,用编程语言实现冒泡排序算法。


冒泡排序实现

要在编程语言中实现冒泡排序算法,我们需要

  1. 一个包含待排序值的数组。
  2. 一个内部循环,它遍历数组并在第一个值高于下一个值时交换值。此循环每次运行时必须少遍历一个值。
  3. 一个外部循环,它控制内部循环必须运行的次数。对于一个包含 n 个值的数组,此外部循环必须运行 n-1 次。

生成的代码如下:

示例

my_array = [64, 34, 25, 12, 22, 11, 90, 5]

n = len(my_array)
for i in range(n-1):
    for j in range(n-i-1):
        if my_array[j] > my_array[j+1]:
            my_array[j], my_array[j+1] = my_array[j+1], my_array[j]

print("Sorted array:", my_array)
运行示例 »

冒泡排序改进

冒泡排序算法可以再改进一点。

想象一下数组几乎已经排序,最低的数字在开头,例如这样:

my_array = [7, 3, 9, 12, 11]

在这种情况下,数组在第一次运行后就会被排序,但冒泡排序算法会继续运行,而不会交换元素,这是不必要的。

如果算法一次遍历数组而没有交换任何值,那么数组必须已完成排序,我们可以停止算法,像这样:

示例

my_array = [7, 3, 9, 12, 11]

n = len(my_array)
for i in range(n-1):
    swapped = False
    for j in range(n-i-1):
        if my_array[j] > my_array[j+1]:
            my_array[j], my_array[j+1] = my_array[j+1], my_array[j]
            swapped = True
    if not swapped:
        break

print("Sorted array:", my_array)
运行示例 »

冒泡排序时间复杂度

有关时间复杂度的一般性解释,请访问此页面

有关冒泡排序时间复杂度的更深入和详细解释,请访问 此页面

冒泡排序算法遍历数组中的每个值,将其与相邻值进行比较。因此,对于一个包含 \(n\) 个值的数组,在一个循环中必须有 \(n\) 次这样的比较。

在一个循环之后,数组会再次循环遍历 \(n\) 次。

这意味着总共进行了 \(n \cdot n\) 次比较,因此冒泡排序的时间复杂度为

\[ \underline{\underline{O(n^2)}} \]

描述冒泡排序时间复杂度的图表如下所示

Bubble Sort time complexity

如您所见,当数组大小增加时,运行时间会非常快地增加。

幸运的是,还有比这更快的排序算法,例如我们稍后会看到的快速排序

您可以在下方模拟冒泡排序,其中红色虚线是理论时间复杂度 \(O(n^2)\)。您可以选择值的数量 \(n\),并运行实际的冒泡排序实现,其中操作被计数,并且计数在下面的图中标记为蓝色十字。理论与实践相比如何?

{{ this.userX }}

操作次数:{{ operations }}

 

DSA 练习

通过练习来测试自己

练习

在此数组上使用冒泡排序

[7,14,11,8,9]

按递增(升序)顺序对值从左到右进行排序。

在第一次遍历之后,数组会变成什么样子?

[,,,,]

开始练习



×

联系销售

如果您想将 W3Schools 服务用于教育机构、团队或企业,请发送电子邮件给我们
sales@w3schools.com

报告错误

如果您想报告错误,或想提出建议,请发送电子邮件给我们
help@w3schools.com

W3Schools 经过优化,旨在方便学习和培训。示例可能经过简化,以提高阅读和学习体验。教程、参考资料和示例会不断审查,以避免错误,但我们无法保证所有内容的完全正确性。使用 W3Schools 即表示您已阅读并接受我们的使用条款Cookie 和隐私政策

版权所有 1999-2024 Refsnes Data。保留所有权利。W3Schools 由 W3.CSS 提供支持