数据结构复习指导之归并排序、基数排序、计数排序

news2025/1/11 12:41:46

目录

1.归并排序

1.1二路归并操作的功能

1.2算法思想

1.3代码分析

1.4性能分析

2.基数排序

2.1算法思想

2.2基数排序的中间过程的分析

2.3性能分析

3.计数排序

3.1算法思想

3.2代码分析

3.3性能分析

知识回顾


1.归并排序

1.1二路归并操作的功能

归并排序与上述基于交换、选择等排序的思想不一样,归并的含义是将两个或两个以上的有序表合并成一个新的有序表

假定待排序表含有n个记录,则可将其视为n个有序的子表,每个子表的长度为1,然后两两归并,得到\left \lceil n/2 \right \rceil个长度为 2 或 1 的有序表;

继续两两归并……如此重复,直到合并成一个长度为n的有序表为止,这种排序算法称为二路归并排序。

图8.9所示为二路归并排序的一个例子,经过三趟归并后合并成了有序序列。

1.2算法思想

Merge()的功能是将前后相邻的两个有序表归并为一个有序表。

设两段有序表 A[low..mid]、A[mid+1..high]存放在同一顺序表中的相邻位置,先将它们复制到辅助数组 B中。

每次从B的两段中取出一个记录进行关键字 的比较,将较小者放入中,当B中有一段的下标超出其对应的表长(即该段的所有元素都已复制到中)时,将另一段的剩余部分直接复制到A中。

1.3代码分析

算法如下:

ElemType *B=(ElemType *)malloc((n+1)*sizeof(ElemType));//辅助数组 B
void Merge(ElemType A[],int low,int mid,int high){
//表A的两段A[low..mid]和a[mid+1..high]各自有序,将它们合并成一个有序表
    int i,j,k;
    for(k=low;k<=high;k++)
        B[k]=A[k];                //将A中所有元素复制到B中
    for(i=low,j=mid+1,k=i;i<=mid && j<=hiqh;k++){
        if(B[i]<=B[j])            //比较B的两个段中的元素
            A[k]=B[i++];          //将较小值复制到A中
        else
            A[k]=B[j++];
    }
    while(i<=mid)  A[k++]=B[i++]; //若第一个表未检测完,复制
    while(j<=high) A[k++]=B[j++]; //若第二个表未检测完,复制
}

注意:在上面的代码中,最后两个 while 循环只有一个会执行。 

一趟归并排序的操作是,调用\left \lceil n/2h \right \rceil次算法 merge(),将 L[1..n]中前后相邻且长度为h的有序段进行两两归并,得到前后相邻、长度为2h的有序段,整个归并排序需要进行\left \lceil log_{2}n \right \rceil趟。

递归形式的二路归并排序算法是基于分治的,其过程如下。

  • 分解:将含有n个元素的待排序表分成各含n/2个元素的子表,采用二路归并排序算法对两个子表递归地进行排序。
  • 合并:合并两个已排序的子表得到排序结果。
void MergeSort(ElemType A[],int low,int high){
    if(low<high){
        int mid=(low+high)/2;    //从中间划分两个子序列
        MergeSort(A,low,mid);    //对左侧子序列进行递归排序
        MergeSort(A,mid+1,high); //对右侧子序列进行递归排序
        Merge(A,low,mid,high);   //归并
    }
}

1.4性能分析

二路归并排序算法的性能分析如下:

空间效率:Merge()操作中,辅助空间刚好为n个单元,因此算法的空间复杂度为O(n)。


时间效率:每趟归并的时间复杂度为 O(n),共需进行\left \lceil log_{2}n \right \rceil趟归并,因此算法的时间复杂度为O(nlog_{2}n)


稳定性:由于 Merge()操作不会改变相同关键字记录的相对次序,因此二路归并排序算法是一种稳定的排序算法


适用性:归并排序适用于顺序存储和链式存储的线性表

