归并排序 与 计数排序

目录

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.mfbz.cn/a/79364.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

集简云本周新增/更新:新增3大功能,集成19款应用,更新5款应用,新增近290个动作

本周更新概要 功能更新 ◉ 新增功能&#xff1a;语聚AI开放API功能 ◉ 新增功能&#xff1a;数据表表格公开分享功能 ◉ 新增功能&#xff1a;浏览器页面操作页面内容读取(增强版本&#xff09; 应用新增 新增应用&#xff1a;赛捷CRM 新增应用&#xff1a;快跑者 新增应…

Matplotlib数据可视化(六)

目录 1.绘制概率图 2.绘制雷达图 3.绘制流向图 4.绘制极坐标图 5.绘制词云图 1.绘制概率图 from scipy.stats import norm fig,ax plt.subplots() plt.rcParams[font.family] [SimHei] np.random.seed() mu 100 sigma 15 x musigma*np.random.randn(437) num_bins …

GRPC 学习记录

GRPC 安装 安装 grpcio、grpcio-tools、protobuf、 pip install grpcio -i https://pypi.tuna.tsinghua.edu.cn/simple pip install grpcio-tools -i https://pypi.tuna.tsinghua.edu.cn/simple pip install protobuf -i https://pypi.tuna.tsinghua.edu.cn/simple常用类型 p…

ai之美:探索写真照片软件的创造力

小青&#xff1a;嘿&#xff0c;小华&#xff0c;你知道最近ai艺术写真非常流行吗&#xff1f; 小华&#xff1a;真的吗&#xff1f;我还不知道呢。告诉我更多细节吧&#xff01; 小青&#xff1a;好的&#xff0c;ai艺术写真是指使用人工智能技术将照片转化为艺术作品的过程…

arcgis数据采集与拓扑检查

1、已准备好一张配准好的浙江省行政区划图&#xff0c;如下&#xff1a; 2、现在需要绘制湖州市县级行政区划。需要右击文件夹新建文件地理数据库&#xff0c;如下&#xff1a; 其余步骤均默认即可。 创建好县级要素数据集后&#xff0c;再新建要素类&#xff0c;命名为县。 为…

Unity制作一个简单的登入注册页面

1.创建Canvas组件 首先我们创建一个Canvas画布&#xff0c;我们再在Canvas画布底下创建一个空物体&#xff0c;取名为Resgister。把空物体的锚点设置为全屏撑开。 2.我们在Resgister空物体底下创建一个Image组件&#xff0c;改名为bg。我们也把它 的锚点设置为全屏撑开状态。接…

【python实现向日葵控制软件功能】手机远程控制电脑

大家好&#xff0c;我是csdn的博主&#xff1a;lqj_本人 这是我的个人博客主页&#xff1a; lqj_本人_python人工智能视觉&#xff08;opencv&#xff09;从入门到实战,前端,微信小程序-CSDN博客 最新的uniapp毕业设计专栏也放在下方了&#xff1a; https://blog.csdn.net/lbcy…

【CUDA】学习记录(4)-线程束的执行

线程模型 block&#xff1a;同一个block内共享内存&#xff0c;同一block中的thread可以彼此进行通信。 block&#xff1a;block-local synchronization。同一个块内的线程可以同步。 线程&#xff0c;可以根据blockIdx和threadIdx唯一的指定。 作者&#xff1a;不会code的程序…

MongoDB:数据库初步应用

一.连接MongoDB 1.MongoDBCompass连接数据库 连接路径:mongodb://用户名:密码localhost:27017/ 2.创建数据库(集合) MongoDB中数据库被称为集合. MongoDBCompass连接后,点击红色框加号创建集合,点击蓝色框加号创建文档(数据表) 文档中的数据结构(相当于表中的列)设计不用管…

Linux——KVM虚拟化

目录标题 虚拟化技术虚拟化技术发展案例KVM简介KVM架构及原理KVM原理KVM虚拟化架构/三种模式虚拟化前、虚拟化后对比KVM盖中盖套娃实验 虚拟化技术 通过虚拟化技术将一台计算机虚拟为多台逻辑计算机&#xff0c;在一台计算机上同时运行多个逻辑计算机&#xff0c;同时每个逻辑…

