排序算法总结

【C++】排序算法 冒泡排序、插入排序、选择排序、希尔排序、堆排序、归并排序、快速排序、计数排序、基数排序、桶排序、外排序 阅读详情

内部串行排序算法

一、比较策略算法

1、冒泡排序
稳定性:稳定
思想:每次调用,都会至少有一个元素就位,整体复杂度呈现算术级数的形式。若一次调用过程没有发生元素交换,则说明所有元素就位,最差和最理想情况下的复杂度为O(n2)O(n^2)O(n2)和O(n)O(n)O(n),平均复杂度为O(n2)O(n^2)O(n2)。
(1)基础版本:

bool bubble(Rank lo, Rank hi){
    bool sorted = true;
    while(++lo < hi){
        if(Array[lo-1] > Array[lo]) {
            sorted = false;
            int holder = Array[lo-1];
            Array[lo-1] = Array[lo];
            Array[lo] = holder;
        }
    }
    return sorted;
}
void bubbleSort(Rank lo, Rank hi){
    while(!bubble(lo,hi--));
}

(2)优化版本:面对后缀部分元素已经就位的情况,原先的算法仍然会进行比较,因此可从此处着手改进,方法是记录上一次扫描交换进行的最后一次交换位置,将hi更新为这个值, 减少不必要的比较次数,最差和最理想情况复杂度依然是O(n2)O(n^2)O(n2)和O(n)O(n)O(n)。

bool bubble(Rank lo, Rank hi){
    Rank last = lo ;
    while(++lo < hi){
        if(Array[lo-1] > Array[lo]) {
            last = lo;
            int holder = Array[lo-1];
            Array[lo-1] = Array[lo];
            Array[lo] = holder;
        }
    }
    return last;
}
void bubbleSort(Rank lo, Rank hi){
    while(lo< bubble(lo,hi));
}

优化版本和初始版本的对比如下图所示:
在这里插入图片描述
2、选择排序
(1)思想:依次从待排序序列中选出最小的元素放入排序序列。冒泡排序也可以看成是一种选择排序,但其最坏情况下需要O(n2)O(n^2)O(n2),元素在转移至最终位置前往往要经过多次位置交换,选择排序则是一次交换直接将元素移动到目标位置。
(2)实现:

void selectionSort(Rank lo,Rank hi){
    Rank i,j,smallest;
    for( i = 0;i<(hi-lo-1);i++){
        smallest = i;
        for(j = i+1;j<hi;j++)
            if(Array[j]<Array[smallest]) smallest = j;
        int swap = Array[smallest];
        Array[smallest] = Array[i];
        Array[i] = swap;
    }
}

(3)性能:
空间复杂度:O(1)
在所有情况下时间复杂度:O(n^2),但其主要消耗于比较操作,冒泡排序则是主要消耗于交换操作,因此选择排序的性能要较冒泡排序高。
稳定性:稳定

(4)能否对比较操作做进一步改进?
sure.

3、插入排序
(1)思想:
使用列表进行组织(不能使用向量), 方式可类比抽扑克牌在手中排好序
(2)实现:
(3)性能:
1、时间复杂度:
最好情况下O(n)O(n)O(n),最坏和平均情况下O(n2)O(n^2)O(n2);
为求平均情况的时间复杂度,需假设各元素取值遵守均匀独立分布,采用后向分析(backward analysis)求每次插入平均需要的比较次数。
当L(r)完成插入后,是插入到了列表的什么地方呢?因为各元素取值均匀独立分布,因此,每个位置的可能性均为1/(r+1)1/(r+1)1/(r+1),而从后到前所需的比较次数从1到r递增。
因此比较成本可表示为
[0+1+...+r]/(r+1)+1=r/2+1[0+1+...+r]/(r+1)+1 = r/2+1[0+1+...+r]/(r+1)+1=r/2+1,
和前缀长度呈线性关系。
将每个元素的比较成本相加,可得整体的比较成本为:
[0+1+...+(n−1)]/2+1=O(n2)[0+1+...+(n-1)]/2+1 = O(n^2)[0+1+...+(n−1)]/2+1=O(n2)

2、空间复杂度:O(1)O(1)O(1)
3、稳定性:稳定

