快速排序算法详解

算法思想

快速排序是一种高效的排序算法,采用分治策略​(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. 尾递归优化​:减少递归深度

算法特点

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

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

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

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

相关推荐
仍然.13 分钟前
算法题目---BFS解决最短路问题
算法·宽度优先
渡众机器人14 分钟前
第八届全球校园人工智能算法精英大赛-算法应用赛-空地协同侦排挑战赛规则
人工智能·算法
wayz1126 分钟前
Overlap:HWMA(Holt-Winter移动平均线)技术指标详解
算法·金融·数据分析·量化交易·特征工程
Shadow(⊙o⊙)43 分钟前
专题四:前缀和
数据结构·算法
JAVA面经实录9171 小时前
高频算法面试题
java·计算机网络·算法·面试
qq_452396231 小时前
第十一篇:《资源管理:Requests/Limits、ResourceQuota、LimitRange》
算法·贪心算法
Tisfy1 小时前
LeetCode 2095.删除链表的中间节点:两次遍历 / 一次遍历(快慢指针)
算法·leetcode·链表·题解·双指针
Irissgwe1 小时前
AVL树详解
数据结构·c++·算法·二叉树·c·二叉搜索树·avl
凌波粒1 小时前
LeetCode--131.分割回文串(回溯算法)
算法·leetcode·职场和发展
北域码匠2 小时前
奇偶归并排序:并行计算的排序利器
数据结构·算法·c#·排序算法