排序算法:堆排序,快速排序,归并排序。内附完整代码和算法思路详解。

news2024/11/17 21:36:11

目录

一:堆排序

1.1:堆的数据结构

1.2:大小根堆

1.3:向下调整算法构建小根堆

1.4:堆排序思想

二:快速排序

2.1:快排单趟思想

三:归并排序

3.1:分组过程

3.2:归并过程


一:堆排序

1.1:堆的数据结构

堆必须是一颗完全二叉树逻辑结构如下:(当然它也可以是一颗满二叉树)

实际的存储结构如下:

 

那我们在数组中去表示这颗完全二叉树时,有两个基本公式,

根据自身下标位置,推导孩子的下标位置。

当本身的下标为 i 时,那么这个节点的左孩子下标为 i*2+1,右孩子的下标节点为 i*2+2;

根据自身下标位置,推导父亲的下标位置。

当本身的下标为 i 时,父亲的下标为 (i - 1)/ 2;

这两个公式是非常重要的,可以说堆排序就是依托着这两个公式存在的。

1.2:大小根堆

大根堆:每一颗子二叉树都必须满足 :根值大于等于左孩子值,根值大于等于右孩子值

小根堆:每一颗子二叉树都必须满足 :根值小于等于左孩子值,根值小于等于右孩子值

上面的图正好是一个小根堆。

1.3:向下调整算法构建小根堆

void ADjustDowld(int* a, int n, int root)
{
	int parent = root;
	int child = parent * 2 + 1;

	while (child < n)
	{
		if (child + 1 < n && a[child + 1] < a[child]) {
            //当右孩子值比左孩子还要小,那就让child+1.保证处理后child指向最小的那个孩子
			child++;
		}

		if (a[child] < a[parent]) {
			int tmp = a[child];
			a[child] = a[parent];
			a[parent] = tmp;
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}
	}

}

思想:我们单看一颗二叉树来说,先找出它左右两个孩子中较小的那个值的下标,然后呢,我们让较小的那个孩子与他的父亲的值进行比较,让较小的那个值去当根。这里就把这一颗二叉树构建成小根堆了。

所以为了构建整棵树的小根堆,我们从最下面的那个根节点开始。

通过数组下标我们可以得到最后一个数据的下标为 i = n -1 ,那么他的根节点的下标就是 (n-1)/ 2;

可以看到,经过我们的向下调整算法后,我们以及把这个堆构建成一个小根堆了, 

对于每一个子二叉树来说,它们都满足小根堆的定义,根值小于等于左孩子值,根值小于等于右孩子值

1.4:堆排序思想

有了前面的先导知识,我们就知道了,堆呢每次只可以选出一个极值,那我们要怎么使用这个算法对数组进行排序呢,这里我们又有了两个定义:

排升序,定义大根堆(每次选出最大值,和最后一位数据进行交换,然后让数组的长度减一)

排降序,定义小根堆(每次选出最小值,和最后一位数据进行交换,然后让数组的长度减一)

这里呢只对排降序进行了实现,如果要使用堆排升序,也是一样的。只需要修改一下向下调整算数中的条件即可。

二:快速排序

2.1:快排单趟思想

 我们使用两个指针,分别指向数组的第一个节点和最后一个节点,然后我们选择一个来当起始点,(这里我们选择end作为起始点),我们记录下end节点的下标,然后让begin指针先走(如果我们选择的是begin为起始点,那么就得让end指针先走)

这里我们就能让每次选出的keyindex的值来到它该到的下标位置,并且左边都是比a[keyindex]要小的,右边都是比a[keyindex]要大的。

那么我们只需要不断递归,就能完成排序。实现代码如下:

int parentSort(int* a, int begin, int end)
{
	int keyindex = end;
	while (begin < end) {
		while (begin < end && a[begin] <= a[keyindex]) {
			++begin;
		} //出来后,a[begin] > temp

		while (begin < end && a[end] >= a[keyindex]) {
			--end;
		} // 出来后,a[end] < temp;
		Swap(a[begin], a[end]);
	}
	Swap(a[end], a[keyindex]);
	return end;
}

void qSort(int* a, int left, int right)
{
	if (left >= right) {
		return;
	}

	int div = parentSort(a, left, right);
	qSort(a, left, div - 1); //排自己左边
	qSort(a, div + 1, right);//排自己右边
}

void test02()
{
	int a[] = { 6,5,4,3,2,1 };
	int n = sizeof(a) / sizeof(a[0]);
    
	qSort(a, 0, n - 1);

	for (int i = 0; i < n; i++) {
		printf("%d ", a[i]);
	}
}

三:归并排序

归并排序的中心思想就是通过不断的分组,分组到最后每个组只有一个数据,那么就可以开始归并排序了。

3.1:分组过程

他会通过递归将数据不断分组,分到最后数据不能再分割的时候,就开始进行归并了。 

3.2:归并过程

 第一次归并1和5,使得1,5有序,

第二趟归并1,5,6,使得1,5,6,有序。

