每日一算法——冒泡排序

0 阅读4分钟

算法概述

冒泡排序(Bubble Sort) 是最基础、最经典的排序算法之一,它通过重复比较相邻元素并交换位置,将较大的元素逐步 " 冒泡 " 到数组末尾,从而实现排序。这个算法的名字来源于排序过程中,较大的元素会像气泡一样逐渐上浮到序列的末端。

为什么需要学习冒泡排序? 虽然冒泡排序在实际工程中效率不高,但它作为排序算法的入门选择,具有以下重要意义:算法思想简单直观,易于理解和实现;是学习其他复杂排序算法的基础;在小规模数据排序或数据基本有序时仍有一定应用价值。

现实应用场景: 冒泡排序适用于小规模数据排序(如几十个元素)、数据库查询中对小结果集排序、数字图像处理中对像素值排序、传感器数据采集中的异常值筛选等场景。

核心思路和原理

冒泡排序的核心思想可以概括为:相邻元素两两比较,若顺序错误则交换,让较大元素像气泡一样逐步上浮到数组末尾。

  1. 外层循环控制轮次: 对于长度为 n 的数组,需要执行 n-1 轮冒泡排序。每一轮都会确定一个当前未排序部分的最大元素的位置。
  2. 内层循环比较交换: 在每一轮中,从数组的第一个元素开始,依次比较相邻的两个元素。如果前一个元素大于后一个元素(升序排序),就交换它们的位置。这样,每一轮结束后,当前未排序部分的最大元素就会 " 冒泡 " 到末尾。
  3. 优化提前终止: 在实现时,可以设置一个标志位来记录本轮是否发生了交换。如果某一轮没有发生任何交换,说明数组已经有序,可以提前结束排序,避免不必要的比较操作。
  4. 重复直到完成: 重复上述过程,每轮比较的范围都会减少一个元素(因为末尾的元素已经有序),直到所有元素都排好序。

关键概念解析 1. 稳定性:冒泡排序是稳定的排序算法,因为只有当相邻元素顺序错误时才交换,相等元素不会交换位置,保持了原始相对顺序。 2. 原地排序:冒泡排序只需要常数级别的额外空间(用于交换的临时变量),不需要额外的存储空间。

算法流程图

流程图说明:

  1. 外层循环控制排序轮次(i 从 0 到 n-2)
  2. 内层循环进行相邻元素比较和交换
  3. 设置标志位 flag,如果某轮没有交换则提前终止
  4. 每轮结束后,最大的元素会 " 冒泡 " 到数组末尾
  5. 重复直到数组完全有序或提前终止

详细示例演示

以数组  [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 = [64342512221190]
    print("排序前:", arr)
    arr = bubble_sort(arr)
    print("排序后:", arr)

代码说明:

  1. 外层循环执行 n-1 轮,控制排序轮次
  2. 内层循环每轮比较 n-i-1 次,比较范围逐轮缩小
  3. 使用 swapped 标志位优化,如果某轮没有交换则提前终止
  4. 交换操作使用 Python 元组交换语法,简洁高效