交换排序:冒泡排序 vs 快速排序(Java)

一、冒泡排序

1. 标准版代码

java 复制代码
public void bubbleSort01(int[] arr) {
    int n = arr.length;
    for (int i = 0; i < n - 1; i++) {
        for (int j = 0; j < n - 1 - i; j++) {
            if (arr[j] > arr[j + 1]) {
                int temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
        }
    }
}

2. 优化版代码(提前终止)

java 复制代码
public void bubbleSort02(int[] arr) {
    int n = arr.length;
    for (int i = 0; i < n - 1; i++) {
        boolean swapped = false;
        for (int j = 0; j < n - 1 - i; j++) {
            if (arr[j] > arr[j + 1]) {
                int temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
                swapped = true;
            }
        }
        if (!swapped) break;
    }
}

3. 复杂度与稳定性

指标
最好时间复杂度 O(n)(优化版,已有序)
最坏时间复杂度 O(n²)
平均时间复杂度 O(n²)
空间复杂度 O(1)
稳定性 ✅ 稳定

4. 适用场景

  • 数据量小(<1000)

  • 数据基本有序(优化版效率高)

  • 教学演示


二、快速排序

1. 核心思路

选一个基准(pivot),把比它小的放左边,比它大的放右边,然后递归处理左右两边。

2. 代码(随机基准版)

java 复制代码
public void quickSort(int[] arr, int left, int right) {
    if (left >= right) return;
    int pivotIndex = partition(arr, left, right);
    quickSort(arr, left, pivotIndex - 1);
    quickSort(arr, pivotIndex + 1, right);
}

public int partition(int[] arr, int left, int right) {
    // 随机选基准,避免最坏情况
    int randomIndex = left + (int)(Math.random() * (right - left + 1));
    swap(arr, randomIndex, right);
    
    int pivot = arr[right];
    int i = left;
    for (int j = left; j < right; j++) {
        if (arr[j] <= pivot) {
            swap(arr, i, j);
            i++;
        }
    }
    swap(arr, i, right);
    return i;
}

public void swap(int[] arr, int i, int j) {
    int temp = arr[i];
    arr[i] = arr[j];
    arr[j] = temp;
}

3. 复杂度与稳定性

指标
最好时间复杂度 O(n log n)
最坏时间复杂度 O(n²)(随机化后几乎不出现)
平均时间复杂度 O(n log n)
空间复杂度 O(log n)(递归栈)
稳定性 ❌ 不稳定

4. 为什么快排不稳定?

快排的不稳定性来源于分区时的远距离交换

举例:[(3A), 2, (3B)](括号表示相同值 3,A 和 B 区分顺序)

  • 2 为基准分区后,3A3B 的相对顺序可能改变

  • 因为 swap 会把右边的小元素换到左边,可能让 3B 跑到 3A 前面

而冒泡排序只交换相邻元素,相同值的元素不会互相跨越,所以是稳定的。

5. 适用场景

  • 数据量大、不要求稳定性

  • 平均性能最好的通用排序


三、两者对比总结

对比项 冒泡排序 快速排序
最好时间复杂度 O(n) O(n log n)
最坏时间复杂度 O(n²) O(n²)(随机化后极少出现)
平均时间复杂度 O(n²) O(n log n)
空间复杂度 O(1) O(log n)
稳定性 ✅ 稳定 ❌ 不稳定
数据量大时
数据基本有序时 快(优化版) 反而可能慢(固定基准)

如何选择?

场景 推荐算法 原因
数据量小(<1000) 冒泡排序 简单,常数小
数据量大、不要求稳定 快速排序 最快
数据量大、要求稳定 归并排序 稳定 O(n log n)
数据基本有序 冒泡排序(优化版) O(n)

四、扩展:快速排序的优化技巧(选读)

  1. 随机选基准(已实现)→ 避免最坏情况

  2. 三数取中 → 更稳定的基准选择

  3. 小数组切换插入排序 → 减少递归深度

  4. 尾递归优化 → 节省栈空间


五、总结

冒泡排序 :简单、稳定、适合小数据,优化版对基本有序数据友好。
快速排序:高效、不稳定、适合大数据,随机选基准避免了最坏情况。

复习:01dx

相关推荐
名侦探7229 分钟前
构建 Agent 的五大难点与解决方案
java·大数据·人工智能
Demons_kirit12 分钟前
图库原理(以阿里云OSS为案例)
java·阿里云·云计算
SimonKing15 分钟前
那个号称"对标 Spring"的国产框架 Solon,到底行不行?
java·后端·程序员
Lethehong17 分钟前
飞算Java:从需求梳理到风险闭环,搭建云盾企业信息安全与权限管理平台
java·开发语言
霸道流氓气质20 分钟前
SpringBoot中使用字典驱动的动态路由示例
java·spring boot·后端
旖-旎21 分钟前
《LeetCode 416 分割等和子集》
c++·算法·leetcode·动态规划·背包问题
Jasmine_llq28 分钟前
《P15798 [GESP202603 五级] 有限不循环小数》
算法·有限小数判定数论定理·质因子约分检验·枚举生成合法数字·哈希集合去重·快速 io 优化
学计算机的计算基36 分钟前
操作系统八股文:进程与线程全面梳理(附调度算法+IPC+锁机制)
java·算法
wuqingshun3141591 小时前
请描述简单工厂模式的工作原理
java·简单工厂模式