PHP自己的框架实现config配置层级存取(完善篇二)

1、实现效果 config(include_once $coreConfig); //加载配置文件config() //获取所有配置 config(DB_HOST) 获取配置 2、按层级配置文件加载&#xff0c;存取配置项 config,function.php function config($varNULL,$valueNULL){static $configarray();if(is_array($var)){…

驱动day5

思维导图 练习 实现设备文件和设备的绑定&#xff0c;编写LED驱动 head.h #ifndef __HEAD_H__ #define __HEAD_H__typedef struct {unsigned int MODER;unsigned int OTYPER;unsigned int OSPEEDR;unsigned int PUPDR;unsigned int IDR;unsigned int ORD; }gpio_t;#define G…

“RFID与光伏板的完美融合:探索能源科技的新时代!“

随着科技的不断发展&#xff0c;人类创造出了许多令人惊叹的发明。其中&#xff0c;RFID&#xff08;Radio Frequency Identification&#xff09;技术的应用在各个领域日益广泛。最近的研究表明&#xff0c;将RFID技术应用于光伏板领域&#xff0c;不仅可以提高光伏板的效率&a…

kafka集成篇

kafka的Java客户端 生产者 1.引入依赖 <dependency><groupId>org.apache.kafka</groupId><artifactId>kafka-clients</artifactId><version>2.6.3</version></dependency>2.生产者发送消息的基本实现 /*** 消息的发送⽅*/ …

常见的Web安全漏洞有哪些,Web安全漏洞常用测试方法介绍

Web安全漏洞是指在Web应用程序中存在的可能被攻击者利用的漏洞&#xff0c;正确认识和了解这些漏洞对于Web应用程序的开发和测试至关重要。 一、常见的Web安全漏洞类型&#xff1a; 1、跨站脚本攻击(Cross-Site Scripting&#xff0c;XSS)&#xff1a;攻击者通过向Web页面注入…

Redis的单线程与多线程

Redis的核心处理逻辑一直都是单线程 有一些分支模块是多线程(某些异步流程从4.0开始用的多线程&#xff0c;例如UNLINK、FLUSHALL ASYNC、FLUSHDB ASYNC等非阻塞的删除操作。网络I/O解包从6.0开始用的是多线程;) 为什么是单线程 多线程多好啊可以利用多核优势 官方给的解释 …

罗勇军 →《算法竞赛·快冲300题》每日一题:“质因子数量” ← 快速幂、素数筛

【题目来源】http://oj.ecustacm.cn/problem.php?id1780http://oj.ecustacm.cn/viewnews.php?id1023【题目描述】 给出n个数字&#xff0c;你可以任意选择一些数字相乘&#xff0c;相乘之后得到新数字x。 其中&#xff0c;x的分数等于x不同质因子的数量。 请你计算所有选择数…

【Rust】Rust学习 第十四章进一步认识 Cargo 和 Crates.io

本章会讨论 Cargo 其他一些更为高级的功能&#xff0c;我们将展示如何&#xff1a; 使用发布配置来自定义构建将库发布到 crates.io使用工作空间来组织更大的项目从 crates.io 安装二进制文件使用自定义的命令来扩展 Cargo Cargo 的功能不止本章所介绍的&#xff0c;关于其全…

蓝蓝设计-ui设计公司-界面设计案例作品

泛亚高科-光伏电站控制系统界面设计 html前端 | 交互设计 | 视觉设计 | 图标设计 泛亚高科(北京)科技有限公司&#xff08;以下简称“泛亚高科”&#xff09;&#xff0c;一个以实时监控、高精度数值计算为基础的科技公司&#xff0c; 自成立以来&#xff0c;组成了以博士、硕…

【Java 动态数据统计图】动态数据统计思路案例(动态,排序,containsKey)五(117)

需求&#xff1a;前端根据后端的返回数据&#xff1a;画统计图&#xff1b; 1.动态获取地域数据以及数据中的平均值&#xff0c;按照平均值降序排序&#xff1b; 说明&#xff1a; X轴是动态的&#xff0c;有对应区域数据则展示&#xff1b; X轴 区域数据降序排序&#xff1b;…
最新文章