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++];

	}
	//拷贝回去,加1
	memcpy(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超过修改end2
			if (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++];

	}
	//拷贝回去,加1
	memcpy(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;
	//数据初始化0
	int* 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,稳定性: 稳定

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

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

相关文章

前端异步相关知识总结

目录 一、同步和异步简介 同步&#xff08;按顺序执行&#xff09; 异步&#xff08;不按顺序执行&#xff09; 异步出现的原因和需求 二、实现异步的方法 回调函数 Promise 生成器Generators/ yield async await 三、promise和 async await 区别 概念 两者的区别 …

ctfshow——命令执行

文章目录 web 29——通配符*绕过web30——调用其他命令执行函数web 31——参数逃逸web 32-web 36——配合文件包含伪协议web 37-web 39——文件包含web 40—— web 29——通配符*绕过 i不区分大小写&#xff0c;直接?csystem(tac fl*.php); web30——调用其他命令执行函数 调用…

二进制安全虚拟机Protostar靶场(7)heap2 UAF(use-after-free)漏洞

前言 这是一个系列文章&#xff0c;之前已经介绍过一些二进制安全的基础知识&#xff0c;这里就不过多重复提及&#xff0c;不熟悉的同学可以去看看我之前写的文章 heap2 程序静态分析 https://exploit.education/protostar/heap-two/#include <stdlib.h> #include &…

JavaScript基础第四天

JavaScript 基础第四天 今天我们学习js的函数&#xff0c;包括普通函数、匿名函数、箭头函数以及函数作用域。 1. 函数的初体验 1.1. 什么是函数 函数是 JavaScript 中的基本组件之一。一个函数是 JavaScript 过程一组执行任务或计算值的语句。要使用一个函数&#xff0c;你…

Django模板(二)

标签if 标签在渲染过程中提供使用逻辑的方法,比如:if和for 标签被 {% 和 %} 包围,如下所示: 由于在模板中,没有办法通过代码缩进判断代码块,所以控制标签都需要有结束的标签 if判断标签{% if %} {% endif %} : # athlete_list 不为空 {% if athlete_list %}# 输出 ath…

[C#] 如何使用ScottPlot.WPF在WPF桌面程序中绘制图表

什么是ScottPlot.WPF&#xff1f; ScottPlot.WPF 是一个开源的数据可视化库&#xff0c;用于在 WPF 应用程序中创建高品质的绘图和图表。它是基于 ScottPlot 库的 WPF 版本&#xff0c;提供了简单易用的 API&#xff0c;使开发人员能够通过简单的代码创建各种类型的图表&#…

高斯伪谱C++封装库开源!

Windows x64/86 C无依赖运行高斯伪谱法求解最优控制问题&#xff0c;你只需要ElegantGP! Author: Y. F. Zhang His Github: https://github.com/ZYunfeii 写在前面 这个库在你下载它的那一时刻起不再依赖任何其他代码&#xff0c;直接可用来构建C的最优控制问题并进行求解。…

Appium使用初体验之参数配置,简单能够运行起来

一、服务器配置 Appium Server配置与Appium Server GUI&#xff08;可视化客户端&#xff09;中的配置对应&#xff0c;尤其是二者如果不在同一台机器上&#xff0c;那么就需要配置Appium Server GUI所在机器的IP&#xff08;Appium Server GUI的HOST也需要配置本机IP&#xf…

Docker-Learn(三)创建镜像Docker(换源)

根据之前的内容基础&#xff0c;本小点的内容主要涉及到的内容是比较重要的文本Dockerfile 1. 编辑Dockerfile 启动命令行终端&#xff08;在自己的工作空间当中&#xff09;,创建和编辑Dockerfile。 vim Dockerfile然后写入以下内容 # 使用一个基础镜像 FROM ubuntu:late…

Flink流式数据倾斜

1. 流式数据倾斜 流式处理的数据倾斜和 Spark 的离线或者微批处理都是某一个 SubTask 数据过多这种数据不均匀导致的&#xff0c;但是因为流式处理的特性其中又有些许不同 2. 如何解决 2.1 窗口有界流倾斜 窗口操作类似Spark的微批处理&#xff0c;直接两阶段聚合的方式来解决…

单片机——FLASH(2)

文章目录 flash &#xff08;stm32f40x 41x的内存映射中区域详解&#xff09;flash写数据时 flash &#xff08;stm32f40x 41x的内存映射中区域详解&#xff09; Main memory 主存储区 放置代码和常数 System memory 系统存储区 方式bootloader代码 OTP区 一次性可编程区 选项…

redis存储对象的过期设置在实际项目中的运用案例展示

redis存储对象的过期设置在实际项目中的运用案例展示&#xff01;经过前面的学习&#xff0c;我们已经基本上初步掌握了redis数据库存储对象的过期时间是如何设置的了。下面给大家展示一个具体的实际开发项目中用到业务场景。 在项目化生寺小程序游戏开发中&#xff0c;有道具&…

DC-7靶机渗透详细流程

信息收集&#xff1a; 1.存活扫描&#xff1a; 由于靶机和kali都是nat的网卡&#xff0c;都在一个网段&#xff0c;我们用arp-scan会快一点&#xff1a; arp-scan arp-scan -I eth0 -l └─# arp-scan -I eth0 -l Interface: eth0, type: EN10MB, MAC: 00:0c:29:dd:ee:6…

从零开始手写mmo游戏从框架到爆炸(十一)— 注册与登录

导航&#xff1a;从零开始手写mmo游戏从框架到爆炸&#xff08;零&#xff09;—— 导航-CSDN博客 从这一章开始&#xff0c;我们进入业务的部分&#xff0c;从注册登录开始。 创建注册和登录的路由 package com.loveprogrammer.command.server;public interface Se…

Java面向对象 继承

目录 继承继承的好处继承具有传递性实例创建Person类Student继承Person类测试 继承 Java中的继承是面向对象编程的一个核心特性&#xff0c;它允许一个类&#xff08;子类或派生类&#xff09;继承另一个类&#xff08;父类或基类&#xff09;的属性和方法。通过继承&#xff0…

蓝桥杯备战——12.超声波与测频代码优化

1.优化分析 昨天我在看原理图的发现超声波模块的反馈引脚P11刚好可以使用PCA模块0的捕获功能&#xff0c;我就想着把PCA功能留给超声波&#xff0c;然后测频功能还是改成定时器0来完成&#xff0c;然后前后台功能改成定时器1。 至于我为什么要这么改呢&#xff0c;看一下我原…

157基于matlab的GVF-snake算法能自动收敛到目标区域

基于matlab的GVF-snake算法能自动收敛到目标区域。关键技术GVF snake模型算法matlab源程序&#xff0c;GVF是根据光流场原理,利用变分方法,从图像中得到的一种向量场,该向量场被称为梯度矢量流(GVF)场。 Snake模型称为动态轮廓模型&#xff08;Active Contour Model&#xff0…

vue的8大生命周期

第072个 查看专栏目录: VUE ------ element UI 专栏目标 在vue和element UI联合技术栈的操控下&#xff0c;本专栏提供行之有效的源代码示例和信息点介绍&#xff0c;做到灵活运用。 提供vue2的一些基本操作&#xff1a;安装、引用&#xff0c;模板使用&#xff0c;computed&a…

51单片机之数码管显示表白数字篇

朝菌不知晦朔 蟪蛄不知春秋 眼界决定境界 CSDN 请求进入专栏 是否进入《51单片机专栏》? 确定 目录 数码管的简介 数码管引脚定义 数码管的原理图 74HC245 代码实现 静态数码管的显示 动态数码管的显示 数码管实现表白画面 数码管的简介 L…

阿里云ECS服务器Linux安装Mysql8

链接&#xff1a;https://pan.baidu.com/s/1s9j7OhiOMV9e9Qq9GDbysA 提取码&#xff1a;dd5a --来自百度网盘超级会员V5的分享 Mysql官网:MySQL 关于Mysql Yum Repository介绍可以看下 更加简单 关于X86和ARM 传到服务器 进入所在包 cd /usr/local/develop/mysql8 解压 …