Gemini永久会员 快速排序(Quick Sort) 基于分治思想的高效排序算法

快速排序(Quick Sort)是一种基于分治思想的高效排序算法,其核心步骤包括选择基准(pivot)、分区(partition)、递归排序。以下是Java中快速排序的实现及详细解析:


1. 快速排序原理

  1. 选择基准:从数组中选择一个元素作为基准(通常选择最后一个元素)。
  2. 分区:将数组分为两部分,使得左边部分的元素均小于等于基准,右边部分的元素均大于基准。
  3. 递归排序:对左右两部分递归调用快速排序。

2. Java实现代码

java 复制代码
public class QuickSort {

    // 主方法:对外接口
    public static void sort(int[] arr) {
        if (arr == null || arr.length <= 1) {
            return;
        }
        quickSort(arr, 0, arr.length - 1);
    }

    // 递归分治
    private static void quickSort(int[] arr, int left, int right) {
        if (left < right) {
            int pivotIndex = partition(arr, left, right); // 获取基准位置
            quickSort(arr, left, pivotIndex - 1);         // 递归排序左半部分
            quickSort(arr, pivotIndex + 1, right);        // 递归排序右半部分
        }
    }

    // 分区操作(Lomuto分区方案)
    private static int partition(int[] arr, int left, int right) {
        int pivot = arr[right]; // 选择最右元素作为基准
        int i = left;           // i是小于基准的边界

        for (int j = left; j < right; j++) {
            if (arr[j] <= pivot) {
                swap(arr, i, j); // 将小于等于基准的元素交换到左边
                i++;
            }
        }
        swap(arr, i, right); // 将基准放到正确位置
        return i;            // 返回基准的最终索引
    }

    // 交换数组元素
    private static void swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

    public static void main(String[] args) {
        int[] arr = {10, 7, 8, 9, 1, 5};
        System.out.println("排序前: " + Arrays.toString(arr));
        sort(arr);
        System.out.println("排序后: " + Arrays.toString(arr));
    }
}

3. 关键点解析

  1. 基准选择
    • 常用方法:选择最右元素(如上例)、随机选择或三数取中(避免最坏情况)。
  2. 分区方案
    • Lomuto分区:简单但效率较低(如上述代码)。
    • Hoare分区:更高效,但实现稍复杂(见下文优化部分)。
  3. 稳定性
    • 快速排序是不稳定的(交换操作可能改变相等元素的顺序)。
  4. 时间复杂度
    • 最优/平均:(O(n \log n))(每次分区平衡)。
    • 最差:(O(n^2))(每次分区极度不平衡,如数组已有序)。
  5. 空间复杂度
    • (O(\log n))(递归栈开销)。

4. 优化方向

(1) 三数取中法选基准

避免最坏情况(如数组已有序):

java 复制代码
private static int choosePivot(int[] arr, int left, int right) {
    int mid = left + (right - left) / 2;
    // 对left、mid、right排序,返回中位数
    if (arr[left] > arr[mid]) swap(arr, left, mid);
    if (arr[left] > arr[right]) swap(arr, left, right);
    if (arr[mid] > arr[right]) swap(arr, mid, right);
    return mid; // 返回中位数的索引
}
(2) Hoare分区方案

减少交换次数:

java 复制代码
private static int partitionHoare(int[] arr, int left, int right) {
    int pivot = arr[left]; // 选择最左元素作为基准
    int i = left - 1;
    int j = right + 1;
    while (true) {
        do { i++; } while (arr[i] < pivot);
        do { j--; } while (arr[j] > pivot);
        if (i >= j) return j;
        swap(arr, i, j);
    }
}
(3) 小数组优化

对小规模子数组(如长度<10)切换为插入排序:

java 复制代码
private static void quickSort(int[] arr, int left, int right) {
    if (left < right) {
        if (right - left < 10) {
            insertionSort(arr, left, right);
        } else {
            int pivotIndex = partition(arr, left, right);
            quickSort(arr, left, pivotIndex - 1);
            quickSort(arr, pivotIndex + 1, right);
        }
    }
}
(4) 尾递归优化

减少递归栈深度:

java 复制代码
private static void quickSort(int[] arr, int left, int right) {
    while (left < right) {
        int pivotIndex = partition(arr, left, right);
        quickSort(arr, left, pivotIndex - 1); // 先处理左半部分
        left = pivotIndex + 1;                // 尾递归处理右半部分
    }
}

5. 对比归并排序

特性 快速排序 归并排序
时间复杂度 平均 (O(n \log n)) 稳定 (O(n \log n))
空间复杂度 (O(\log n)) (O(n))
稳定性 不稳定 稳定
适用场景 内存敏感、追求平均性能 大数据量、需要稳定性

6. 适用场景

  • 内存敏感:快速排序的 (O(\log n)) 空间复杂度优于归并排序的 (O(n))。
  • 平均性能优先:在随机数据中表现优异。
  • 不要求稳定性:如排序基本类型数组。

总结

快速排序通过分治和分区思想实现了高效排序,但在最坏情况下性能较差。通过优化基准选择、分区方案和小数组处理,可以显著提升其鲁棒性。理解快速排序的核心在于掌握分区过程的实现细节。

相关推荐
x***440144 分钟前
linux 设置tomcat开机启动
linux·运维·tomcat
I***t7161 小时前
【MyBatis】spring整合mybatis教程(详细易懂)
java·spring·mybatis
YA3331 小时前
mcp-grafana mcp 使用stdio报错
java·开发语言
cpp_25011 小时前
P5412 [YNOI2019] 排队
数据结构·c++·算法·题解·洛谷
z***02601 小时前
SpringBoot创建动态定时任务的几种方式
java·spring boot·spring
正在努力的小河1 小时前
Linux 块设备驱动实验
linux·运维·服务器
w***95491 小时前
VScode 开发 Springboot 程序
java·spring boot·后端
_OP_CHEN1 小时前
算法基础篇:(二十一)数据结构之单调栈:从原理到实战,玩转高效解题
数据结构·算法·蓝桥杯·单调栈·算法竞赛·acm/icpc
兔子撩架构1 小时前
Dubbo 的同步服务调用
java·后端·spring cloud