排序——快速排序

本文详细介绍了快速排序算法,包括其分治思想、实现代码、性能分析等关键内容。快速排序是一种高效的排序算法,采用递归方式将数组分为较小的子数组进行排序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

排序——快速排序

1. 思想

​ 快速排序主要运用的是分治的思想。例如对一个典型的子数组 A[p...r]A[p ... r ]A[p...r]进行快速排序,主要分成三步:

(1)分解

​ 数组 A[p...r]A[p ... r ]A[p...r] 被分成两个(可能为空)子数组 A[p...q−1]A[p ... q-1 ]A[p...q1]A[q+1...r]A[q+1 ... r ]A[q+1...r] ,使得 A[p...q−1]A[p ... q-1 ]A[p...q1]中的每个元素都小于等于 A[q]A[q]A[q],而 A[q]A[q]A[q] 也小于等于A[q+1...r]A[q+1 ... r ]A[q+1...r] 里的每个元素。其中,计算 q 也是划分过程的一部分;

(2)解决

​ 通过递归调用快速排序,对子数组 A[p...q−1]A[p ... q-1 ]A[p...q1]A[q+1...r]A[q+1 ... r ]A[q+1...r] 分别进行排序。

(3)合并

​ 因为子数组都是原址排序的,因此不需要合并操作,即此时数组 A[p...r]A[p ... r ]A[p...r]已经是有序的。

2. 代码

​ 利用快速排序算法对数组 a 的所有元素进行排序(从小到大),则开始时需要调用 Quiksort 函数:

void Quiksort(int *a, int p, int r) {
    int q;

    if(p < r) {
        q = Partition(a, p, r);
        Quiksort(a, p, q-1);
        Quiksort(a, q+1, r);
    }
}

该函数的关键在于 Partition,即划分的过程,该函数如下:

int Partition(int *a, int p, int r) {
    int x, i, j, temp;

    x = a[r];
    i = p - 1;

    for(j=p; j<r; j++) {
        if(a[j] < x) {
            temp = a[++i];
            a[i] = a[j];
            a[j] = temp;
        }
    }
    temp = a[i+1];
    a[i+1] = x;
    a[r] = temp;
    return i+1;
}

partition 函数总是选择一个 x=a[r]x = a[r]x=a[r] 作为主元,并围绕它来划分子数组 A[p...r]A[p ... r]A[p...r]。随着程序的进行,数组被划分成 4 个(可能有空的)区域:

(1)若 $p \leq k \leq i $,则 A[k]≤xA[k] \leq xA[k]x;

(2)若 i+1≤k≤j−1i+1 \leq k \leq j-1i+1kj1,则 A[k]&gt;xA[k] &gt; xA[k]>x;

(3)若 $k = r $,则 A[k]=xA[k] = xA[k]=x;

(4)若 j≤k≤r−1j \leq k \leq r-1jkr1,还未到达。

3. 性能分析

(1)稳定性

​ 快速排序是不稳定的。举个例子,对 [3, 8, 4, 5A, 6, 5B]进行快速排序,最后的结果 5B 会排到 5A 前面。

(2)原地排序

​ 快速排序是原地排序

(3)时间复杂度

​ 最坏情况下是 O(n2)O(n^2)O(n2);最好情况是 O(nlgn)O(nlgn)O(nlgn)

(4)空间复杂度

O(lgn)O(lgn)O(lgn)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值