14 归并排序和其他排序

1.归并排序
2.计数排序

1. 归并排序

基本思想

建立在归并操作上的一种排序算法,采用分治法的一个典型应用。将已有序的子序列合并,得到完全有序的序列,将两个有序表合成一个称为二路归并。
在这里插入图片描述

原数组无序,以中间分割为两个数组,仍然无序,继续分割每个区间,直到两个数时,可以使它有序,然后利用两个数组的合并,将小的尾插,不断的就可以排序之前分割的完整序列。采用的类似后序的方法,想要让原数组有序,只需要让它的左右区间有序,再对原数组做有序处理

在这里插入图片描述

因为需要对每组数据排序,需要申请一段和原数组一样的空间,在原数组直接排序会覆盖需要的数据。申请空间的部分需要和递归部分分开写。取中间变量对原数组分割的左右区间做递归,用四个变量记录两个左右区间的范围,当两端区间都存在的时候合并两个区间,最后拷贝回原数组,区间不存在返回

递归

void _MergeSort(int ary[],int begin, int end, int temp[])
{//终止条件,不存在大于区间if (begin == end){return;}int mid = (begin + end) / 2;//[begin,mid] [mid+1,end]//递归循环_MergeSort(ary, begin, mid, temp);_MergeSort(ary, mid+1, end, temp);//定义边界int begin1 = begin, end1 = mid;int begin2 = mid + 1, end2 = end;//下标int i = begin;while (begin1 <= end1 && begin2 <= end2){if (ary[begin1] <= ary[begin2]){temp[i++] = ary[begin1++];}else{temp[i++] = ary[begin2++];}}//没放完的while (begin1 <= end1){temp[i++] = ary[begin1++];}while (begin2 <= end2){temp[i++] = ary[begin2++];}//拷贝回去,加1memcpy(ary+begin, temp+begin, sizeof(int) * (end - begin + 1) );
}
//归并排序
void MergeSort(int ary[], int len)
{int* temp = (int*)malloc(sizeof(int) * len);_MergeSort(ary, 0, len -1 , temp);
}

左边区间递归情况
在这里插入图片描述
循环
循环需要以gap作为变量,控制每组的数量。每个for循环对这gap的分组进行排序,模仿递归从最后一层往回走的过程。先把左右分组排好序,再合并排序。不能使用栈的原因是,栈排好后数据会销毁,合并的时候不知道合并的两个区间是什么

在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

其中,需要关注的是分组的越界情况。可能有3个越界
1.end1,begin2,end2全部越界
2.begin2,end2越界
3.end2越界