(4)插入排序与逆序对
逆序对:两个元素,左侧的元素大于右侧,则称这两个元素构成了一个逆序对。
在插入排序中,设待插入结点为P,其在排好序的序列中逆序对的个数i(P)i(P)i(P)就是其在插入过程中需要经过的比较次数。
因此,整个序列中的逆序对数∑P(i)\sum_P(i)∑P​(i),即排序过程中比较次数总和,加上元素插入的时间总和O(n)O(n)O(n)即是插入排序总共所花费的时间。
在最好情况下,无逆序对,所有元素都是顺序输入的。
而在最坏情况下,任何一对元素都是逆序对。
可以将插入排序看成是将逆序对逐渐修复的过程,因此插入排序输入对“输入敏感的”排序算法。

4、比较策略排序算法的下界:
基于比较策略的算法的比较过程可用一颗二叉树来表示,最坏时间复杂度取决于树的深度。
高度为h的二叉树,叶结点数目小于等于2^h, 排序算法的叶结点<=n,因此排序算法的树高h> =log2n ,因此基于比较策略的排序算法的复杂度下界为log(n)log(n)log(n)。

二、 分治策略算法

1、归并排序
最好和最坏的情况下,复杂度都为O(nlogn)O(nlogn)O(nlogn),稳定。
(1)思想:将待排序的序列一分为二( O(1)O(1)O(1) ),对子序列递归排序( 2∗T(n/2)2*T(n/2)2∗T(n/2)),合并有序子序列(merge)。
(2)实现:

void merge(Rank lo,Rank mid , Rank hi){
    //A指向区间的起点
    int * A = Array + lo;
    //将向量的前半段复制到新开辟的空间中
    int lb = mid - lo ;int *B = new int[lb];
    for(int i = 0;i<lb;i++)B[i] = A[i];
    //C指向区间的后半段,C并不需要另辟空间缓存
    int lc = hi - mid;
    int * C = Array + mid;
    /*
     每次比较B,C两个子向量当前的首元素,
     取出其中更小的项,放入到A中
     j或k每次其中一个会加1,初始j+k = 0,最终j+k = n。
     因此迭代最多只会进行n次,merge算法时间复杂度为O(n)
     */
    for(Rank i =0,j=0,k=0;(j<lb)||(k<lc);){
        if((j<lb)&&((k>=lc)||(B[j]<=C[k]))) A[i++] = B[j++];
        if((k<lc)&&((j>=lb)||(C[k]< B[j]))) A[i++] = C[k++];
    }
    delete []B;
}
void mergeSort(Rank lo,Rank hi){
    if((hi - lo)<2 )return ;
    int mid = (hi + lo) >> 1 ;
    mergeSort(lo, mid);
    mergeSort(mid, hi);
    merge(lo,mid,hi);
    
    
}

因为merge算法的时间复杂度为O(n)O(n)O(n)(见代码注释),
因此归并排序递推式为:
T(n)=2∗T(n/2)+O(n)T(n)=2*T(n/2)+O(n)T(n)=2∗T(n/2)+O(n)
解得
T(n)=O(nlogn)T(n)=O(nlogn)T(n)=O(nlogn)

2、快速排序
(1)与归并排序的区别:
相同点:和归并排序一样,都是将两个排好序的子序列合二为一。
不同点:
1、对两个要合并的序列,快速排序要求Smax(L)<= Smin( R),不用merge
2、归并排序能保证划分出来的两个子任务彼此规模相当,而快速排序则不能,具体取决于候选轴点的选取
(2)轴点转化算法:

/*
将候选元素转化为轴点,方法:
将候选轴点“取出”,原位置成为“空闲单元”,
设lo与hi两个指针,初始指向序列的首元素和末元素,
hi向左移动,直到hi指向的元素比候选轴点小,则将其放入当前的“空闲单元”,hi指向的位置成为新的“空闲单元”;
lo向右移动,直到指向的元素比候选轴点大,~。
lo和hi交替移动,直到lo和hi相遇,则其位置就是轴点所在,将候选元素放入。
*/
Rank partition(Rank lo,Rank hi){
    //随机选取候选轴点
       int seq = rand()%(hi-lo) + lo;
       Rank n = Array[seq];
       Array[seq] = Array[lo];
       Array[lo] = n;
       Rank pivot = Array[lo];
    //轴点转化
    while(lo<hi){
        while((lo<hi)&&(pivot<=Array[hi]))hi--;
        Array[lo] = Array[hi] ;
        while((lo<hi)&&(pivot>=Array[lo]))lo++;
        Array[hi] = Array[lo] ;
    }
    Array[lo] = pivot;
    return lo;
}
void quicksort(Rank lo,Rank hi){
    if(hi-lo<2) return ;
    Rank mi = partition(lo,hi);
    quicksort(lo, mi);
    quicksort(mi+1, hi);
}

