八大排序算法——堆排序

目录

前言

一、向上调整算法建堆

二、向下调整算法建堆 

三、堆排序


前言

        堆排序是基于堆结构的一种排序思想,因此要为一个乱序的数组进行排序的前提是数组必须要是一个堆,所以要先对数组进行建堆操作


一、向上调整算法建堆

        时间复杂度:O( n*logn )

         由于向上调整算法建堆的时间复杂度的证明太过晦涩难懂,还要涉及数学中的错位相减法,所以这里就不证明了,感兴趣的可以自己去了解一下

        这里只需要知道向上调整算法建堆的时间复杂度为 O( n*logn )

//交换两个数的位置
void sweap(int* num1, int* num2)
{
	int tmp = *num1;
	*num1 = *num2;
	*num2 = tmp;
}
//向上调整算法(大根堆)
void AdjustUp(int* arr, int pos)
{
	//当前调整的位置不能是堆顶
	if (pos == 0)
	{
		return;
	}
	//寻找双亲节点
	int parents = (pos - 1) / 2;
	//当前位置与双亲节点进行比较
	//如果当前位置的数大于双亲节点,就进行交换,并且继续向上调整
	//如果当前位置的数小于双亲节点,表示堆已经构建好了
	if (arr[parents] < arr[pos])
	{
		//交换两个数位置
		sweap(&arr[parents], &arr[pos]);
		//继续向上调整
		AdjustUp(arr, parents);
	}
}
int main()
{
	//给定一个乱序数组
	int arr[] = { 8,3,2,6,7,1,4,9,5 };
	//计算数组元素个数
	int size = sizeof(arr) / sizeof(arr[0]);
	//向上调整算法建堆
	//从前往后依次调整建堆
	//先让节点之前的数为堆,然后整体为堆
	for (int i = 0; i < size; i++)
	{
		AdjustUp(arr, i);
	}
	return 0;
}

二、向下调整算法建堆 

         时间复杂度:O( n )

        由于向下调整算法建堆的时间复杂度的证明太过晦涩难懂,还要涉及数学中的错位相减法,所以这里就不证明了,感兴趣的可以自己去了解一下

        这里只需要知道向下调整算法建堆的时间复杂度为 O( n )        

//交换两个数的位置
void sweap(int* num1, int* num2)
{
	int tmp = *num1;
	*num1 = *num2;
	*num2 = tmp;
}
//向下调整算法(大根堆)
void AdjustDown(int* arr, int size, int pos)
{
	//左孩子位置
	int child = pos * 2 + 1;
	//向下调整算法,直到左孩子位置大于数组个数
	if (child < size)
	{
		//选出左右孩子中最大的那个孩子
		if (child + 1 < size && arr[child] < arr[child + 1])
		{
			child++;
		}
		//与当前位置进行比较
		//如果左右孩子中最大数大于当前位置的数,就进行交换,并且继续向下调整
		//如果左右孩子中最大数小于当前位置的数,表示堆已经调整好了
		if (arr[child] > arr[pos])
		{
			//交换两个数的位置
			sweap(&arr[pos], &arr[child]);
			//继续向下调整
			AdjustDown(arr, size, child);
		}
	}
}
int main()
{
	//给定一个乱序数组
	int arr[] = { 8,3,2,6,7,1,4,9,5 };
	//计算数组元素个数
	int size = sizeof(arr) / sizeof(arr[0]);
	//向上调整算法建堆
	//从最后一个叶子节点父节点往前依次调整建堆
	//先让节点的左右子树为堆,然后整体为堆
	int pos = (size - 1) / 2;//最后一个叶子节点父节点
	for (int i = pos; i >= 0; i--)
	{
		AdjustDown(arr, size, i);
	}
	return 0;
}

三、堆排序

         时间复杂度:O( n*logn )

         在进行建堆操作时我们可以选择向上调整算法和向下调整算法,但是由于向下调整算法的时间复杂度要优于向上调整算法,因此更推荐使用向下调整算法建堆

        建堆的时间复杂度为O( n )每次调整的堆结构的时间复杂度为O( logn ) ,因此整体时间复杂度为O( n*logn )

堆排序的过程大致如下:

  1. 将待排序的数组构造成一个大顶堆(或小顶堆,根据需要)。此时,整个数组的最大值(或最小值)就是堆结构的顶端
  2. 将顶端的数与末尾的数交换。此时,末尾的数为最大值(或最小值),剩余待排序数组个数为n-1
  3. 将剩余的n-1个数再构造成大顶堆(或小顶堆),再将顶端数与n-1位置的数交换。如此反复执行,便能得到有序数组

【注意】

  • 排升序要建大堆
  • 排降序要建小堆 

        整体代码实现 

//交换两个数的位置
void sweap(int* num1, int* num2)
{
	int tmp = *num1;
	*num1 = *num2;
	*num2 = tmp;
}

