堆排序C++

#include<iostream>
using namespace std;

//headify初始化堆,堆化
//a为待排序的数列,i为当前节点(非叶子节点),n为待排序数列的长度
void heapify(int a[],int i,int n)
{
	int l = 2 * i + 1;//当前节点i的左孩子
	int r = 2 * i + 2;//当前节点i的右孩子
	int largest=i;//首先设置父子节点3个节点中最大值的位置为父节点的下标
	if (l<n && a[l] > a[largest])//l要小于n,否则是数组越界,当l节点的值大于i的值的时候,最大值节点的下标为l 
	{
		largest=l;
	}

	if (r<n && a[r] > a[largest])
	{
		largest=r;
	}

	if (largest!=i)//最大节点不是父节点,要进行交换
	{
		swap(a[i],a[largest]);
		//同时要递归保证子树还是最大堆
		heapify(a,largest,n);
	}
}
//堆排序的算法
void heapsort(int a[],int n)
{
	//建立最大堆,从最后一个非叶子节点开始(n/2-1),自下而上,
	for (int i=n/2-1 ; i>=0 ; i--)
	{
		heapify(a,i,n);
	}
	//调整,将根节点(大顶堆的根节点,也就是最大值)和待排序部分的最后一个节点(下标为 n-1)进行交换,自下而上
	for (int i=n-1; i>0 ;i--)
	{
		swap(a[0],a[i]);
		//待排序数组长度减1,对交换到堆顶的元素进行排序,重复直至排序结束
		heapify(a,0,i);
	}
}


int main()
{
	int b[]={99,89,10,32,6,5,2,8,465,33,7,7};
	int len=sizeof(b)/sizeof(b[0]);
	heapsort(b,len);
	for (int i=0;i<len;i++)
	{
		cout<<b[i]<<" ";
	}
	return 0;
}

参考:https://zhuanlan.zhihu.com/p/75894663
https://www.cnblogs.com/wanglei5205/p/8733524.html
https://www.jb51.net/article/86168.htm
https://jingyan.baidu.com/article/73c3ce284eed31e50343d9fd.html
https://www.cnblogs.com/chengxiao/p/6129630.html

<think>好的,用户想了解C++堆排序的实现示例。首先我需要回忆堆排序的基本原理。堆排序是一种基于二叉堆的排序算法,分为两个主要步骤:构建堆和调整堆。通常使用大顶堆来进行升序排序,或者小顶堆进行降序排序。 接下来,我需要确保提供的代码示例正确且符合C++语法。根据引用[3]和引用[4],堆排序的实现需要两个主要函数:HeapSort和HeapAdjust。HeapSort负责初始化堆结构并进行排序循环,而HeapAdjust用于调整堆以满足堆的性质。 用户可能需要详细的代码解释,所以代码中的注释很重要。例如,在HeapAdjust函数中,需要说明循环的条件以及交换节点的过程。另外,主函数中的示例使用数组来演示排序过程,这样用户可以直观地看到输入和输出。 还需要注意堆排序的时间复杂度分析,最好在回答中提到平均和最坏情况下的复杂度都是O(n log n),以及堆排序是不稳定的排序算法。这些信息能帮助用户更好地理解其性能和应用场景。 用户提供的引用中有提到堆排序与其他排序算法的比较,比如快速排序在特定情况下的性能问题。可能用户在实际应用中遇到了性能问题,想通过堆排序来优化。因此,在相关问题中,可以推荐堆排序的适用场景,比如数据量大或需要稳定性时。 最后,确保代码示例中的语法正确,比如循环的范围、数组索引是否正确。例如,在构建堆时,从最后一个非叶子节点开始,即i=length/2-1,这一点需要正确体现在代码中。此外,交换堆顶元素和末尾元素后,调整堆的范围需要逐渐缩小,避免重复处理已排序的元素。 总结一下,回答需要包含清晰的代码示例、分步解释、时间复杂度分析以及相关问题,帮助用户全面理解堆排序C++实现。</think>以下是C++实现堆排序的详细代码示例及分步解释: ### 堆排序实现步骤 1. **构建大顶堆**:从最后一个非叶子节点开始向上调整 2. **堆调整**:保持父节点值大于子节点值 3. **排序循环**:将堆顶元素交换至末尾,缩小堆范围后重新调整 ### C++代码实现 ```cpp #include <iostream> using namespace std; // 调整堆(大顶堆) void HeapAdjust(int* arr, int parent, int length) { int temp = arr[parent]; // 保存父节点值 int child = 2 * parent + 1; // 左子节点索引 while (child < length) { // 选择较大的子节点 if (child + 1 < length && arr[child] < arr[child + 1]) { child++; // 切换到右子节点 } // 父节点值最大时停止调整 if (temp >= arr[child]) break; // 将子节点值赋给父节点位置 arr[parent] = arr[child]; parent = child; // 移动到子节点位置继续调整 child = 2 * parent + 1; } arr[parent] = temp; // 最终放置原始父节点值 } // 堆排序主函数 void HeapSort(int* arr, int length) { // 构建初始大顶堆(从最后一个非叶子节点开始) for (int i = length/2 - 1; i >= 0; i--) { HeapAdjust(arr, i, length); } // 依次取出堆顶元素进行排序 for (int j = length - 1; j > 0; j--) { swap(arr[0], arr[j]); // 将最大值移到末尾 HeapAdjust(arr, 0, j); // 调整剩余元素为堆(范围缩小) } } // 测试示例 int main() { int arr[] = {3, 5, 3, 0, 8, 6, 1, 5}; int length = sizeof(arr)/sizeof(arr[0]); HeapSort(arr, length); cout << "排序结果: "; for (int i = 0; i < length; i++) { cout << arr[i] << " "; } return 0; } ``` ### 关键特性 1. **时间复杂度**:始终为$O(n \log n)$,无论数据是否有序[^4] 2. **空间复杂度**:$O(1)$,原地排序算法 3. **稳定性**:非稳定排序(交换操作可能导致相同元素顺序改变) 4. **适用场景**:大数据量排序、优先队列实现、需要保证最坏情况性能的排序需求 ### 性能对比 根据引用[1],当处理逆序数组时,快速排序会退化为$O(n^2)$时间复杂度,而堆排序仍保持$O(n \log n)$的性能优势。在LeetCode等算法测试中,堆排序常被用于规避快速排序的最坏情况问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值