首页 > 编程语言 >算法与数据结构——堆排序

算法与数据结构——堆排序

时间:2024-10-17 10:31:55浏览次数:1  
标签:ma 堆化 nums int 元素 堆排序 算法 数据结构 节点

堆排序

堆排序(heap sort)是一种基于堆数据结构实现的高效排序算法。我们可以利用已经学过的“建堆操作”和“元素出堆操作”实现堆排序。

  • 输入数组并建立小顶堆,此时最小元素位于堆顶。
  • 不断执行出堆操作,依次记录出堆元素,即可得到从小到大排序的序列。

以上方法虽然可行,但需借助一个额外数组来保存弹出的元素,比较浪费空间。在实际中,我们通常使用一种更加优雅的实现方式。

算法流程

设数组长度为n,对排序流程如下所示。

  1. 输入数组并建立大顶堆。完成后,最大元素位于堆顶。
  2. 将堆顶元素(第一个元素)与堆底元素(最后一个元素)交换。完成交换后,堆的长度减1,已排序元素数量加1。
  3. 从堆顶元素开始,从顶至底执行堆化操作(sift down)。完成堆化后,堆的性质得到修复。
  4. 循环执行第2.步和第3.步。循环n-1轮后,即可完成数组排序。






在代码实现中,我们使用了与“堆”相同的从顶至底堆化sift_down()函数。值得注意的是,由于堆的长度会随着提取最大元素而减小,因此我们需要给sift_down()函数添加一个长度参数n,用于指定堆的当前有效长度。

#include "iostream"
#include "vector"
using namespace std;
/*从顶至底堆化*/
void sift_down(vector<int> &nums, int n, int i){
	while (true){
		// 判断节点 i, l, r 中值最大的节点,记为 ma
		int l = 2 * i + 1;
		int r = 2 * i + 2;
		int ma = i;
		if (l < n  && nums[l] > nums[ma]){
			ma = l;
		}
		if (r < n &&nums[r] > nums[ma]){
			ma = r;
		}
		// 若节点 i 最大或索引 l, r 越界,则无须继续堆化,跳出
		if (ma == i) break;
		// 交换两节点
		swap(nums[i], nums[ma]);
		// 循环向下堆化
		i = ma;
	}
	
}
/*堆排序*/
void heap_sort(vector<int> &nums){
	// 建堆操作:堆化除叶节点之外的其他所有节点
	for (int i = nums.size() / 2 - 1; i >= 0; --i){
		sift_down(nums, nums.size(), i);
	}
	// 从堆中提取最大元素,循环 n - 1 轮
	for (int i = nums.size() - 1; i > 0; --i){
		// 交换根节点与最右叶节点(交换首元素与尾元素)
		swap(nums[0], nums[i]);
		// 以根节点为起点,从顶至底进行堆化
		sift_down(nums, i, 0);
	}
}
int main(){
	vector<int> nums = { 12, 33, 5, 4, 66, 7, 2 };
	heap_sort(nums);
	for (int num : nums){
		cout << num << " ";
	}
	cout << endl;

	system("pause");
	return 0;
}

算法特性

  • 时间复杂度为O(nlogn)、非自适应排序:建堆操作使用O(n)时间。从堆中提取最大元素的时间复杂度为O(logn),总共循环n-1轮。
  • 空间复杂度为O(1)、原地排序:几个指针变量使用O(1)空间。元素交换和堆化操作都是在原数组上进行的。
  • 非稳定排序:在交换堆顶元素和堆底元素时,相等元素的相对位置可能发生变化。

标签:ma,堆化,nums,int,元素,堆排序,算法,数据结构,节点
From: https://www.cnblogs.com/1873cy/p/18470293

相关文章

  • go 基于推特雪花算法生成定长id
    基于推特雪花算法生成定长id,属于int64类型。1BitUnused|41BitTimestamp|10BitNodeID|12BitSequenceID1bit未使用,默认是0。41bit存储毫秒级时间戳,当前时间与Nov04201001:42:54UTC的时间差。10bit存储节点的id,最多支持1024个。12bit自增id,同1个节点在1秒内最多......
  • 206号资源-源程序:2024年新智能优化算法-鹦鹉优化算法---------已提供下载资源
    ......
  • 数模创新算法篇 | 基于CEEMDAN分解与LSTM模型的电力负荷预测
    目录 废话不多说,直接上目录问题背景与理论1.长短期记忆网络(LSTM)理论2.CEEMDAN分解理论3.LSTM与CEEMDAN结合的优势4.应用场景与前景Python代码实操导入库和准备数据备注定义数据整理函数定义LSTM模型构建函数数据处理和模型训练评估模型性能绘制预测结果图......
  • 必学的排序算法——冒泡排序
    目录前言一、什么是冒泡排序二、冒泡排序的的基本步骤三、冒泡排序的特点四、冒泡排序算法图解五、经典例题1.合并两个有序数组代码题解2.元素计数代码题解3.最后一块石头的重量代码题解六、结语前言冒泡排序算法是必须掌握的一种基础算法,在一些比较出名的竞赛可......
  • C++算法练习-day1——704.二分查找
    题目来源:.-力扣(LeetCode)题目思路分析二分查找是一种在有序数组中查找某一特定元素的搜索算法。搜索过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜索过程结束;如果某一特定元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找,而且跟开始一样从......
  • 路径规划——RRT、RRT*、RRT-Connect算法说明
    1.RRT伪代码RRT的目标是在状态空间中随机采样并扩展树结构,直到找到连接起点和终点的路径。RRT(Rapidly-exploringRandomTree,快速随机扩展树)是一种用于解决运动规划问题的采样算法。它通过随机采样的方式,逐步构建一棵树,直到找到一条从起始状态到目标状态的路径。RRT算法的......
  • 机器学习篇-day08-聚类Kmeans算法
    一.聚类算法简介概念无监督学习算法根据样本之间的相似性,将样本划分到不同的类别中;不同的相似度计算方法,会得到不同的聚类结果,常用的相似度计算方法有欧式距离法。聚类算法的目的是在没有先验知识的情况下,自动发现数据集中的内在结构和模式。使用不同的聚类准则,产生的......
  • 【面试经验】美团搜索推荐算法工程师面经(已OC)
    一共只面了两轮,9.3一面,9.9二面,没有HR面,9.20OC一面/技术面2024/9/3晚上20:00-21:00自我介绍腾讯实习介绍实习过程中做的比较好的部分有哪些华为框架以及NPU使用过程中遇到的问题LongLoRA和LoRA区别大模型和推荐你觉得有哪些可结合的点?商品的理解、描述等介绍快手......
  • 【面试经验】美团 大模型算法工程师 一面面经
    预训练数据收集流程隐私过滤是怎么做的怎么用OCR算法解决读取pdf公式语料以及双栏pdf的问题预训练数据集构建中的亮点数据质量评估方式垂域评测集的构建方式微调评测集是怎么做的,全参微调还是lora,lora原理图文模型是怎么做的没有八股,coding是旋转图像和编辑距离二选......
  • 【面试经验】美团搜推算法日常(已oc)
    一面手撕重排链表,k个最小元素秒了,面试官后续引导我大根堆优化,没get到,说没关系前面的算我做出来了论文环节,问的不细,大体问了下思路SGD、AdaGrad、Adam的区别,各自适用场景用过什么损失函数实际用过什么attention:GAT,targetattention和selfattention结束后马上电话......