注意:一般而言,对于N个元素进行 k 路归并排序时,排序的趟数 m 满足K^{m}=N,从而m=log_{k}N,又考虑到 m 为整数,因此m=\left \lceil log_{k}N \right \rceil。这和前面的二路归并排序算法是一致的。

2.基数排序

2.1算法思想

基数排序是一种很特别的排序算法,它不基于比较和移动进行排序,而基于关键字各位的大小进行排序。

基数排序是一种借助多关键字排序的思想对单逻辑关键字进行排序的方法。

假设长度为 n 的线性表中每个结点 a_{j}的关键字由 d 元组(k^{d-1}_{j},k^{d-2}_{j},...,k^{1}_{j},k^{0}_{j})组成,满足(0≤j<n,0≤i≤d-1)。

其中k^{d-1}_{j}为最主位关键字,k^{0}_{j}为最次位关键字。

为实现多关键字排序,通常有两种方法:

  • 第一种是最高位优先(MSD)法,按关键字位权重递减依次逐层划分成若干更小的子序列,最后将所有子序列依次连接成一个有序序列;
  • 第二种是最低位优先(LSD)法,按关键字位权重递增依次进行排序,最后形成一个有序列。

下面描述以 r 为基数的最低位优先基数排序的过程,在排序过程中,使用 r 个队列 Q0,Q1…Qr-1。基数排序的过程如下:

对 i=0,1.,d-1,依次做一次分配收集(其实是一次稳定的排序过程)。

分配:开始时,把Q0,Q1…Qr-1各个队列置成空队列,然后依次考察线性表中的每个结
a_{j} (j=0,1,…,n-1),若a_{j}的关键字k_{j}^{i}=k,就把a_{j}放进 Q_{k}队列中。

收集:把Q0,Q1…Qr-1各个队列中的结点依次首尾相接,得到新的结点序列,从而组成新的线性表。

2.2基数排序的中间过程的分析

通常采用链式基数排序,假设对如下10个记录进行排序:

每个关键字是 1000 以下的正整数,基数r=10,在排序过程中需借助 10 个链队列,每个关键字由3位子关键字构成--K¹K²K³,分别代表百位、十位和个位,一共进行三趟“分配”和“收集”操作。

第一趟分配用最低位子关键字K³进行,将所有最低位子关键字(个位)相等的记录分配到同一个队列,如图8.10(a)所示,然后进行收集操作。

第一趟收集后的结果如图 8.10(b)所示。

第二趟分配用次低位子关键字K²进行,将所有次低位子关键字(十位)相等的记录分配到同一个队列,如图 8.11(a)所示。

第二趟收集后的结果如图 8.11(b)所示。

第三趟分配用最高位子关键字K¹进行,将所有最高位子关键字(百位)相等的记录分配到同一个队列,如图8.12(a)所示,

第三趟收集后的结果如图 8.12(b)所示,至此整个排序结束。

2.3性能分析

基数排序算法的性能分析如下。

空间效率:一趟排序需要的辅助存储空间为r (r个队列:r个队头指针和r个队尾指针),但以后的排序中会重复使用这些队列,所以基数排序的空间复杂度为O(r)


时间效率

  • 基数排序需要进行 d趟“分配”和”收集”操作。
  • 一趟分配需要遍历所有关键字,时间复杂度为 O(n);
  • 一趟收集需要合并r个队列,时间复杂度为 O(r)。
  • 因此基数排序的时间复杂度为 O(d(n+r)),它与序列的初始状态无关

稳定性:每一趟分配和收集都是从前往后进行的,不会交换相同关键字的相对位置,因此基数排序是一种稳定的排序算法


适用性:基数排序适用于顺序存储和链式存储的线性表。 

3.计数排序

3.1算法思想

计数排序也是一种不基于比较的排序算法。

计数排序的思想是:对每个待排序元素x,统计小于x的元素个数,利用该信息就可确定x的最终位置。