(3)性能分析
1、稳定性:不稳定,在轴点构造的过程中可能会颠倒元素的次序。
2、空间复杂度:可以就地实现,只需要维护常数个指针,空间复杂度O(1)
3、时间复杂度:
最优性能:每次选取的轴点都能讲序列均衡划分,此时:
T(n)=2∗T((n−1)/2)+O(n)=O(nlogn)T(n) = 2*T((n-1)/2) + O(n) = O(nlogn)T(n)=2∗T((n−1)/2)+O(n)=O(nlogn)
最差性能:每次轴点选取的都是最大/最小的元素,此时
T(n)=T(n−1)+T(0)+O(n)=O(n2)T(n) = T(n-1)+T(0)+O(n) = O(n^2)T(n)=T(n−1)+T(0)+O(n)=O(n2)
平均性能:
设序列中所有元素都是均匀独立分布,设选取的候选轴点最终的秩为k,则性能表示如下:
T(n)=(n+1)+(1/n)×T(n)=(n+1)+(1/n)\timesT(n)=(n+1)+(1/n)× ∑k=0n−1[T(k)+T(n−k−1)]\sum_{k=0}^{n-1} [T(k)+T(n-k-1)]∑k=0n−1​[T(k)+T(n−k−1)]
化简得到:
T(n)/(n+1)=2/(n−1)+2/n+T(n−2)/(n−1)T(n)/(n+1) = 2/(n-1) + 2/n +T(n-2)/(n-1)T(n)/(n+1)=2/(n−1)+2/n+T(n−2)/(n−1)

可将T(n)/(n+1)看成S(n),T(n-2)/(n-1)看成S(n-2),由此递推…构成调和级数
调和级数与自然对数logN同阶,因此快速排序的平均运行时间不超过O(nlogn)O(nlogn)O(nlogn)

(4)优化
快速排序算法的优化可以从两方面考虑:
1、优化候选轴点选取: 众数
2、优化轴点构造算法

(5)优化轴点选取
1、众数选取

4、希尔排序

三、 散列算法

1、桶排序

2、基数排序

3、奇数排序

四、 优先级队列

1、堆排序

2、锦标赛排序

https://play.google.com/apps/test/RQFlordB7z8/ahAIGJVrcSQNYxHGIYbG31j5ctZzYMIhwLHRyBXkaNfF1hWjOsI-P0oBIeGy-R0igQciAypFSaAdXXFhfEGOw_48xy

排序算法:稳定的排序算法 元素,并围绕主元对列表进行分区,将较小的元素放入低数组中,将所有较大的元素放入高数组中。然后,我们对他们的第十位的值进行排序。因此,我们可以对任意大小的列表进行排序,而无需在冒泡排序中使用任何额外的空间。我们可以说,子问题可以被视为对数组的一部分进行排序,从任何索引 s(start) 开始,到任何索引 e(end) 结束。正如我们上面所讨论的,最大堆是一个完全二叉树,其中每个内部节点中的值都大于或等于该节点的子节点中的值。此外,每次迭代后,已排序子数组的大小都会增加,而未排序子数组的大小会减少。 阅读详情

相关推荐

八种排序算法

偶尔有看到排序算法,想起来大学里老师也有讲授过冒泡排序、快速排序等,不过现在已经没什么概念,一查发现排序算法有八种,有的甚至连名字都没听过,感概平时看的少。既然已经看到了,就干脆了解下基础概念,避免在后续学习途中,出现一看就懵逼的情况。   冒泡排序 冒泡排序是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。走访数列的工作是重复地进行直到...

dobat的博客 3348

整理的8种排序算法的总结和比较

快速排序是一个就地排序,分而治之,大规模递归的算法。从本质上来说,它是归并排序的就地版本。快速排序可以由下面四步组成。 (1) 如果不多于1个数据,直接返回。 (2) 一般选择序列最左边的值作为支点数据。 (3) 将序列分成2部分,一部分都大于支点数据,另外一部分都小于支点数据。 (4) 对两边利用递归排序数列。 快速排序比大部分排序算法都要快。尽管我们可以在某些特殊的情况下写出比快速排序快的算法,但是就通常情况而言,没有比它更快的了。快速排序是递归的,对于内存非常有限的机器来说,它不是一个好的选择。

