排序算法【2】——快速排序

算法描述

快速排序采用了分治的思想:

  • 分解:数组A[pr]被划分为两个子数组A[pq1]A[q+1r],使得A[pq1]中的元素小于等于A[q]A[q+1r]中的元素大于等于A[q]
  • 解决:通过递归调用快速排序,对子数组A[pq1]A[q+1r]进行排序

伪代码

在不同的快速排序算法实现中有不同的分区PARTITION策略

QUICKSORT(A, p, r)
    if p < r
        q = PARTITION(A, p, r)
        QUICKSORT(A, p, q - 1)
        QUICKSORT(A, q + 1, r)

PARTITION(A, p, r)
    i = RANDOM(p, r)
    exchange A[r] with A[i]
    x = A[r]
    i = p - 1
    for j = p to r - 1
        if A[j] <= x
            i = i + 1
            exchange A[i] with A[j]
    exchange A[i + 1] with A[r]
    return i + 1

算法复杂度

这里假设数组A[pr]中元素互不相同

  • 最好情况:每次分区的时候,两边的分区大小一致,那么最多递归log(n)层,每一层都会比对n次,所以时间复杂度为Θ(nlog(n))
  • 最坏情况:每次分区选的主元A[q]都是当前数组中的最大值或者最小值,那么会递归n层,时间复杂度为Θ(n2)
  • 平均情况:令随机变量X表示整个快速排序过程中比对次数,那么E(X)2nlnn,所以时间复杂度为Θ(nlog(n))

期望E(X)的计算过程:
令随机变量

Xij={1,if A[i] compared with A[j] during the process0,otherwise

注意到,元素A[i]A[j]最多只会发生一次比较(比较之后主元不会进入分区),所以

E(X)=E(i=1n1j=i+1nXij)

同时A[i]A[j]发生比较的概率,就是元素A[i]或者A[j]作为区间A[ij]中第一个被选取的主元,这一概率

Pr{A[i]orA[j]asthefirstpivotchosenfromA[ij]}=2ji+1

所以

(1)E(X)=E(i=1n1j=i+1nXij)(2)=i=1n1j=i+1nE(Xij)(3)=i=1n1j=i+1n2ji+1(4)=i=1n12(ln(ni+2)1)(5)=i=1n12(ln(i+2)1)(6)2ln(n!)(7)2nlnn

Hoare分区

在上面朴素的分区策略中,无法将与主元相等的元素平均地划分到左右子区间,Hoare分区策略解决了这个问题,那就是从两边开始扫描:

HOARE-PARTITION(A, p, r)
    i = RANDOM(p, r)
    pivot = A[i]
    p = p - 1
    while true
        while A[++p] < pivot
        while pivot < A[--r]
        if p < r
            exchange A[p] with A[r]
        else
            return p

实际上,std::sort采用的也是这种方式,所以C++标准规定了传入的比较函数必须保证cmp(a,b)!=cmp(b,a),比如:

int n = 10000000;
std::vector<int> vec(n);
std::sort(vec.begin(), vec.end(), [] (int x, int y) {
    return x <= y;
});

上面的代码会造成内存越界,从而segmentfault

posted @   HachikoT  阅读(123)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示