数据结构算法——排序算法解析

1、快排

  • 快速排序:
  • 将子序列划分为两个部分S1、S2,并且满足S1中最大值小于S2中最小值。

  • 这样,在子序列分别递归的排序之后,原序列自然有序。

  • 轴点:左 / 右侧的元素,均不比它更大 / 小。

  • 轴点自然的将序列分为了符合之前条件的两个部分,剩下的部分只需递归完成即可。

    template
    void Vector::quickSort ( Rank lo, Rank hi ) {
    if ( hi - lo < 2 ) return; //单元素区间自然有序,否则...
    Rank mi = partition ( lo, hi ); //在[lo, hi)内构造轴点
    quickSort ( lo, mi ); //对前缀递归排序
    quickSort ( mi + 1, hi ); //对后缀递归排序
    }

  • 但是,轴点在原始序列中未必存在。轴点存在的必要条件是,轴点在序列中所在的位置必定是其排序后所在的位置(就位)。

  • 在有序序列中,所有元素都是轴点。因此快排就是将所有元素逐个转换为轴点的过程。通过适当的交换,可使任一元素转换为轴点。

  • 轴点的构造:

    • 以首元素m为轴点为例,使用lo和hi两个指针,将序列分为三部分。L是从前往后的小于等于m的部分,G是从后往前的大于等于m的部分,U是未扫描的部分。lo和hi指向U的边界。

    • lo和hi向中间扫描,最终重合的位置就是m作为轴点所在的位置。

  • 具体的,在算法进行的开始,先去除m并备份。这样原来m的位置就空闲了,并由lo指向。

  • 然后hi开始扫描,遇到大于等于m的就越过,遇到小于m的就将其移至lo指向的空闲位置。然后改为lo扫描,hi空闲。

  • 最后扫描完成后,将备份的m移入空闲位置。

  • 时间复杂度最好O(nlog n),最坏O(n^2),平均O(nlog n)。
  • 快速排序的变种:
  • 同样的将整个序列分为四部分,只不过待处理部分U在最后端,而P也不需要取出备份。
  • k指针从头后移,遇到大于等于轴点的元素就只后移,相当于将该元素归入G。遇到小于轴点的元素,则与G中的首元素交换位置,相当于将该元素归入L,然后再后移。
  • 最后U的规模为0时,将位于序列首端的轴点P与L中的最后一个元素交换位置。
复制代码
template <typename T> //轴点构造算法:通过调整元素位置构造区间[lo, hi)的轴点,并返回其秩
Rank Vector<T>::partition ( Rank lo, Rank hi ) { //版本C
   swap ( _elem[lo], _elem[ lo + rand() % ( hi - lo ) ] ); //任选一个元素与首元素交换
   T pivot = _elem[lo]; //以首元素为候选轴点------经以上交换,等效于随机选取
   int mi = lo;
   for ( int k = lo + 1; k < hi; k++ ) //自左向右扫描
      if ( _elem[k] < pivot ) //若当前元素_elem[k]小于pivot,则
         swap ( _elem[++mi], _elem[k] ); //将_elem[k]交换至原mi之后,使L子序列向右扩展
   swap ( _elem[lo], _elem[mi] ); //候选轴点归位
   return mi; //返回轴点的秩
}

2、选取

  • 众数:这里指的是出现次数超过序列长度一半以上的元素。

  • 这种定义下,如果存在众数,则其必然也是中位数。

  • 减而治之:

    • 若在向量A的前缀P(P长度为偶数)中,元素x出现的次数恰占半数,则A有众数仅当,对应的后缀A --Р有众数m,且m就是A的众数。
    • 若x= m,则在排除前缀P之后,m与其它元素在数量上的差距保持不变。
    • 若x ≠ m,则在排除前缀Р之后,m与其它元素在数量上的差距不致缩小。
  • 用一个计数器记录众数的候选者与其他元素的数量差。

    template T majEleCandidate ( Vector A ) { //选出具备必要条件的众数候选者
    T maj; //众数候选者
    // 线性扫描:借助计数器c,记录maj与其它元素的数量差额
    for ( int c = 0, i = 0; i < A.size(); i++ )
    if ( 0 == c ) { //每当c归零,都意味着此时的前缀P可以剪除
    maj = A[i]; c = 1; //众数候选者改为新的当前元素
    } else //否则
    maj == A[i] ? c++ : c--; //相应地更新差额计数器
    return maj; //至此,原向量的众数若存在,则只能是maj ------ 尽管反之不然
    }

  • 选取的通用算法:

  • 选取的目标是,取出序列中经排序后秩为k的元素。

  • quickSelect():

    • 借鉴快排的思想,如果轴点的秩恰好为k,则直接返回。
    • 如果轴点的秩不是k,但可通过与轴点的秩比较,得出k是在L中还是在G中。

点击链接数据结构算法------排序算法解析阅读原文

相关推荐
2601_962218614 小时前
万象生鲜系统业财一体化底层打通技术自动生成经营账单
大数据·数据库·人工智能·python·算法
吞下星星的少年·-·5 小时前
The 2026 ICPC Asia East Continent Online Contest (II)(构造)
数据结构·算法
stolentime6 小时前
洛谷P10515 转圈题解
c++·算法·数学建模·贪心算法
和裕7 小时前
蜂窝板 vs 七层瓦楞重型纸箱:大件工业设备运输性能与成本全对比
大数据·运维·网络·人工智能·算法
衡石科技7 小时前
Data_Agent记忆机制与经验复用衡石分析智能体会话记忆与长期学习技术解析
人工智能·科技·学习·算法·企业级bi
Msshu1238 小时前
2~5串锂电快充优选|XSP36 Type‑C升压/升降压快充管理芯片
数据结构·随机森林·贪心算法·排序算法·线性回归·启发式算法
shirsl9 小时前
算法 Day 2 滑动窗口 + 栈 / 单调栈
开发语言·python·算法
土司大王10 小时前
LeetCode hot100 回溯专题总结:Java 通用模板、决策树模型
java·算法·leetcode·决策树
2601_9622186110 小时前
万象生鲜系统订单全生命周期状态同步技术实现业务可视
大数据·数据库·人工智能·python·算法
那年窗外下的雪.10 小时前
AIDC 学习日志|第 22 天|All-Active/Single-Active 故障演练设计
服务器·网络·学习·算法·哈希算法