排序(3)-第三篇:交换排序专题——从冒泡排序到快速排序的效率飞跃

📌 引言

交换排序,顾名思义,核心操作就是通过"两两比较并交换"来达到有序的目的 。这一族群里有两个极具代表性的选手:一个是无数人的启蒙算法------冒泡排序 ;另一个则是工业界、面试官长盛不衰的宠儿------快速排序。它们之间,是一场关于执行效率的惊艳飞跃。

1. 冒泡排序(Bubble Sort)

💡 核心思想

从左到开依次比较相邻的两个数,如果前面的数比后面的大,就交换它们。这样一轮下来,当前区间的最大值就像"气泡"一样浮到了数组的最右端。

💻 Java 代码实现(带提前跳出优化)
复制代码
public class BubbleSort {
    public static void sort(int[] arr) {
        if (arr == null || arr.length < 2) return;
        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; 
        }
    }
}

2. 快速排序(Quick Sort)

🚀 为什么叫快速排序?

冒泡排序太慢了,因为每次交换只能解决相邻 两个元素的无序问题。而快速排序采用分治思想(Divide and Conquer),通过选择一个"基准值",让大小元素横跨大半个数组进行对调,从而实现大步流星的排序。

💡 核心思想
  1. 找基准(Pivot): 通常选区间第一个数作为基准。

  2. 分区(Partition): 通过双指针左右开弓,把比 Pivot 小的扔到左边,比 Pivot 大的扔到右边。

  3. 递归(Solve): 此时 Pivot 已经锁定了它的最终位置。接下来对左、右两部分分别重复上述过程。

💻 Java 代码实现(标准双指针法)
复制代码
public class QuickSort {
    public static void sort(int[] arr) {
        if (arr == null || arr.length < 2) return;
        quickSort(arr, 0, arr.length - 1);
    }

    private static void quickSort(int[] arr, int low, int high) {
        if (low >= high) return;
        
        // 核心切分操作,返回基准值的最终正确索引
        int pivotIndex = partition(arr, low, high);
        
        quickSort(arr, low, pivotIndex - 1);  // 递归搞定左半部分
        quickSort(arr, pivotIndex + 1, high); // 递归搞定右半部分
    }

    private static int partition(int[] arr, int low, int high) {
        int pivot = arr[low]; 
        int i = low, j = high + 1;
        
        while (true) {
            // 左指针向右找第一个比 pivot 大的数
            while (arr[++i] < pivot) if (i == high) break;
            // 右指针向左找第一个比 pivot 小的数
            while (pivot < arr[--j]) if (j == low) break;
            
            if (i >= j) break; // 指针相遇,退出循环
            swap(arr, i, j);   // 交换这两个错位的数
        }
        swap(arr, low, j); // 将基准值交换到它的最终正确位置 `j`
        return j; 
    }

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

📊 交换排序大比拼

算法 最好时间复杂度 最坏时间复杂度 平均时间复杂度 空间复杂度 稳定性
冒泡排序 O(n) O(n^2) O(n^2) O(1) 稳定
快速排序 O(n \log n) O(n^2) O(n \log n) O(\log n) (递归栈) 不稳定
相关推荐
小羊没烦恼!1 天前
微服务化的基石——持续集成
java·大数据·word·powerpoint·.net
倒头就睡的小比特1 天前
算法竞赛C++常用的STL
c++·算法
俊昭喜喜里1 天前
java中的继承和多态的区别
java
小羊没烦恼!1 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
譕痕1 天前
JSONObject与JSONArray封装数据格式区别
java·json
胡写代码1 天前
别再前后端各写一套表单校验了
java·后端
小鱼能吃糖1 天前
缺陷修复总览 · mall电商项目:5类缺陷,1个病根,4个业务域
java·电商
此时不提桶,更待何时1 天前
01-06-A-JVM排查实战详解
java·jvm
猎头南楼1 天前
知识社区推荐系统实践:新用户冷启动与长短期兴趣建模的挑战 资深推荐算法工程师
人工智能·深度学习·算法·机器学习
vipxieliang1 天前
ValidX 在 DDD 领域驱动设计中的实践
java·spring boot