【每日算法】Day 1-2:快速排序终极指南——从原理到优化一网打尽(C++实现)

算法进阶必备!今日解锁高效排序算法——快速排序,双版本代码+复杂度优化分析,带你领略分治思想的精妙。

一、快速排序核心思想

快速排序(Quick Sort)由Tony Hoare于1959年提出,采用分治策略

通过选定基准值(pivot),将数组分割为两个子序列,递归排序后合并实现整体有序。

算法特性:

  • 不稳定排序(相同元素可能改变顺序)

  • 平均时间复杂度:O(n log n)

  • 最坏时间复杂度:O(n²)(可通过优化避免)

  • 空间复杂度:O(log n)(递归栈)

二、算法原理图解

三步核心流程:

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

  2. 分区操作:将数组分为三部分(< pivot,== pivot,> pivot)

  3. 递归排序:对左右子数组递归执行上述操作

三、C++代码实现

基础递归版本
#include <iostream>
using namespace std;

// 分区函数(Lomuto方案)
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;
            swap(arr[i], arr[j]);
        }
    }
    swap(arr[i+1], arr[high]);
    return i + 1;  // 返回基准最终位置
}

void quickSort(int arr[], int low, int high) {
    if (low < high) {
        int pi = partition(arr, low, high);
        quickSort(arr, low, pi - 1);
        quickSort(arr, pi + 1, high);
    }
}

// 示例用法
int main() {
    int arr[] = {10, 7, 8, 9, 1, 5};
    int n = sizeof(arr)/sizeof(arr[0]);
    
    quickSort(arr, 0, n-1);
    
    cout << "排序结果:";
    for (int i=0; i<n; ++i) 
        cout << arr[i] << " ";
    return 0;
}
迭代优化版本(避免递归栈溢出)
#include <stack>
void quickSortIterative(int arr[], int low, int high) {
    stack<int> s;
    s.push(low);
    s.push(high);

    while (!s.empty()) {
        high = s.top(); s.pop();
        low = s.top(); s.pop();
        
        int pi = partition(arr, low, high);
        
        if (pi - 1 > low) {
            s.push(low);
            s.push(pi - 1);
        }
        if (pi + 1 < high) {
            s.push(pi + 1);
            s.push(high);
        }
    }
}

关键点解析:

  • partition()函数实现核心分区逻辑

  • Lomuto方案 vs Hoare方案(本文采用更易理解的Lomuto)

  • 递归终止条件low < high

  • 迭代版本使用显式栈模拟递归过程

四、实例演算

以数组[3, 0, 2, 5, 1]为例(选择最后一个元素为pivot):

首次分区过程:

初始数组:[3, 0, 2, 5, 1](pivot=1)
第1次比较:3 > 1 → 不交换(i=-1, j=0)
第2次比较:0 ≤ 1 → i=0,交换arr[0]和arr[1]
当前数组:[0, 3, 2, 5, 1]
第3次比较:2 > 1 → 不交换
第4次比较:5 > 1 → 不交换
最终交换基准位置:[0, 1, 2, 5, 3]
返回基准位置:1

五、复杂度与优化

情况时间复杂度空间复杂度解决方案
最佳情况O(n log n)O(log n)平衡分区
最差情况O(n²)O(n)随机化选择pivot
平均情况O(n log n)O(log n)

三数取中法

常见优化策略:

  1. 随机化pivot选择:避免有序数组的最坏情况

    int random = low + rand() % (high - low);
    swap(arr[random], arr[high]);
  2. 三数取中法:取首、中、尾的中位数作为pivot

  3. 插入排序混合:当子数组长度较小时切换排序算法

六、总结与进阶

优势:

  • 平均性能最好的O(n log n)排序算法

  • 内存访问模式对缓存友好

  • 可并行化优化(多线程处理子数组)

局限:

  • 递归实现可能栈溢出

  • 不稳定排序特性

  • 最坏情况需通过优化避免

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值