快速排序算法详解

算法思想

快速排序是一种高效的排序算法,采用分治策略​(Divide and Conquer)。它的基本思想是:

  1. 选择一个基准元素(pivot)

  2. 将数组分区,使得所有小于基准的元素都在其左侧,所有大于基准的元素都在其右侧

  3. 递归地对左右两个子数组进行快速排序

算法步骤

  1. 选择基准​:从数组中选择一个元素作为基准(pivot)

  2. 分区操作​:重新排列数组,使所有小于基准的元素放在基准前面,所有大于基准的元素放在基准后面

  3. 递归排序​:递归地将上述过程应用于基准左右两侧的子数组

Java实现

复制代码
public class QuickSort {
    
    // 快速排序入口方法
    public static void quickSort(int[] arr) {
        if (arr == null || arr.length == 0) {
            return;
        }
        quickSort(arr, 0, arr.length - 1);
    }
    
    // 递归快速排序
    private static void quickSort(int[] arr, int low, int high) {
        if (low < high) {
            // 分区操作,返回基准的索引位置
            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[high];
        
        // 小于基准的元素的边界索引
        int i = low - 1;
        
        for (int j = low; j < high; j++) {
            // 如果当前元素小于或等于基准
            if (arr[j] <= pivot) {
                i++;
                // 交换arr[i]和arr[j]
                swap(arr, i, j);
            }
        }
        
        // 将基准元素放到正确位置
        swap(arr, i + 1, high);
        
        return i + 1;
    }
    
    // 交换数组中两个元素的位置
    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 = {64, 34, 25, 12, 22, 11, 90};
        
        System.out.println("排序前的数组:");
        printArray(arr);
        
        quickSort(arr);
        
        System.out.println("排序后的数组:");
        printArray(arr);
    }
    
    // 打印数组
    private static void printArray(int[] arr) {
        for (int value : arr) {
            System.out.print(value + " ");
        }
        System.out.println();
    }
}

时间复杂度分析

  • 最佳情况​:O(n log n) - 每次分区都能将数组均匀分成两部分

  • 平均情况​:O(n log n)

  • 最坏情况​:O(n²) - 当数组已经有序或逆序,且选择最边缘的元素作为基准时

空间复杂度

  • 平均情况下:O(log n) - 递归调用栈的空间

  • 最坏情况下:O(n) - 需要n层递归调用

优化策略

  1. 随机选择基准​:随机选择基准元素可以避免最坏情况的发生

  2. 三数取中法​:选择第一个、中间和最后一个元素的中值作为基准

  3. 小数组使用插入排序​:当子数组规模较小时(如<10),使用插入排序更高效

  4. 尾递归优化​:减少递归深度

算法特点

  • 不稳定排序​:相等元素的相对位置可能会改变

  • 原地排序​:只需要常数级的额外空间

  • 实践中最快​:尽管最坏情况时间复杂度较高,但在实际应用中通常是最快的排序算法

快速排序因其高效性和实用性,被广泛应用于各种编程语言和系统的排序实现中。

相关推荐
jiaway5 小时前
【C语言】第二课 位运算
c语言·开发语言·算法
Q741_1475 小时前
C++ 面试高频考点 力扣 153. 寻找旋转排序数组中的最小值 二分查找 题解 每日一题
c++·算法·leetcode·面试·二分查找
麦格芬2305 小时前
LeetCode 994 腐烂的橘子
算法·leetcode·职场和发展
mit6.8245 小时前
[re_3]
c++·算法
LDG_AGI5 小时前
【推荐系统】推荐召回算法(一):双塔召回模型训练与推理(Dual Tower Model and Faiss Retrieval)
算法
程序员Xu6 小时前
【LeetCode热题100道笔记】轮转数组
笔记·算法·leetcode
JuneXcy6 小时前
指针高级(3)
数据结构·算法
数维学长9866 小时前
【全网最全】《2025国赛/高教杯》C题 思路+代码python和matlab+文献 一到四问 退火算法+遗传算法 NIPT的时点选择与胎儿的异常判定
开发语言·算法·matlab
zhuoya_6 小时前
子串:最小覆盖子串
java·数据结构·算法·leetcode