//向下调整算法(大根堆)
void AdjustDown(int* arr, int size, int pos)
{
	//左孩子位置
	int child = pos * 2 + 1;
	//向下调整算法,直到左孩子位置大于数组个数
	if (child < size)
	{
		//选出左右孩子中最大的那个孩子
		if (child + 1 < size && arr[child] < arr[child + 1])
		{
			child++;
		}
		//与当前位置进行比较
		//如果左右孩子中最大数大于当前位置的数,就进行交换,并且继续向下调整
		//如果左右孩子中最大数小于当前位置的数,表示堆已经调整好了
		if (arr[child] > arr[pos])
		{
			//交换两个数的位置
			sweap(&arr[pos], &arr[child]);
			//继续向下调整
			AdjustDown(arr, size, child);
		}
	}
}

//堆排序——升序
void HeapSort(int* arr, int size)
{
	//从后往前依次调整建堆
	//先让节点的左右子树为堆,然后整体为堆
    int pos = (size - 1) / 2;//最后一个叶子节点父节点
	for (int i = pos; i >= 0; i--)
	{
		//向下调整建堆
		AdjustDown(arr, size, i);
	}
	//堆排序
	//排升序要建大堆
	//排降序要建小堆
	for (int i = 0; i < size; i++)
	{
		//堆顶与最后一个有效元素交换位置
		sweap(&arr[0], &arr[size - 1 - i]);
		//向下调整,保持堆的结构
		AdjustDown(arr, size - i - 1, 0);
	}
}