例如,若有8个元素小于x,则x就排在第9号位置上。当有几个元素相同时,该排序方案还需做一定的优化。

注意:计数排序并不在统考大纲的范围内,但其排序思想在历年真题中多次涉及。

在计数排序算法的实现中,假设输入是一个数组 A[n],序列长度为 n,我们还需要两个数组:B[n]存放输出的排序序列,C[k]存储计数值。

用输入数组A中的元素作为数组C的下标(索引),而该元素出现的次数存储在该元素作为下标的数组C中。

3.2代码分析

算法如下: 

void CountSort (ElemType A[],ElemType B[],int n,int k){
    int i,C[k];
    for(i=0;i<k;i++)
        C[i]=0;              //初始化计数数组
    for(i=0;i<n;i++)         //遍历输入数组,统计每个元素出现的次数
        C[A[i]]++;           //C[A[i]]保存的是等于A[i]的元素个数
    for(i=1;i<k;i++)
        C[i]=C[i]+C[i-1];    //c[x]保存的是小于或等于x的元素个数
    for(i=n-l;i>=0;i--){     //从后往前遍历输入数组
        B[C[A[i]-1]]=A[i];   //将元素A[i]放在输出数组B[]的正确位置上
        C[A[i]]=C[A[i]]-1;
    }
}

第一个 for 循环执行完后,数组C的值初始化为 0。

第二个 for 循环遍历输入数组 ,若一个输入元素的值为 x,则将C[x]值加 1,该 for 循环执行完后,C[x]中保存的是等于x的元素个数。

第三个 for 循环通过累加计算后,C[x]中保存的是小于或等于x的元素个数。

第四个 for 循环从后往前遍历数组 A,把每个元素 A[i] 放入它在输出数组B的正确位置上。

若数组 A中不存在相同的元素,则 C[A[i]]-1 就是 A[i] 在数组 B 中的最终位置,这是因为共有 C[A[i]]个元素小于或等于 A[i]。

若数组A中存在相同的元素,将每个元素 A[i] 放入数组 B[] 后,都要将 C[A[i]]减 1,这样,当遇到下一个等于A[i]的输入元素(若存在)时,该元素就可放在数
组B中 A[i] 的前一个位置上。

假设输入数组A[ ]={2,4,3,0,2,3},第二个for 循环执行完后,辅助数组C的情况如图8.13(a)所示;

第三个 for 循环执行完后,辅助数组C的情况如图 8.13(b)所示。

图 8.13(c)至图 8.13(h)分别是第四个 for 循环每迭代一次后,输出数组B和辅助数组C的情况。

由上面的过程可知,计数排序的原理是:数组的索引(下标)是递增有序的,通过将序列中的元素作为辅助数组的索引,其个数作为值放入辅助数组,遍历辅助数组来排序。 

3.3性能分析

计数排序算法的性能分析如下。

空间效率:计数排序是一种用空间换时间的做法。

  • 输出数组的长度为n;
  • 辅助的计数数组的长度为 k,空间复杂度为 O(n+k)。
  • 若不把输出数组视为辅助空间,则空间复杂度为 O(k)。

时间效率

  • 上述代码的第1个和第3个for 循环所花的时间为 O(k),
  • 第2个和第4个 for 循环所花的时间为 O(n),
  • 总时间复杂度为 O(n+ k)。
  • 因此,当 k=O(n) 时,计数排序的时间复杂度为O(n);
  • 但当 k>O(nlog₂n)时,其效率反而不如一些基于比较的排序(如快速排序、堆排序等)。

稳定性:上述代码的第4个 for 循环从后往前遍历输入数组,相同元素在输出数组中的相对位置不会改变,因此计数排序是一种稳定的排序算法


适用性:计数排序更适用于顺序存储的线性表。计数排序适用于序列中的元素是整数且元素范围(0~k-1)不能太大,否则会造成辅助空间的浪费。

知识回顾

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1811400.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux LCD屏幕上电不显示

