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

目录

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中elseA[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.mzph.cn/news/848339.shtml

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

相关文章

HarmonyOS鸿蒙-DevEco Studio工具

一、官网下载DevEco Studio工具地址 文章内容: 1、下载工具 2、运行项目 3、安装启动器 https://developer.harmonyos.com/cn/develop/deveco-studio/https://developer.harmonyos.com/cn/develop/deveco-studio/ 下载不同平台工具目录 : 二、 安装DevEco Studio工具 安装的配置…

如何令谷歌浏览器搜索时,子页面使用新窗口,而不是迭代打开

1 问题描述 工作相关需要常用谷歌浏览器&#xff0c;但是现在设置就是每次搜索后&#xff0c;点击搜索结果进去之后&#xff0c;都会覆盖掉原来的父页面&#xff0c;也就是如果我看完了这个子页面的内容&#xff0c;关掉的话&#xff0c;我就需要重新google.com来一遍。。。很…

Dinky MySQLCDC 整库同步到 MySQL jar包冲突问题解决

资源&#xff1a;flink 1.17.0、dinky 1.0.2 问题&#xff1a;对于kafka相关的包内类找不到的情况 解决&#xff1a;使用 flink-sql-connector- 胖包即可&#xff0c;去掉 flink-connector- 相关瘦包&#xff0c;解决胖瘦包冲突 source使用 flink-sql-connector- 胖包&#…

Java【springBoot和springCould引入外部jar包】

在项目的研发过程中&#xff0c;我们经常需要导入外部系统提供的jar包&#xff0c;并且这种jar包并没有上传到开源的maven仓库&#xff0c;属于内部环境的包&#xff0c;那么应该如何添加呢&#xff1f; springBoot 1、首先&#xff0c;将你的 JAR 文件拷贝到项目的 resource…

基础数学-求平方根(easy)

一、问题描述 二、实现思路 1.题目不能直接调用Math.sqrt(x) 2.这个题目可以使用二分法来缩小返回值范围 所以我们在left<right时 使 mid (leftright)/21 当mid*mid>x时&#xff0c;说明right范围过大&#xff0c;rightright-1 当mid*mid<x时&#xff0c;说明left范…

使用Qt对word文档进行读写

目录 开发环境原理使用的QT库搭建开发环境准备word模板测试用例结果Gitee地址 开发环境 vs2022 Qt 5.9.1 msvc2017_x64&#xff0c;在文章最后提供了源码。 原理 Qt对于word文档的操作都是在书签位置进行插入文本、图片或表格的操作。 使用的QT库 除了基本的gui、core、…

JavaWeb1 Json+BOM+DOM+事件监听

JS对象-Json //Json 字符串转JS对象 var jsObject Json.parse(userStr); //JS对象转JSON字符串 var jsonStr JSON.stringify(jsObject);JS对象-BOM BOM是浏览器对象模型&#xff0c;允许JS与浏览器对话 它包括5个对象&#xff1a;window、document、navigator、screen、hi…

力扣hot100:138. 随机链表的复制(技巧,数据结构)

LeetCode&#xff1a;138. 随机链表的复制 这是一个经典的数据结构题&#xff0c;当做数据结构来学习。 1、哈希映射 需要注意的是&#xff0c;指针也能够当做unordered_map的键值&#xff0c;指针实际上是一个地址值&#xff0c;在unordered_map中&#xff0c;使用指针的实…

VXLAN技术

VXLAN技术 一、VXLAN简介 1、定义 VXLAN&#xff08;Virtual eXtensible Local Area Network&#xff09;&#xff1a;采用MAC in UDP&#xff08;User Datagram Protocol&#xff09;封装方式&#xff0c;是NVO3&#xff08;Network Virtualization over Layer 3&#xff09…

使用 Logback.xml 配置文件输出日志信息

官方链接&#xff1a;Chapter 3: Configurationhttps://logback.qos.ch/manual/configuration.html 配置使用 logback 的方式有很多种&#xff0c;而使用配置文件是较为简单的一种方式&#xff0c;下述就是简单描述一个 logback 配置文件基本的配置项&#xff1a; 由于 logba…

Vuforia AR篇(七)— 二维码识别

目录 前言一、什么是Barcode &#xff1f;二、使用步骤三、点击二维码显示信息四、效果 前言 在数字化时代&#xff0c;条形码和二维码已成为连接现实世界与数字信息的重要桥梁。Vuforia作为领先的AR开发平台&#xff0c;提供了Barcode Scanner功能&#xff0c;使得在Unity中实…

json和axion结合

目录 java中使用JSON对象 在pom.xml中导入依赖 使用 public static String toJSONString(Object object)把自定义对象变成JSON对象 json和axios综合案例 使用的过滤器 前端代码 响应和请求都是普通字符串 和 请求时普通字符串&#xff0c;响应是json字符串 响应的数据是…

MySQL换路径(文件夹)

#MySQL作为免费数据库很受欢迎&#xff0c;即使公司没有使用&#xff0c;自己也可以用。它是一个服务&#xff0c;在点击CtrlAltDelete选择任务管理器后&#xff0c;它在服务那个归类里。 经常整理计算机磁盘分类的小伙伴&#xff0c;如果你们安装了MySQL&#xff0c;并且想移…

插件:Plugins

一、安装网格插件

重大变化,2024软考!

根据官方发布的2024年度计算机技术与软件专业技术资格&#xff08;水平&#xff09;考试安排&#xff0c;2024年软考上、下半年开考科目有着巨大变化&#xff0c;我为大家整理了相关信息&#xff0c;大家可以看看&#xff01; &#x1f3af;2024年上半年&#xff1a;5月25日&am…

高并发短视频系统设计:架构、存储与性能优化全解

1. 系统概况与需求分析 1.1 短视频系统简介 当前短视频行业的快速发展&#xff0c;加上用户对高清、流畅观看体验的需求不断提升&#xff0c;对系统的并发处理能力、视频处理速度、存储效率等多方面都提出了极高的要求。那么&#xff0c;我们首先需要了解一个完整的短视频系统…

msvcp140.dll是什么dll文件?msvcp140.dll文件的丢失要怎么去修复?

msvcp140.dll是什么dll文件&#xff1f;一般会问出这种问题的人&#xff0c;都是遇到了msvcp140.dll丢失的情况了&#xff0c;这时候你的一些程序是打不开的&#xff0c;你需要修复好msvcp140.dll文件才可以正常的打开程序&#xff0c;今天我们就来了解一下msvcp140.dll这文件&…

hcia datacom学习(11):vlan基础配置

1.vlan作用 &#xff08;1&#xff09;限制广播域&#xff1a;广播被限制在vlan内&#xff0c;不会在vlan间转发 &#xff08;2&#xff09;提高安全性&#xff1a;不同vlan的报文在传输时是相互隔离的 &#xff08;3&#xff09;灵活构建&#xff1a;交换机可以把不同终端分…

【实物+仿真设计】基于单片机的物流皮带传输监控系统设计

《基于单片机的物流皮带传输监控系统设计 实物仿真》 整体功能&#xff1a; 本设计采用以单片机为核心控制器&#xff0c;以及传感器检测部分作为输入部分&#xff0c;以报警、显示、洒水、排烟、电机停止模块作为输出部分&#xff0c;构成整个物流皮带传输监控系统。 本设计…

【Linux】信号(一)

信号我们将从信号产生&#xff0c;信号的保存&#xff0c;信号处理分别进行讲解~ 至少大思路是这样。开始之前还要进行一些基础知识的铺垫。 目录 从生活中提炼一些结论&#xff1a;信号概念的一些储备&#xff1a;信号产生&#xff1a;一、kill指令&#xff1a;二、键盘组合键…