int main()
{
	//给定一个乱序数组
	int arr[] = { 8,3,2,6,7,1,4,9,5 };
	//计算数组元素个数
	int size = sizeof(arr) / sizeof(arr[0]);
	//堆排序
	HeapSort(arr, size);
	//打印排序后的数据
	for (int i = 0; i < size; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

 

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

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

相关文章

2024年医疗人工智能研究报告-生成式AI爆发,医疗人工智能走到新的十字路口(附下载)

前言 2024的医疗AI&#xff0c;既是坎坷&#xff0c;又是新生。 快速发展的大语言模型&#xff0c;携着生成式AI掠过医疗领域。过往的互联网医疗、医学影像、新药研发……一个一个场景经由新一代AI重塑&#xff0c;焕发出前所未有的价值。 不过&#xff0c;发现价值并不意味着…

微信小程序25__实现卡片变换

先看效果图 实现代码如下&#xff1a; <view class"page" style"filter:hue-rotate({{rotation}}deg)"><view class"prev" catchtap"toPrev">《《《</view><view class"next" catchtap"toNext&q…

115页PPT华为管理变革:制度创新与文化塑造的核心实践

集成供应链&#xff08;ISC&#xff09;体系 集成供应链&#xff08;ISC&#xff09;体系是英文Integrated Supply Chain的缩写&#xff0c;是一种先进的管理思想&#xff0c;它指的是由相互间提供原材料、零部件、产品和服务的供应商、合作商、制造商、分销商、零售商、顾客等…

C++进阶-->多态(Polymorphism)

1. 多态的概念 多态&#xff0c;顾名思义多种形态&#xff1b;多态分为编译时多态&#xff08;静态多态&#xff09;和运行时多态&#xff08;动态多态&#xff09;&#xff0c;静态多态就是就是我们前面讲的函数重载和函数模板&#xff0c;可以通过传不同类型&#xff0c;然后…

stm32教程:keil5安装及stm32f1xx系列芯片包下载

早上好啊&#xff0c;大佬们&#xff0c;咱们这个专栏是来浅学一下stm32的内容&#xff0c;然后本篇是一个导言篇&#xff0c;主要是让大家安装好软件&#xff0c;能够正常的进入stm32的学习。 keil5安装包夸克网盘链接&#xff1a; 链接&#xff1a;https://pan.quark.cn/s/1…

保护压缩文件安全:为RAR文件添加密码的两种方法

在日常办公中&#xff0c;给RAR文件设置密码可以保护其中的敏感信息不被随意访问。想要给RAR文件设置密码&#xff0c;需要用到支持RAR格式的解压缩工具&#xff0c;比如WinRAR。本文将介绍WinRAR为RAR文件设置密码的两种常用方法&#xff0c;一起来看看吧&#xff01; 方法一…

【Java语言】类和对象

类 类是用来对一个对象进行描述的&#xff0c;主要描述这个对象哪些属性。 类需要class进行修饰&#xff0c;一个Java文件中可以存在多个类&#xff0c;但是只能存在一个public类且必须与Java文件名相同。eg&#xff1a;有一个Demo.Java文件&#xff0c;在文件中只能存在publi…

大模型系列——AlphaZero/强化学习/MCTS

AlphaGo Zero无需任何人类历史棋谱&#xff0c;仅使用深度强化学习&#xff0c;从零开始训练三天的成就已远远超过了人类数千年积累的围棋知识。 1、围棋知识 &#xff08;1&#xff09;如何简单理解围棋知识 &#xff08;2&#xff09;数子法分胜负&#xff1a;https://zhu…

CSS.导入方式

1.内部样式 在head的style里面定义如 <style>p1{color: brown;}</style> 2.内联样式 直接在标签的里面定义如 <p2 style"color: blue;">这是用了内联样式&#xff0c;蓝色</p2><br> 3.外部样式表 在css文件夹里面构建一个css文件…

LeetCode题(二分查找,C++实现)

LeetCode题&#xff08;二分查找&#xff0c;C实现&#xff09; 记录一下做题过程&#xff0c;肯定会有比我的更好的实现办法&#xff0c;这里只是一个参考&#xff0c;能帮到大家就再好不过了。 目录 LeetCode题&#xff08;二分查找&#xff0c;C实现&#xff09; 一、搜…

ComfyUI初体验

ComfyUI 我就不过多介绍了&#xff0c;安装和基础使用可以看下面大佬的视频&#xff0c;感觉自己靠图文描述的效果不一定好&#xff0c;大家看视频比较方便。 ComfyUI全球爆红&#xff0c;AI绘画进入“工作流时代”&#xff1f;做最好懂的Comfy UI入门教程&#xff1a;Stable D…

STM32G474硬件CRC7和软件CRC7校验

1、CRC7的多项式和初始值 #define CRC_Hardware_POLYNOMIAL_7B 0x09//硬件CRC多项式为0x09 //SD卡中的校验算法CRC7&#xff0c;生成多项式为x^7 x^3 1&#xff0c;由于bit7不存在&#xff0c;只有bit31和bit01&#xff0c;所以多项式为0x09#define CRC7_INIT_VALUE 0…

传输线临界长度

临界长度 临界长度是联结传输线长度与信号反射量之间的一个重要参数。如果用信号在传输线 上的时间延迟来表示传输线长度&#xff0c;临界长度在数值上可表示为 临界长度是传输线末端信号能否达到振铃的最大幅度的传输线长度临界值。传输线长度小于临界长度时&#xff0c;振铃…

微信小程序 - 动画(Animation)执行过程 / 实现过程 / 实现方式

前言 因官方文档描述不清晰,本文主要介绍微信小程序动画 实现过程 / 实现方式。 实现过程 推荐你对照 官方文档 来看本文章,这样更有利于理解。 简单来说,整个动画实现过程就三步: 创建一个动画实例 animation。调用实例的方法来描述动画。最后通过动画实例的 export 方法…

UI设计软件全景:13款工具助力创意实现

选择恰当的UI设计工具对于创建美观且用户体验良好的应用程序界面至关重要。不同的APP功能可能需要不同的界面设计软件&#xff0c;但并非所有工具都需要精通&#xff0c;熟练掌握几个常用的就足够了。以下是13款APP界面设计软件&#xff0c;它们能够为你的团队提供绘制APP界面所…

【动手学强化学习】part2-动态规划算法

阐述、总结【动手学强化学习】章节内容的学习情况&#xff0c;复现并理解代码。 文章目录 一、什么是动态规划&#xff1f;1.1概念1.2适用条件 二、算法示例2.1问题建模2.2策略迭代&#xff08;policyiteration&#xff09;算法2.2.1伪代码2.2.2完整代码2.2.3运行结果2.2.4代码…

2024年【焊工(中级)】最新解析及焊工(中级)考试总结

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 焊工&#xff08;中级&#xff09;最新解析参考答案及焊工&#xff08;中级&#xff09;考试试题解析是安全生产模拟考试一点通题库老师及焊工&#xff08;中级&#xff09;操作证已考过的学员汇总&#xff0c;相对有…

Java题集练习4

Java题集练习4 1 异常有什么用&#xff1f; 用来找到代码中产生的错误 防止运行出错2 异常在java中以什么形式存在&#xff1f; 异常在java中以类的形式存在&#xff0c;分为运行时异常和编译期异常&#xff0c;他们都在类Exception中3 异常是否可以自定义&#xff1f;如何自…

2024年【金属非金属矿山(地下矿山)安全管理人员】考试报名及金属非金属矿山(地下矿山)安全管理人员复审考试

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 金属非金属矿山&#xff08;地下矿山&#xff09;安全管理人员考试报名是安全生产模拟考试一点通生成的&#xff0c;金属非金属矿山&#xff08;地下矿山&#xff09;安全管理人员证模拟考试题库是根据金属非金属矿山…

海洋生物图像分割系统:一键训练

海洋生物图像分割系统源码&#xff06;数据集分享 [yolov8-seg-C2f-EMSCP&#xff06;yolov8-seg-dyhead等50全套改进创新点发刊_一键训练教程_Web前端展示] 1.研究背景与意义 项目参考ILSVRC ImageNet Large Scale Visual Recognition Challenge 项目来源AAAI Global Al l…