第三趟归并4,7,使得4,7,有序。

第二趟归并1,5,6,和4,7使得1,4,5,6,7,有序。

(这里只列举了左边的归并过程,右边的也同理,当然这个顺序是归并到临时数组中,最后有序了,再拷贝回原数组中)

/* 归并排序 */
void _MergeSort(int* a, int left, int right, int* tmp)
{
	if (left >= right) { //不能再进行分组了
		return;
	}

	int mid = left + (right - left) / 2;
	//[left, mid] [mid+1, right]分组,有序即可排序,无序,分出子问题

	_MergeSort(a, left, mid, tmp);
	_MergeSort(a, mid + 1, right, tmp);

	//归并[left, mid][mid+1, right]有序
	int begin1 = left; int end1 = mid;
	int begin2 = mid + 1; int end2 = right;
	int index = begin1;

	while (begin1 <= end1 && begin2 <= end2) {
		if (a[begin1] <= a[begin2])
			tmp[index++] = a[begin1++];
		else
			tmp[index++] = a[begin2++];
	}

	while (begin1 <= end1)//begin2走完了
		tmp[index++] = a[begin1++];

	while (begin2 <= end2)//begin1走完了
		tmp[index++] = a[begin2++];

	//将归并好顺序的tmp中的数据都拷贝回a中。
	for (int i = left; i <= right; i++) {
		a[i] = tmp[i];
	}
}

void MergeSort(int *a, int n)
{
	if (a == NULL) {
		return;
	}

	int* tmp = (int*)malloc(sizeof(int) * n);
	_MergeSort(a, 0, n - 1, tmp);

	free(tmp);
}

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

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

相关文章

JSP ssh学习管理系统myeclipse开发mysql数据库MVC模式java编程计算机网页设计

一、源码特点 JSP ssh学习管理系统是一套完善的web设计系统&#xff08;系统采用ssh框架进行设计开发&#xff09;&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式 开发。开发环境为TOMCAT7.0,Mye…

MMDetection框架入门教程之环境部署

创建虚拟环境 打开Anaconda Prompt&#xff0c;创建一个新的虚拟环境mmlab。注意我这里选择了python3.6&#xff0c;因为在python3.7下出现了mmdet3d.apis中的类无法无法import的情况&#xff08;但mmdet3d可以import&#xff09;&#xff0c;暂时不清楚原因。 conda create …

SQLSERVER,求平均数,最大,最小,中位数,众数

SQLSERVER&#xff0c;求平均数&#xff0c;最大&#xff0c;最小&#xff0c;中位数&#xff0c;众数 SQLSERVER&#xff0c;求平均数&#xff0c;最大&#xff0c;最小&#xff0c;中位数&#xff0c;众数 SELECT -- *, t1.remark, t1.my_count, t1.my_sum, …

ArcGIS Python ​影像批量裁剪

该工具在&#xff1a;“14综合\工具箱.tbx\影像裁剪\按记录批量裁剪影像”&#xff0c;影像数据按矢量面要素批量裁剪&#xff0c;界面如图14-5所示。 图14-5 影像批量裁剪 按一个矢量面数据&#xff0c;按字段值相同的融合在一起裁剪影像&#xff0c;字段值是裁剪后的影像名字…

【再学Tensorflow2】TensorFlow2的高层封装

TensorFlow2的高层封装使用Tensorflow2构建模型的3种方法使用Sequential按层顺序构建模型使用函数式API创建任意结构的模型使用Model子类化创建自定义模型训练模型的3种方法内置fit方法内置train_on_batch方法自定义训练循环使用GPU训练模型使用单GPU训练模型使用多GPU训练模型…

ti3090安装cuda113+cudnn+anaconda+yolopose过程

wget https://developer.download.nvidia.com/compute/cuda/11.3.1/local_installers/cuda_11.3.1_465.19.01_linux.run sudo sh cuda_11.3.1_465.19.01_linux.run 如果有了nvidia driver&#xff0c;可以不用install driver选项。 配置环境变量&#xff1a; export PATH“/…

十一、kubernetes核心技术Label详解、实例

1、概述 Label是kubernetes系统中的一个重要概念。它的作用就是在资源上添加标识&#xff0c;用来对它们进行区分和选择。 Label的特点&#xff1a; 一个Label会以key/value键值对的形式附加到各种对象上&#xff0c;如Node、Pod、Service等等 一个资源对象可以定义任意数量的…

【技术博客】文本挖掘之LDA主题模型

文本挖掘之LDA主题模型 作者&#xff1a;郑培 引言 主题模型是文本挖掘的重要工具&#xff0c;近年来在工业界和学术界都获得了非常多的关注。在文本挖掘领域&#xff0c;大量的数据都是非结构化的&#xff0c;很难从信息中直接获取相关和期望的信息&#xff0c;一种文本挖掘…

ArcGIS基础实验操作100例--实验23提取栅格有效边界值