一、问题描述 LCD屏幕点不亮 二、相关配置 timing获取&#xff1a;&#xff08;1280x800) 最好的获取方式是通过询问LCD屏厂获得确切的时序参考值。其次或是从屏手册或者Driver IC手册中查找&#xff08;向屏厂索要这些文档&#xff09;。 至少需要从屏厂获得Width&#xff…

FL Studio21.2.8最新永久破解安装包下载,音乐创作神器免费下载

大家好&#xff01;今天我要和大家分享一个超棒的音乐制作软件——FL Studio21永久免费破解中文版下载&#xff01;&#x1f929; 作为一名音乐爱好者&#xff0c;我一直在寻找一款功能强大、操作简单的音乐制作工具。而FL Studio21正是我梦寐以求的宝藏&#xff01;&#x1f3…

这些维生素助帕友健康前行

&#x1f338;帕金森病&#xff0c;除了药物治疗&#xff0c;营养补充也是帮助患者缓解病情、提升生活质量的重要方式。今天&#xff0c;我们就来谈谈帕金森病患者应该补充的维生素。 &#x1f31f;首先&#xff0c;维生素B族对于帕金森病患者来说尤为重要。它们参与神经递质的…

【Linux】进程3——PID/PPID,父进程,子进程

在讲父子进程之前&#xff0c;我们接着上面那篇继续讲 1.查看进程 mycode.c makefile 我们在zs_108直接编译mycode.c&#xff0c;直接运行&#xff0c;然后我们转换另一个账号来查看这个进程 我们可以通过ps指令来查看进程 我们就会好奇了&#xff0c;第二行是什么&#xff…

LLM的基础模型6:Positional Encoding

大模型技术论文不断&#xff0c;每个月总会新增上千篇。本专栏精选论文重点解读&#xff0c;主题还是围绕着行业实践和工程量产。若在某个环节出现卡点&#xff0c;可以回到大模型必备腔调或者LLM背后的基础模型新阅读。而最新科技&#xff08;Mamba,xLSTM,KAN&#xff09;则提…

学fpga需要有C语言基础吗。完全0代码基础?

在开始前刚好我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「C语言的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区回复“888”之后私信回复“888”&#xff0c;全部无偿共享给大家&#xff01;&#xff01;&#xff01;作为FPGA开发者和FPGA实训负…

nvm 安装说明

1、下线nvm地址 https://nvm.uihtm.com/2、安装步骤 2.1、双击解压后的exe 2.2、选择I accept…&#xff0c;然后点击next 2.3、选择nvm安装位置,选择好后点击next 2.4、选择nodejs的安装位置&#xff0c;点击next&#xff0c;记住你的nodejs路径&#xff01;甚至可以复制这…

Kaggle命令行下载数据

Kaggle下载数据 从Kaggle网站下载数据&#xff0c;要么点击页面中的Download按钮&#xff0c;要么找到下面形式的命令 kaggle competitions download -c xxxxxxxx用命令行工具下载。 下载的前提&#xff1a;接受规则 在数据集的下方&#xff0c;往往有“接受规则”的选项&…

【网络安全的神秘世界】在Kali上轻松安装蚁剑详细教程

&#x1f31d;博客主页&#xff1a;泥菩萨 &#x1f496;专栏&#xff1a;Linux探索之旅 | 网络安全的神秘世界 | 专接本 下载源码&#xff1a;https://github.com/AntSwordProject/antSword 下载加载器&#xff1a;https://github.com/AntSwordProject/AntSword-Loader 往下…

Bosch力士乐控制器维修案例讲解

在工业自动化领域&#xff0c;伺服拧紧控制器扮演着至关重要的角色。它们精确控制拧紧力矩&#xff0c;确保产品质量的稳定性和可靠性。然而&#xff0c;当出现博世力士乐拧紧扳手控制器故障时&#xff0c;及时的维修和保养就变得尤为重要。【子锐机器人的维修测试平台是确保机…