千丈之松的专栏 1999

排序算法总结及C++实现

文章目录1 引入 认识时间复杂度2 补充 对数器3 排序算法分析3.1 基于比较的排序3.1.1 冒泡排序3.1.2 选择排序3.1.3 插入排序3.1.4 归并排序补充题目 小和问题补充题目 逆序数3.1.5 快速排序3.1.6 堆排序3.2 非基于比较的排序3.2.1 计数排序3.2.2 桶排序3.2.3 基数排序4 排序总结4.1 稳定性4.2 工程中的综合排序算法4.3 有关排序...

李滚滚的博客 2222

排序算法(二)选择&插入

选择排序 思路: 在一组数中找到最大者后,拿出,再去该组数中找到最大者,直到空 有点像 冒泡排序 但比冒泡排序少了反复比较的步骤 找到最大者后直接放在了最后的位置,而不是一步步交换到该位置 每次在未排序部分找到最大元素,放到已排序部分的最前端 ...

m0_49404210的博客 272

排序算法 - 面试中的排序算法总结

排序算法总结 查找和排序算法是算法的入门知识,其经典思想可以用于很多算法当中。因为其实现代码较短,应用较常见。所以在面试中经常会问到排序算法及其相关的问题。但万变不离其宗,只要熟悉了思想,灵活运用也不是难事。 一般在面试中最常考的是快速排序和归并排序,并且经常有面试官要求现场写出这两种排序的代码。对这两种排序的代码一定要信手拈来才行。还有插入排序、冒泡排序、堆排序、基数排序、桶排序等。面试官对

从零开始 2982

基于串行计算的排序算法实证分析 (2010年)

文章简述了排序算法的研究现状,着重分析地址映射计数排序的基本思想,提出了相异密度因子的概念,以快速排序为参照系,通过理论分析和实验数据的实证分析验证,表明相异密度因子是应用领域选择合适的排序算法的重要参考因素,最后指出了排序算法的研究新趋势。

排序专题——3.插入排序

插入排序

MarkBeY博客 310

别再被SpringerLink虐了!手把手教你搞定LaTeX源文件提交(附正确文件顺序和类型选择)

本文详细解析了SpringerLink投稿系统中LaTeX源文件提交的常见问题与解决方案,包括文件打包、类型选择和顺序排列等关键步骤。通过实战经验,帮助科研人员避开隐形陷阱,一次性完成LaTeX提交,提升投稿效率。特别针对`.bst`和`.cls`文件的正确处理提供了专业指导。

weixin_42522964的博客 445

九大排序算法再总结

如果要转载,需要注明出处: http://blog.youkuaiyun.com/xiazdong 本文是 http://blog.youkuaiyun.com/xiazdong/article/details/7304239 的补充,当年看了《大话数据结构》总结的,但是现在看了《算法导论》,发现以前对排序的理解还不深入,所以打算对各个排序的思想再整理一遍。 本文首先介绍了基于比较模型的排序算法,

xiazdong 31万+

[Python]:热血传奇-Wzl,Wzx的解析