本实验专栏来自于汤国安教授《地理信息系统基础实验操作100例》一书 实验平台&#xff1a;ArcGIS 10.6 实验数据&#xff1a;请访问实验1&#xff08;传送门&#xff09; 基础编辑篇--实验23 提取栅格有效边界值 目录 一、实验背景 二、实验数据 三、实验步骤 &#xff08;…

sqlserver 求平均数,中位数,众数

sqlserver 求平均数&#xff0c;中位数&#xff0c;众数 sqlserver 聚合函数结合 窗口函数的巧妙使用。 SELECT -- *, t1.remark, t1.my_count, t1.my_sum, t1.my_avg, t1.my_min, t1.my_max, /*my_median : 中位数*/ t2.my_median, /*my_mos…

保姆教程系列二、Redis高可用(主从同步+哨兵模式)

系列文章目录 &#xff01;&#xff01;&#xff01;是的没错&#xff0c;胖友们&#xff0c;保姆教程系列又更新了&#xff01;&#xff01;&#xff01; 保姆教程系列一、Redis部署 so easy 保姆教程系列二、Redis高可用&#xff08;主从同步哨兵模式&#xff09; 保姆教程系…

2008-2020年上市公司环境治理费用

2008-2020年上市公司环境治理费用 1、时间区间为&#xff1a;2008-2020年 2、指标包括&#xff1a;统计截止日期、证券代码、证券简称、本期金额、上期金额、上市公司排污费、环保费、绿化费、环保支出等有关环境治理费用 3、指标说明&#xff1a; EndDate [统计截止日期] …

ArcGIS基础实验操作100例--实验22NoData数据处理

本实验专栏来自于汤国安教授《地理信息系统基础实验操作100例》一书 实验平台&#xff1a;ArcGIS 10.6 实验数据&#xff1a;请访问实验1&#xff08;传送门&#xff09; 基础编辑篇--实验22 NoData数据处理 目录 一、实验背景 二、实验数据 三、实验步骤 方法一&#xff1…

Linux网络协议之以太网协议(数据链路层)

Linux网络协议之以太网协议(数据链路层) 文章目录Linux网络协议之以太网协议(数据链路层)1.数据链路层解决的问题2.以太网协议2.1 认识以太网2.2 以太网帧格式2.3 认识MAC地址2.4 MAC地址与IP地址的区别3.ARP协议3.1 ARP协议的作用3.2 ARP数据报格式3.3 ARP协议工作流程3.4 ARP…

数据结构——基本术语

数据 数据能输入且被被计算机处理的符号集合。数据包括数值型数据和非数值型数据。非数值类型包括图&#xff0c;文字等 数据项和数据元素 数据元素时数据的基本单位&#xff0c;在计算机中通常被当作一个整体处理 也简称为元素&#xff0c;或者记录 数据元素又可以被若干个…

LaTeX环境的安装和配置 (vscode版)

目录下载Latex镜像文件安装镜像检验是否安装成功第一个Latex文件在vscode中使用latex支持中文编译引用下载Latex镜像文件 访问清华镜像网站&#xff0c;进行latex2022的下载 网站地址如下&#xff1a;latex_清华镜像 选择后缀名为.iso的文件进行下载即可 安装镜像 下载完成之…

CloudCanal对Online DDL 工具 GH-OST 和 PT-OSC 的支持

简介 CloudCanal 实现了对 Online DDL 工具如 GH-OST 和 PT-OSC 的支持&#xff0c;保证了对端实时同步源端的 Online DDL 操作。 本文以 MySQL -> MySQL 同步链路使用 GH-OST 为例&#xff0c;介绍 CloudCanal 是如何支持实时同步 GH-OST 产生的 DDL 的。 Online DDL 技…

CentOS7版本中mysql卸载和安装步骤问题汇总记录--2020-12-29

目录一、如何卸载1.1 查询系统是否安装了MySQL1.2 关闭MySQL服务1.3 删除MySQL安装的服务1.4 删除MySQL相关的文件夹二、如何安装2.1 下载MySQL5.7安装包2.2 安装MySQL2.3 配置MySQL2.3.1 初始化数据库2.3.2 配置开机自启2.3.3 启动MySQL服务2.3.4 登录MySQL进行初始化参考文献…

【开源项目】消息队列XXL-MQ源码解析

消息队列XXL-MQ源码解析 项目介绍 XXL-MQ是一款轻量级分布式消息队列&#xff0c;拥有 “水平扩展、高可用、海量数据堆积、单机TPS过10万、毫秒级投递” 等特性, 支持 “并发消息、串行消息、广播消息、延迟消息、事务消费、失败重试、超时控制” 等消息特性。现已开放源代码…

专栏目录总览

文章目录摘要1. Backbone2. Neck3. Bottleneck4. Head5.GAP或者avgpool&#xff1a;6.Embedding摘要 梳理了一些长见的名词&#xff0c;方便大家够好的理解论文和Ai方向的文章。 1. Backbone 骨干网络或者说是主干网络&#xff0c;指的是提取特征的网络&#xff0c;其作用就…