一句话说透数据结构里面的冒泡排序,如何优化?

241 阅读3分钟

一句话总结:
冒泡排序就像排队——个子高的同学不断往后冒泡,直到全体从矮到高排好队。优化就是让老师别傻盯着,发现队伍已经整齐就提前放学!


一、基础版冒泡排序(老实人版)

原理:

  1. 从头开始比较相邻两个同学
  2. 如果左边比右边高,就交换位置
  3. 每轮结束,最高的同学冒到最后
  4. 重复直到全体有序

Kotlin 代码:

fun bubbleSortBasic(arr: IntArray) {
    for (i in 0 until arr.size - 1) {         // 外层:要排n-1轮
        for (j in 0 until arr.size - 1 - i) { // 内层:每轮少比一个(最后的已排好)
            if (arr[j] > arr[j + 1]) {        // 前一个比后一个大
                val temp = arr[j]             // 交换位置(矮个前移)
                arr[j] = arr[j + 1]
                arr[j + 1] = temp
            }
        }
    }
}

举个栗子 🌰:
初始数组:[5, 3, 8, 2]
第1轮结束:[3, 5, 2, 8] (8冒到最后)
第2轮结束:[3, 2, 5, 8] (5冒到倒数第二)
第3轮结束:[2, 3, 5, 8] (3冒到位)

缺点:

  • 即使数组已经有序,仍然傻乎乎跑完所有轮
  • 每轮都要从头比到尾,不管后面是否已排好

二、优化版冒泡排序(聪明版)

优化 1:提前放学(发现无交换就停止)

fun bubbleSortOptimized(arr: IntArray) {
    var swapped: Boolean
    for (i in 0 until arr.size - 1) {
        swapped = false // 每轮开始重置标志
        for (j in 0 until arr.size - 1 - i) {
            if (arr[j] > arr[j + 1]) {
                val temp = arr[j]
                arr[j] = arr[j + 1]
                arr[j + 1] = temp
                swapped = true // 发生交换就标记
            }
        }
        if (!swapped) break // 一轮无交换 → 全体有序 → 收工!
    }
}

优化 2:记录最后交换位置(减少无效比较)

fun bubbleSortSuperOptimized(arr: IntArray) {
    var lastSwapIndex = arr.size - 1
    var currentSwapIndex: Int

    repeat(arr.size) { // 最多还是n轮
        currentSwapIndex = -1 // 初始化
        for (j in 0 until lastSwapIndex) {
            if (arr[j] > arr[j + 1]) {
                val temp = arr[j]
                arr[j] = arr[j + 1]
                arr[j + 1] = temp
                currentSwapIndex = j // 记录最后一次交换的位置
            }
        }
        if (currentSwapIndex == -1) break // 无交换直接结束
        lastSwapIndex = currentSwapIndex // 下一轮只比到这里
    }
}

优化效果:

  • 如果数组已经有序 → 只跑一轮(时间复杂度从O(n²) → O(n))
  • 后半段已排好 → 后面不再比较(减少内层循环次数)

三、性能对比(假设数组长度n)

情况基础版优化版1优化版2
完全逆序O(n²)O(n²)O(n²)
完全有序O(n²)O(n)O(n)
部分有序O(n²)介于O(n)-O(n²)更接近O(n)

四、使用场景

  1. 优点:

    • 代码简单,适合教学
    • 对小规模数据或接近有序的数据表现不错
  2. 缺点:

    • 大规模数据效率低(时间复杂度硬伤)
    • 实际开发中更常用快速排序、归并排序

举个真实场景:

  • 手机通讯录里100个联系人按名字排序 → 可以用
  • 给10万个用户ID排序 → 快跑,别用冒泡!

五、终极口诀

冒泡排序两重天,
优化只需两板斧:
一轮无交换,提前收工;
记录最后位,少做白工!

简单场景用它行,
海量数据请绕道。