首先我们要了解,wzl与wzx的对应关系,wzx里面存的是每张二进制图片数据在wzl中的偏移量,所以取到wzx中的偏移数据就可以取到wzl每张图片数据,其实就这么简单。结构体为 [Byte][Byte][Byte][Byte][short][short][short][short][int]-读取44至48字节代表为,[wzx中偏移值总数量] [int类型] [4字节]-根据在wzx中取得的偏移值总数量,每张图片偏移值在wzl中取图片数据。2.[取wzl中图片偏据]:根据wzx中取得数据对[

qq_36138506的博客 3447

深入解析6T SRAM的读写机制与性能优化

本文深入解析了6T SRAM的基本结构与核心工作原理,详细阐述了其读写操作的具体时序与机制。文章重点探讨了在先进工艺下面临的读写稳定性、写入能力等性能挑战,并系统介绍了写入辅助与读取辅助等关键优化技术,旨在提升SRAM的可靠性与整体性能。

weixin_29205061的博客 1225

「排序算法」十大经典排序算法

文章目录十大经典排序算法一、冒泡排序二、选择排序三、插入排序四、希尔排序五、归并排序六、快速排序七、堆排序八、计数排序九、桶排序十、基数排序 引用网站:菜鸟教程十大经典排序 十大经典排序算法 排序算法图片总结(图片来源于网络) 一、冒泡排序 冒泡排序(Bubble Sort)也是一种简单直观的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢

秋天,黄叶坠地,凉风有信。 6428

python利用IQR方法与3σ方法进行异常值处理(含代码)

python利用IQR方法进行异常值处理

weixin_46713695的博客 2031

稳定排序算法有哪些

稳定排序算法有哪些 相信您已经掌握了很多种排序算法,比如冒泡排序、插入排序、希尔排序、选择排序等。这些排序算法中,有些是 “稳定” 的,有些是 “不稳定” 的。 给定的待排序序列中,经常会包含相同的元素,例如: 3 1 2 4 2 此序列中包含两个元素 2,为了区分它们,我们分别称它们为 “红 2” 和 “绿 2”。 评价一个排序算法是否稳定,是指该算法完成排序的同时,是否会改变序列中相同元素的相对位置。例如,上面序列中红 2 和绿 2 的相对位置是:红 2 位于绿 2 的左侧,或者说绿 2 位于红 2

ccc369639963的博客 1万+

移动端实战指南:深入理解 & 接入 IAB OMSDK

OMSDK(OpenMeasurementSDK)是IABTechLab推出的标准化测量工具,用于统一移动端/原生App广告的可见性和验证流程。其核心包括Native库(采集设备数据)和OMID JavaScript层(实现通信),通过标准化接口让开发者只需接入一套SDK即可兼容多个测量厂商,减少冲突和性能损耗。v1.4版本强化了对CTV和原生App场景的支持,而v1.5新增了画中画检测等功能。集成流程需通过IAB技术实验室注册下载,并遵循严格的命名空间规则。测试阶段需嵌入验证脚本并通过指定工具验证

帅次的博客 1187

有道龙虾LobsterAI vs. OpenClaw:对比与安装部署攻略

LobsterAI是"中国版OpenClaw",更注重易用性和中文场景适配;OpenClaw是技术极客的玩具,需要大量命令行操作。

lpfasd123的博客 2395

【排序算法】排序算法总结

排序算法总结,将排序算法的分类、稳定性和特点进行一个总结,并附有跳转到对应详解的链接,方便大家学习

weixin_52811588的博客 984

在isaacsim仿真系统进行遥操作(设备是quest3):怎么让遥操作设备(quest3)在Isaac sim系统中控制机械臂并把其中的参数传输出来??

我长期专注 Python 爬虫工程化实战,主理专栏 👉 《Python爬虫实战》:从采集策略到反爬对抗,从数据清洗到分布式调度,持续输出可复用的方法论与可落地案例。内容主打一个“能跑、能用、能扩展”,让数据价值真正做到——抓得到、洗得净、用得上。

**My Coding Family** 940

十大经典排序算法

十种常见的排序算法可分为以下两大类: 比较类排序:通过比较来决定元素间的相对位置,由于其时间复杂度不能突破O(nlogn),因此也称为非线性时间比较类排序。 非比较类排序:不通过比较来决定元素间的相对位置,它可以突破基于比较排序的时间下限,以线性时间运行,因此也称为线性时间非比较类排序。 时间复杂度: 从序列的初始状态到经过排序算法的变换移位等操作变到最终排序好的结果状态的过程所花费的时间度量。

qq_40896594的博客 3672

YOLOv11 TensorRT极致加速:C++部署性能优化完全指南

购买即可解锁300+YOLO优化文章,并且还有海量深度学习复现项目,价格仅需两杯奶茶的钱,别人有的本专栏也有!

LXY_LOVE36的博客 118

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

什么是排序算法?常见的排序算法有哪些?

计数排序适用于数据范围较小且已知的情况,其时间复杂度为线性时间,非常适合处理小范围内的数据排序。基数排序适用于整数排序,特别是当数据范围较大但数据量适中时。它通过多次应用计数排序来实现多轮排序,从而克服了传统排序算法在处理大范围数据时的效率问题。

破损的天堂鸟博客 1226

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

十大排序算法

算法稳定性:单次比较后,两个值相等的邻近元素的位置在排序后,相对位置没有改变。

一名想做出点成就的后端~ 1429

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

排序算法详解

排序算法是计算机科学中最基础也最重要的算法之一。它将一组数据(例如数字列表、字符串集合)按照特定的顺序(升序或降序)重新排列。高效的排序算法对于优化其他算法(如搜索和合并算法)的效率至关重要。

m0_54069809的博客 1169
上一篇: Games101笔记:几何(二):曲线
下一篇: Games104 gameplay系统笔记
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值