归并排序 与 计数排序

目录

1.归并排序

1.1 递归实现归并排序:

 1.2 非递归实现归并排序

1.3 归并排序的特性总结:

1.4 外部排序

2.计数排序

2.1 操作步骤:

2.2 计数排序的特性总结:

3. 7种常见比较排序比较


1.归并排序

基本思想:

归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide andConquer)的一个非常典型的应用。已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。

归并排序核心步骤:

 动图演示:

1.1 递归实现归并排序:

归并排序类似于二叉树中的后序遍历,先让整个数组分为两个子序列,归并这两部份子序列,但是归并需要两部份子序列有序,然后取小的尾插到一个新开辟的数组中,归并完成后后再拷贝回原数组,如何让子序列有序,还要再次将每个子序列分为两部分,直到每个子序列只有一个值,这时已经递归到最深处,然会递归向回归并。

递归代码实现:

//归并排序
//开辟好空间后由下面元素调用此函数
void _MergeSort(int* arr, int* tmp, int begin, int end)
{if (begin == end){return;}int midi = (begin + end) / 2;_MergeSort(arr, tmp, begin, midi);_MergeSort(arr, tmp, midi+1, end);int begin1 = begin;int end1 = midi;int begin2 = midi + 1;int end2 = end;int i = begin;//归并  取小的尾插到开辟的空间while (begin1 <= end1 && begin2 <= end2){if (arr[begin1] <= arr[begin2]){tmp[i++] = arr[begin1++];}else{tmp[i++] = arr[begin2++];}}while (begin1 <= end1){tmp[i++] = arr[begin1++];}while (begin2 <= end2){tmp[i++] = arr[begin2++];}//将归并好的两组数据拷贝会原数组memcpy(arr + begin, tmp + begin, sizeof(int) * (end - begin + 1));}void MergeSort(int* arr, int n)
{//开辟空间int* tmp = (int*)malloc(sizeof(int) * n);_MergeSort(arr, tmp, 0, n - 1);
}

小区间优化

//小区间优化
if (end - begin +1<10)
{//使用插入排序InsertSort(arr + begin, end - begin + 1);return;
}

优化的本质是减小递归调用的次数,由于二叉树的性质。我们可以得出满二叉树后三层大约占总个数的85%。为了减小递归开销,我们可以将小区间的递归调用改为直接插入排序可以提高一点排序的性能,但也不会提高很多。快排也可以使用这种方式优化。

 1.2 非递归实现归并排序

我们可以先让每组gap=1个数据,每次归并两组,然后在让gap*=2,再次归并,直到gap>n。

代码实现:

//非递归实现归并排序
void MergeSortNonR1(int* arr, int n)
{int* tmp = (int*)malloc(sizeof(int) * n);//每组有gap个数据,归并两组int gap = 1;while (gap < n){int j = 0;for (int i = 0; i < n; i += 2 * gap){int begin1 = i, end1 = i + gap - 1;int begin2 = i + gap, end2 = i + 2 * gap - 1;if (end1 >= n || begin2 >= n)//不需要归并{break;}//修正if (end2 >= n){end2 = n - 1;}//归并while (begin1 <= end1 && begin2 <= end2){if (arr[begin1] <= arr[begin2]){tmp[j++] = arr[begin1++];}else{tmp[j++] = arr[begin2++];}}while (begin1 <= end1){tmp[j++] = arr[begin1++];}while (begin2 <= end2){tmp[j++] = arr[begin2++];}//将归并后的两组数据 拷贝回原数组 memcpy(arr + i, tmp + i, sizeof(int) * (end2 - i + 1));}gap *= 2;}
}

边界越界问题:

int begin1 = i, end1 = i + gap - 1;
int begin2 = i + gap, end2 = i + 2 * gap - 1;

begin1不会越界,因为begin1 = i,i 复合循环条件 。

  1. end1,begin2,end2都越界
  2. begin2,end2越界
  3. end2越界

1. end1,begin2,end2都越界

   此时不需要归并直接跳出循环。

2. begin2,end2越界

 此时也不需要归并直接跳出循环。

3. end2越界

此时需要归并,但是我们要修改end2,将end2改为n-1。

代码:

if (end1 >= n || begin2 >= n)//不需要归并{break;}//修正if (end2 >= n){end2 = n - 1;}

1.3 归并排序的特性总结:

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

1.4 外部排序

概念:当数据元素太多不能同时放在内存中,根据排序过程的要求不能在内外存之间移动数据的排序。

在我们所学的排序算法中,只有非递归归并排序的思想可以用于外部排序。其他排序算法都只适用于内部排序,因为他们都使用了下标来进行随机存取,而非递归归并排序不需要,是顺序存取,这里举个例子:

假如我们由100亿个整数要排序,也就是大约40G,而我们的内存中只有1G,步骤:

  1. 把40G的文件分为40份。
  2. 让每份文件依次放到内部中排序,让40份文件内部有序。
  3. 两两归并,分别从两个文件中读一个数据,然后选小的写文件,这时就与非递归归并排序相同了。

2.计数排序

思想:计数排序又称为鸽巢原理,是一种非比较排序,是对哈希直接定址法的变形应用。

2.1 操作步骤:

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

 代码实现:

// 计数排序
void CountSort(int* arr, int n)
{//遍历 确定最大值与最小值int max = arr[0];int min = arr[0];for (int i = 0; i < n; i++){if (arr[i] < min){min = arr[i];}if (arr[i] > max){max = arr[i];}}//遍历计数int range = max - min + 1;int* CountA = (int*)malloc(sizeof(int) * range);memset(CountA, 0, sizeof(int) * range);for (int i = 0; i < n; i++){CountA[arr[i] - min]++;}//回收到原数组int j = 0;for (int i = 0; i < range; i++){while (CountA[i]--){arr[j++] = i + min;}}
}

2.2 计数排序的特性总结:

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

3. 7种常见比较排序比较

排序方法平均情况最好情况最坏情况辅助空间稳定性
冒泡排序O(N^2)O(N)O(N^2)O(1)稳定
简单选择排序O(N^2)O(N^2)O(N^2)O(1)不稳定
直接插入排序O(N^2)O(N)O(N^2)O(1)稳定
希尔排序O(NlogN)~O(N^2)O(N^1.3)O(N^2)O(1)不稳定
堆排序O(NlogN)O(NlogN)O(N*logN)O(1)不稳定
归并排序O(NlogN)O(NlogN)O(N*logN)O(n)稳定
快速排序O(NlogN)O(NlogN)O(N^2)O(logn)~O(n)不稳定

本篇结束!

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

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

相关文章

redis分布式集群-redis+keepalived+ haproxy

redis分布式集群架构&#xff08;RedisKeepalivedHaproxy&#xff09;至少需要3台服务器、6个节点&#xff0c;一台服务器2个节点。 redis分布式集群架构中的每台服务器都使用六个端口来实现多路复用&#xff0c;最终实现主从热备、负载均衡、秒级切换的目标。 redis分布式集…

使用Edge和chrom扩展工具(GoFullPage)实现整页面截图或生成PDF文件

插件GoFullPage下载&#xff1a;点击免费下载 如果在浏览网页时&#xff0c;有需要整个页面截图或导出PDF文件的需求&#xff0c;这里分享一个Edge浏览器的扩展插件&#xff1a;GoFullPage。 这个工具可以一键实现页面从上到下滚动并截取。 一、打开“管理扩展”&#xff08;…

网络设备(防火墙、路由器、交换机)日志分析监控

外围网络设备&#xff08;如防火墙、路由器、交换机等&#xff09;是关键组件&#xff0c;因为它们控制进出公司网络的流量。因此&#xff0c;监视这些设备的活动有助于 IT 管理员解决操作问题&#xff0c;并保护网络免受攻击者的攻击。通过收集和分析这些设备的日志来监控这些…

Python 3 使用Hadoop 3之MapReduce总结

MapReduce 运行原理 MapReduce简介 MapReduce是一种分布式计算模型&#xff0c;由Google提出&#xff0c;主要用于搜索领域&#xff0c;解决海量数据的计算问题。 MapReduce分成两个部分&#xff1a;Map&#xff08;映射&#xff09;和Reduce&#xff08;归纳&#xff09;。…

tauri-react:快速开发跨平台软件的架子,支持自定义头部和窗口阴影效果

tauri-react 一个使用 taurireacttsantd 开发跨平台软件的模板&#xff0c;支持窗口头部自定义和窗口阴影&#xff0c;不用再自己做适配了&#xff0c;拿来即用&#xff0c;非常 nice。 开原地址&#xff1a;GitHub - Sjj1024/tauri-react: 一个最基础的使用tauri和react开发…

生成式 AI 在泛娱乐行业的应用场景实践 – 助力风格化视频内容创作

感谢大家阅读《生成式 AI 行业解决方案指南》系列博客&#xff0c;全系列分为 4 篇&#xff0c;将为大家系统地介绍生成式 AI 解决方案指南及其在电商、游戏、泛娱乐行业中的典型场景及应用实践。目录如下&#xff1a; 《生成式 AI 行业解决方案指南与部署指南》《生成式 AI 在…

一个概率论例题引发的思考

浙江大学版《概率论与数理统计》一书&#xff0c;第13章第1节例2&#xff1a; 这个解释和模型比较简单易懂。 接下来&#xff0c;第13章第2节的例2也跟此模型相关&#xff1a; 在我自己的理解中&#xff0c;此题的解法跟上一个题目一样&#xff0c;其概率如下面的二维矩阵&a…

聊聊计算机技术

目录 1.计算机的概念 2.计算机的发展过程 3.计算机的作用 4.计算机给人类带来的福利 1.计算机的概念 计算机是一种用于处理和存储数据的电子设备。它能够执行各种操作&#xff0c;比如计算、逻辑操作、数据存储和检索等。计算机由硬件和软件两部分组成。 计算机的硬件包括中…

Go 语言并发编程 及 进阶与依赖管理

1.0 从并发编程本质了解Go高性能的本质 1.1 Goroutine 协程可以理解为轻量级线程&#xff1b; Go更适合高并发场景原因之一&#xff1a;Go语言一次可以创建上万协成&#xff1b; “快速”&#xff1a;开多个协成 打印。 go func(): 在函数前加 go 代表 创建协程; time.Sleep():…

基于深度信念网络的西储大学轴承故障分类识别,基于EMD+DBN的西储大学轴承故障识别,LCD+DBN,LMD+DBN

目录 背影 DBN神经网络的原理 DBN神经网络的定义 受限玻尔兹曼机(RBM) (EMD,LCD,LMD)+DBN的深度信念网络的西储大学轴承故障分类识别 基本结构 主要参数 数据 MATALB代码 结果图 展望 背影 DBN是一种深度学习神经网络,拥有提取特征,非监督学习的能力,是一种非常好的分类…

Nacos使用SpringCloudAlibaba+Dubbo实现

Nacos简介 Nacos是阿里的一个开源产品&#xff0c;它是针对微服务架构中的服务发现、服务治理、配置管理的综合型解决方案。 官方介绍是这样的&#xff1a; Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集&#xff0c;帮助您实现动态服务发现、…

CSDN编程题-每日一练(2023-08-14)

CSDN编程题-每日一练&#xff08;2023-08-14&#xff09; 一、题目名称&#xff1a;小股炒股二、题目名称&#xff1a;王子闯闸门三、题目名称&#xff1a;圆小艺 一、题目名称&#xff1a;小股炒股 时间限制&#xff1a;1000ms内存限制&#xff1a;256M 题目描述&#xff1a; …

ISIS技术(第三十七课)

1 分享一下华为官网上的一张地图 官网地址:https://support.huawei.com/hedex/hdx.do?docid=EDOC1000105967&id=ZH-CN_CONCEPT_0000001501534705 2 路由的分类 -直连路由 直接连接的路由,且配置了IP地址之后(在同一网段内),就是直连路由。 -非直连路由 -静态路由…

2021年06月 C/C++(二级)真题解析#中国电子学会#全国青少年软件编程等级考试

第1题&#xff1a;数字放大 给定一个整数序列以及放大倍数x&#xff0c;将序列中每个整数放大x倍后输出。 时间限制&#xff1a;1000 内存限制&#xff1a;65536 输入 包含三行&#xff1a; 第一行为N&#xff0c;表示整数序列的长度(N ≤ 100); 第二行为N个整数(不超过整型范围…

(css)点击前隐藏icon图表 点击后显示

(css)点击前隐藏icon图表 点击后显示 效果 html <liv-for"(item,index) in sessionList":key"index"class"liClass":class"{ active: change2 index }"tabindex"2">...<el-tooltip class"item" effec…

分布式监控平台——Zabbix

市场上常用的监控软件&#xff1a; 传统运维&#xff1a;zabbix、 Nagios 一、zabbix概述 作为一个运维&#xff0c;需要会使用监控系统查看服务器状态以及网站流量指标&#xff0c;利用监控系统的数据去了解上线发布的结果&#xff0c;和网站的健康状态。 利用一个优秀的监…

Dedecms V110最新版RCE---Tricks

前言 刚发现Dedecms更新了发布版本&#xff0c;顺便测试一下之前的day有没有修复&#xff0c;突然想到了新的tricks去实现RCE。 文章发布的时候估计比较晚了&#xff0c;一直没时间写了。 利用 /uploads/dede/article_string_mix.php /uploads/dede/article_template_rand.…

Blender增强现实3D模型制作指南【AR】

推荐&#xff1a;用 NSDT编辑器 快速搭建可编程3D场景 将静态和动画 3D 内容集成到移动增强现实 (AR) 体验中是增强用户沉浸感和参与度的高效方法。 然而&#xff0c;为 AR 创建 3D 对象可能相当艰巨&#xff0c;尤其是对于那些缺乏 3D 建模经验的人来说。 与添加视频或照片 AR…

THUDM/chatglm2-6b-int4体验

在gpu下 gpu&#xff1a; Telsa T4 资源消耗&#xff1a;RAM大概4G&#xff0c;GPU显存大概6G # 安装transformers等包 !pip install protobuf transformers4.30.2 cpm_kernels torch>2.0 gradio mdtex2html sentencepiece accelerate# 导入AutoTokenizer, AutoModel from…

CSAPP Lec01

1. CMU 15213_15513 CSAPP 深入理解计算机系统 Lecture 01 Course Overview 中英字幕_哔哩哔哩_bilibili 从这个课程中可以学到什么&#xff1f;&#xff08;为什么要学这门课&#xff09; Great Reality #1&#xff08;数字类型&#xff09;: Ints are not Integers, Floats…