刷题训练之分治归并

> 作者&#xff1a;დ旧言~ > 座右铭&#xff1a;松树千年终是朽&#xff0c;槿花一日自为荣。 > 目标&#xff1a;熟练掌握分治归并算法。 > 毒鸡汤&#xff1a;学习&#xff0c;学习&#xff0c;再学习 ! 学&#xff0c;然后知不足。 > 专栏选自&#xff1a;刷…

4.keepalived高可用

keepalived高可用 一、keepalived高可用介绍二、keepalived高可用设计1、两台haproxy负载均衡器配置一致2、在haproxy上分别安装keepalived3、配置keepalived实现高可用4、分别在两个调度器上查看浮动IP5、测试客户端通过浮动IP可正常访问业务6、模拟故障&#xff0c;将优先级高…

3个方法 介绍现货白银是如何操作的

很多朋友看到近期现货白银价格上涨得这么火热&#xff0c;他们也跟风入场开户&#xff0c;成为了白银投资者想去买卖白银。但是他们发现&#xff0c;看着走势涨涨跌跌&#xff0c;而自己却不会操作。下面我们就来讨论一下&#xff0c;现货白银是如何操作的。 看K线操作。我们打…

【菜狗学前端】在原生微信小程序使用腾讯地图API接口

一直想调用一下地图API接口什么的&#xff0c;刚好遇到了这个实验就浅浅研究写了一下&#xff0c;顺便总结一下给其他没太了解的人一点便利&#xff0c;希望能够对你有所帮助~ 如何引入、配置、使用、显示。 PS:要是嫌麻烦想要源码/有什么问题欢迎评论/私信&#xff0c;问题的话…

虹科案例|为什么PCAN MicroMod FD是数模信号转换的首选方案?

导读&#xff1a;精确的信号采集和转换是确保生产效率和质量的关键。虹科PCAN MicroMod FD系列模块&#xff0c;以其卓越的数模信号转换能力&#xff0c;为工程师们提供了一个强大的工具。本文将深入探讨如何通过虹科PCAN MicroMod FD系列模块&#xff0c;将模拟信号无缝转换为…

容器:现代计算的基础设施

人不走空 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌赋&#xff1a;斯是陋室&#xff0c;惟吾德馨 目录 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌…

15. 《C语言》——【如何动态内存开辟】

亲爱的读者&#xff0c;大家好&#xff01;我是一名正在学习编程的高校生。在这个博客里&#xff0c;我将和大家一起探讨编程技巧、分享实用工具&#xff0c;并交流学习心得。希望通过我的博客&#xff0c;你能学到有用的知识&#xff0c;提高自己的技能&#xff0c;成为一名优…

MySQL-----JOIN语句之左连接、右连接

接着上文我们将基于学生&#xff0c;课程&#xff0c;考试信息三个表对内连接的总结&#xff0c;我们再来对左右连接进行一个总结&#xff0c;三个表结构以及表内数据如下图所示&#xff1a; 左连接 为了便于展示左右连接的区别&#xff0c;我们在student表里插入了一位成员…

用英语介绍端午节,柯桥零基础英语培训

端午节 Dragon Boat Festival 中国传统节日&#xff0c;农历五月初五。相传古代诗人屈原在五月初五投江自杀&#xff0c;后人把这天作为节日纪念他。有划龙舟比赛、包粽子等风俗。 A traditional Chinese festival on the fifth day of the fifth lunar month. Legend has i…

2024苹果开发者大会:Siri 接上 ChatGPT,OpenAI苹果强强联合

一直在生成式AI战争中默默无闻的苹果终于憋不住了&#xff01; 北京时间6月11日凌晨1点&#xff0c;2024苹果WWDC全球开发者大会在苹果总部 Apple Park开幕。Day 1的发布会在介绍完各个操作系统的更新后&#xff0c;一半的时间都留给了本次WWDC的重头戏——苹果AI&#xff08;…