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

2023-05-16

目录

一:堆排序

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);
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

  • Redis 部署及介绍

    1 安装单机版redis root 64 redis master mkdir p data application 创建工作目录 root 64 redis master wget http download redis io relea
  • shenyu中logback替换成log4j2

    一 背景 shenyu框架默认使用的是logback处理日志 xff0c 压测发现写入日志存在瓶颈 基于log4j2优秀的性能 xff0c 使用log4j2替换logback 二 如何替换logback 1 删除logback的依赖项 sp
  • 图片项目部署

    1 xff0c 准备 mysql 主从 43 读写分离 3台 nginx 43 uwsgi 43 python3 6 1台 redis 哨兵 3台 A nginx uwsgi python3 上传代码包 xff0c 调试 B mysql r
  • Git 构建分布式版本控制系统详解

    安装git要4G以上内存 安装和配置必要的依赖关系 root 64 localhost yum install curl policycoreutils openssh server openssh clients 安装邮件程序 root
  • jenkins 详细部署

    部署jenkins需要以下的步骤 环境需要4G内存 1 xff0c 部署git 安装依赖环境 root 64 localhos yum install curl devel expat devel gettext devel openssl
  • RabbitMQ消息队列的部署

    RabbitMQ消息队列的用处 对于一个大型的软件系统来说 xff0c 它会有很多的组件或者说模块或者说子系统 xff08 subsystem or Component or submodule xff09 那么这些模块的如何通信 xff1
  • Docker 基础使用命令

    Docker下载 配置阿里云Docker Yum源 root 64 xingdian yum install y yum utils device mapper persistent data lvm2 git root 64 xingdi
  • docker部署mysql AB复制-详细步骤

    docker部署mysql AB复制 详细步骤 1 安装docker 参考链接 xff1a https blog csdn net qq 50263172 article details 109640641 spm 61 1001 2014
  • mysql 查询特定时间内的操作数量

    查询某几个月中每天的操作量 命令格式 Select DATE FORMAT 字段 39 Y m d 39 AS 34 时间 34 COUNT 1 AS 34 数量 34 FROM 表名 WHERE 字段 gt 39 2021 01 01 0
  • zabbix 邮箱,钉钉报警详解

    1 zabbix部署环境说明 zabbix监控服务器 xff1a mastsc zabbix被监控服务器 xff1a slave 两台机器关闭 34 selinux 34 xff1a setenforce 0 两台机器关闭防火墙 xff1a
  • Centos7离线安装redis

    Centos7离线安装redis 参考文档 xff1a https www cnblogs com yy3b2007com p 10513752 html 1 下载redis安装包 在 opt redis 如没有这个目录需要手动建立 roo
  • zabbix监控使用ping来判断主机是否存活,向邮箱发送邮件报警

    1 安装zabbix监控服务 server 和被监控服务器 slave 安装zabbix参考文档 https blog csdn net qq 50263172 article details 115519613 spm 61 1001 2
  • Feign调用错误no suitable HttpMessageConverter found for response type

    Feign接口 span class token annotation punctuation 64 PostMapping span span class token punctuation span value span class t
  • ubuntu WPS字体缺失 解决方法

    前言 请保证您还有一台windows 文章目录 前言一 在windows复制字体二 复制到ubuntu三 重启WPS总结 一 在windows复制字体 首先在windows下载好WPS xff0c 然后找到字体 xff0c 复制 二 复制到
  • 将IMG等镜像文件转换VMware虚拟机

    先下载好qemu这个转换软件 然后这个软件是用鼠标点不开的 xff0c 先到软件的文件路径然后在路径栏打cmd 或者另一种打开方法 xff0c 在文件所在位置 xff0c 按shift 43 鼠标右键 我这里用第一种 xff0c 接下来两条
  • VNC访问阿里云服务器

    最近阿里云年终特惠 xff0c 新用户服务器只要38一年 xff0c 爱住了呀 xff01 xff01 xff01 果断下单 xff01 买它个一年 xff01 接下来介绍如何通过vnc访问阿里云服务器 一 先要对端口进行开放 在服务器的防
  • ISCSI的部署与安装

    iSCSI xff08 Internet Small Computer System Interface xff0c Internet小型计算机系统接口 xff09 是一种由IBM公司研究开发的IP SAN技术 该技术是将现有SCSI接口与
  • JavaScript 中的相等操作符 ( 详解 [] == []、[] == ![]、{} == !{} )

    一 前言 xff08 比较规则 xff09 JS中的相等操作符由 61 61 表示 xff0c 如果两个操作数相等 xff0c 则返回true 原理 xff1a 相等操作符会先转换操作数 xff08 通常称为强制转型 xff09 xff0c
  • 计算机网络——IP地址与划分子网

    IP地址 1 IP地址表示 对主机和路由器来说 xff0c IP地址用32位二进制代码表示 xff0c 每八位分为一段 xff0c 每段间用空格隔开 xff0c 例如 xff1a 10000000 00001011 00000011 000
  • Snipaste下载安装(使用教程)

    Snipaste下载安装 使用教程 一 简单介绍 Snipaste 是一个免费简单但强大的截图工具 xff0c 也可以让你将截图贴回到屏幕上 xff01 下载并打开 Snipaste xff0c 按下 F1 来开始截图 xff0c 再按 F

随机推荐