//归并排序 循环
void Mergesort(int ary[], int len)
{int* temp = (int*)malloc(sizeof(int) * len);//gap归的数量int gap = 1;while (gap < len){//下标int j = 0;for (int i = 0; i < len; i += 2 * gap){//每组合并int begin1 = i, end1 = i + gap - 1;int begin2 = i + gap, end2 = i + 2 * gap - 1;//打印左右区间//printf("[%d,%d],[%d,%d]\r\n", begin1, end1, begin2, end2);//对于超过数组范围的区间调整//end1,begin2超过直接break//edn2超过修改end2if (end1 >= len || begin2 >= len){break;}if (end2 >= len){end2 = len - 1;}while (begin1 <= end1 && begin2 <= end2){if (ary[begin1] <= ary[begin2]){temp[j++] = ary[begin1++];}else{temp[j++] = ary[begin2++];}}//没放完的while (begin1 <= end1){temp[j++] = ary[begin1++];}while (begin2 <= end2){temp[j++] = ary[begin2++];}//归并一组,拷贝一组memcpy(ary + i, temp + i, sizeof(int) * (end2 - i + 1));}//整体拷贝回去//memcpy(ary, temp, sizeof(int) * len);gap = gap * 2;//printf("\r\n");}}

优化
归并法假如有很大的数据量,分割成比较小的组里,如果再继续分下去,就没有必要,浪费效率。所以对于比较小的组可以直接采用另一种排序的方法来排序。叫小区间优化,如果指定数量用另一种排序效率高于归并,就说明优化是有效的

void _MergeSort(int ary[],int begin, int end, int temp[])
{//终止条件,不存在大于区间if (begin == end){return;}//只剩10个,可以用其他排序提升效率//小区间优化if ((end - begin + 1) < 10){Sort(ary + begin, end - begin + 1);return;}int mid = (begin + end) / 2;//[begin,mid] [mid+1,end]//递归循环_MergeSort(ary, begin, mid, temp);_MergeSort(ary, mid+1, end, temp);//定义边界int begin1 = begin, end1 = mid;int begin2 = mid + 1, end2 = end;//下标int i = begin;while (begin1 <= end1 && begin2 <= end2){if (ary[begin1] <= ary[begin2]){temp[i++] = ary[begin1++];}else{temp[i++] = ary[begin2++];}}//没放完的while (begin1 <= end1){temp[i++] = ary[begin1++];}while (begin2 <= end2){temp[i++] = ary[begin2++];}//拷贝回去,加1memcpy(ary+begin, temp+begin, sizeof(int) * (end - begin + 1) );
}

在这里插入图片描述
上面是递归数量的展开图,倒数三层就占了总共87.5%的调用层次,所以小区间优化针对最下面的递归层次减少是有必要的

特性
1.归并的缺点在于O(N)的空间复杂度,更多的是解决磁盘中的外排序问题
2.时间复杂度: O(N*logN)
3. 空间复杂度: O(N)
4.稳定性: 稳定

2. 非比较排序

基本思想
计数排序又称鸽巢原理,是对哈希直接定址法的变形应用。操作步骤:

1.统计相同元素出现次数
2.根据统计的结果序列回收到原来的序列中

在这里插入图片描述

重新开一个数组,用这个数组来统计每个数出现的次数,比如上面的1出现了两次,就在下标1的位置填入2。如果原序列不是从0开始,那记录次数的数组0下标就不是记录0的次数了,用相对映射,如果数据最小值是100,那第一个下标处就记录100出现的次数,依次递增

//计数排序
void CountSort(int ary[], int len)
{//遍历找到序列最大和最小值int max = ary[0];int min = ary[0];for (int i = 0; i < len; i++){if (ary[i] > max){max = ary[i];}if (ary[i] < min){min = ary[i];}}//申请空间int range = max - min + 1;//数据初始化0int* temp = (int*)calloc(sizeof(int), range);//记录次数for (int i = 0; i < len; i++){temp[ary[i] - min]++;}//遍历数组int j = 0;for (int i = 0; i < range; i++){while (temp[i]--){//写回原序列ary[j++] = i + min;}}
}

特性
1.计数排序在数据范围集中时,效率很高,但是适用范围和场景有限
2.时间复杂度:O(MAX(N,范围)) ,数据量和范围哪个大
3.空间复杂度: O(范围)
4,稳定性: 稳定

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

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

相关文章

用Jmeter进行接口测试

web接口测试工具&#xff1a; 手工测试的话可以用postman &#xff0c;自动化测试多是用到 Jmeter&#xff08;开源&#xff09;、soupUI&#xff08;开源&商业版&#xff09;。 下面将对前一篇Postman做接口测试中的接口用Jmeter来实现。 一、Jmeter 的使用步骤 打开Jme…

惊鸿一瞥-网络初识

&#x1f495;"Echo"&#x1f495; 作者&#xff1a;Mylvzi 文章主要内容&#xff1a;惊鸿一瞥-网络初识 一.网络的发展过程 网络的发展过程是循序渐进的,大致可以分为四个阶段: 单机时代->局域网时代->广域网时代->互联网时代 单机时代:就是每个机器之间…

linux 06 磁盘管理

01.先管理vm中的磁盘&#xff0c;添加一个磁盘 第一步.vm软件&#xff0c;打开虚拟机设置&#xff0c;添加硬盘 第二步.选择推荐scsi 第三步.创建一个新的虚拟磁盘 第四步. 第五步. 02.在创建好的vm虚拟机中查看刚才创建的磁盘 在centos中/dev 目录是设备目录 sda是磁盘…

S7-1200PLC通讯问题总结

文章目录 一、硬件1.串口通信RS232RS485RS422 2.网口通信 二、协议1.串口通信协议2.网口通信协议 三、程序编写1.S7通信PUTGET 2.开放式以太网通信 一、硬件 可分为PLC与PLC通信&#xff0c;PLC与上位机通信&#xff0c;PLC与变频器通信&#xff0c;PLC与仪器仪表通信&#xf…

数据结构——单链表详解

目录 前言 一.什么是链表 1.概念 ​编辑 2.分类 二.单链表的实现(不带头单向不循环链表) 2.1初始化 2.2打印 2.3创建新节点 2.4头插、尾插 2.5头删、尾删 2.6查找 2.7在指定位置之前插入 2.8在指定位置之后插入 2.9删除pos位置 2.10删除pos之后的 2.11销毁链表…

风丘EV能量流测试解决方案 提高电动汽车续航能力

电动汽车&#xff08;EV&#xff09;近些年发展迅猛&#xff0c;已被汽车业内普遍认为是未来汽车发展的新方向&#xff0c;但现如今电动汽车仍然存在一些短板&#xff0c;导致其还无法替代传统燃油车。对此&#xff0c;首先想到的肯定就是电动车的续航问题。其实解决电动车续航…

锁(二)队列同步器AQS

一、队列同步器AQS 1、定义 用来构建锁或者其他同步组件的基础框架&#xff0c;它使用了一个int成员变量表示同步状态&#xff0c;通过内置的FIFO队列来完成资源获取线程的排队工作。是实现锁的关键。 2、实现 同步器的设计是基于模板方法模式的&#xff0c;也就是说&#…

社交媒体数据治理:Facebook的隐私与透明度

在数字化时代&#xff0c;社交媒体平台扮演着连接人们、传播信息的关键角色。然而&#xff0c;随着社交媒体数据的积累和应用&#xff0c;数据治理的议题逐渐引起了社会的广泛关注。本文将深入探讨Facebook在社交媒体数据治理方面的举措&#xff0c;特别关注其在隐私保护和透明…

Vue代理模式和Nginx反向代理(Vue代理部署不生效)

在使用axios时&#xff0c;经常会遇到跨域问题。为了解决跨域问题&#xff0c;可以在 vue.config.js 文件中配置代理&#xff1a; const { defineConfig } require(vue/cli-service) module.exports defineConfig({transpileDependencies: true,devServer: {port: 7070,prox…

PMP证书含金量如何?到底有啥用处?

接下来就为大家对PMP的一些入门问题做个解答。 01PMP是什么&#xff1f; | PMP是指项目管理专业人士资格认证。 | 美国项目管理协会&#xff08;PMI&#xff09;举办的项目管理专业人员&#xff08;PMP&#xff09;认证考试。 | 是目前项目管理领域含金量很高的认证。 国内…

实例分割论文阅读之:《Mask Transfiner for High-Quality Instance Segmentation》

1.摘要 两阶段和基于查询的实例分割方法取得了显著的效果。然而&#xff0c;它们的分段掩模仍然非常粗糙。在本文中&#xff0c;我们提出了一种高质量和高效的实例分割Mask Transfiner。我们的Mask Transfiner不是在规则的密集张量上操作&#xff0c;而是将图像区域分解并表示…

cesium系列篇:Entity vs Primitive 源码解析(从Entity到Primitive)02

上篇文章中&#xff0c;我们介绍了使用viewer.entities.add添加entity之后的信号传递以及最后entity对象被传递到GeometryVisualizer&#xff1b; 这篇文章&#xff0c;我们则介绍如何在逐帧渲染的过程中根据GeometryVisualizer中的entity对象创建相应的primitive 这是下文中…