算法概述
冒泡排序(Bubble Sort) 是最基础、最经典的排序算法之一,它通过重复比较相邻元素并交换位置,将较大的元素逐步 " 冒泡 " 到数组末尾,从而实现排序。这个算法的名字来源于排序过程中,较大的元素会像气泡一样逐渐上浮到序列的末端。
为什么需要学习冒泡排序? 虽然冒泡排序在实际工程中效率不高,但它作为排序算法的入门选择,具有以下重要意义:算法思想简单直观,易于理解和实现;是学习其他复杂排序算法的基础;在小规模数据排序或数据基本有序时仍有一定应用价值。
现实应用场景: 冒泡排序适用于小规模数据排序(如几十个元素)、数据库查询中对小结果集排序、数字图像处理中对像素值排序、传感器数据采集中的异常值筛选等场景。
核心思路和原理
冒泡排序的核心思想可以概括为:相邻元素两两比较,若顺序错误则交换,让较大元素像气泡一样逐步上浮到数组末尾。
- 外层循环控制轮次: 对于长度为 n 的数组,需要执行 n-1 轮冒泡排序。每一轮都会确定一个当前未排序部分的最大元素的位置。
- 内层循环比较交换: 在每一轮中,从数组的第一个元素开始,依次比较相邻的两个元素。如果前一个元素大于后一个元素(升序排序),就交换它们的位置。这样,每一轮结束后,当前未排序部分的最大元素就会 " 冒泡 " 到末尾。
- 优化提前终止: 在实现时,可以设置一个标志位来记录本轮是否发生了交换。如果某一轮没有发生任何交换,说明数组已经有序,可以提前结束排序,避免不必要的比较操作。
- 重复直到完成: 重复上述过程,每轮比较的范围都会减少一个元素(因为末尾的元素已经有序),直到所有元素都排好序。
关键概念解析 1. 稳定性:冒泡排序是稳定的排序算法,因为只有当相邻元素顺序错误时才交换,相等元素不会交换位置,保持了原始相对顺序。 2. 原地排序:冒泡排序只需要常数级别的额外空间(用于交换的临时变量),不需要额外的存储空间。
算法流程图
流程图说明:
- 外层循环控制排序轮次(i 从 0 到 n-2)
- 内层循环进行相邻元素比较和交换
- 设置标志位 flag,如果某轮没有交换则提前终止
- 每轮结束后,最大的元素会 " 冒泡 " 到数组末尾
- 重复直到数组完全有序或提前终止
详细示例演示
以数组 [5, 3, 8, 4, 2] 进行升序排序为例,逐步演示冒泡排序过程:
第一轮排序:
- 比较 5 和 3:5>3,交换 → [3, 5, 8, 4, 2]
- 比较 5 和 8:5<8,不交换 → [3, 5, 8, 4, 2]
- 比较 8 和 4:8>4,交换 → [3, 5, 4, 8, 2]
- 比较 8 和 2:8>2,交换 → [3, 5, 4, 2, 8]
- 第一轮结束,最大值 8 已到末尾
第二轮排序:
- 比较 3 和 5:3<5,不交换 → [3, 5, 4, 2, 8]
- 比较 5 和 4:5>4,交换 → [3, 4, 5, 2, 8]
- 比较 5 和 2:5>2,交换 → [3, 4, 2, 5, 8]
- 第二轮结束,次大值 5 已到正确位置
第三轮排序:
- 比较 3 和 4:3<4,不交换 → [3, 4, 2, 5, 8]
- 比较 4 和 2:4>2,交换 → [3, 2, 4, 5, 8]
- 第三轮结束,4 已到正确位置
第四轮排序:
- 比较 3 和 2:3>2,交换 → [2, 3, 4, 5, 8]
- 第四轮结束,数组完全有序
Python 代码实现
def bubble_sort(arr):
n = len(arr)
for i in range(n-1):
swapped = False # 标记是否有交换发生
for j in range(0, n-i-1):
if arr[j] > arr[j+1]:
arr[j], arr[j+1] = arr[j+1], arr[j]
swapped = True
# 如果在一次遍历中没有发生交换,说明数组已经有序,直接跳出循环
if not swapped:
break
return arr
if __name__ == '__main__':
arr = [64, 34, 25, 12, 22, 11, 90]
print("排序前:", arr)
arr = bubble_sort(arr)
print("排序后:", arr)
代码说明:
- 外层循环执行 n-1 轮,控制排序轮次
- 内层循环每轮比较 n-i-1 次,比较范围逐轮缩小
- 使用 swapped 标志位优化,如果某轮没有交换则提前终止
- 交换操作使用 Python 元组交换语法,简洁高效