堆排序C++

//堆排序
#include<iostream>
using namespace std;
void BuildMaxHeap(int* A, int len);
void HeadAdjust(int *A,int k,int len) {//调整以k为根的子树
	A[0] = A[k];
	for (int i = 2 * k; i <=len ; i*=2) {//一直找左孩子结点
		if (i<len&&A[i] < A[i + 1])//判断左右孩子节点哪个大
			i++;
		if (A[0] >= A[i]) break;
		else {
			A[k] = A[i];
				k = i;
		}

	}
	A[k]=A[0];
}

void BuildMaxHeap(int* A, int len) {//建立大根堆
	for (int i = len / 2; i > 0; i--)//从分支节点向前遍历
	{
		HeadAdjust(A,i,len);
	}
}

void HeapSort(int *A,int len) {//堆排序
	BuildMaxHeap(A, len);
	for (int i = len; i >1 ; i--) {
		 A[0] = A[i];//交换第一个和最后一个元素
		 A[i]= A[1];
		 A[1] = A[0];
		 HeadAdjust(A, 1, i-1);//把剩余i-1个元素整理成大根堆
	}
}
int main() {
	int a[9] = { 0,17,65,53,9,32,78,45,87 };
	int i;
	cout<<"建立的大根堆:"<<endl;
	BuildMaxHeap(a, 8);
	for ( i = 1; i < 9; i++)
		cout << a[i] << " ";
	cout<<"\n堆排序:"<<endl;
	HeapSort(a, 8);
	for (i = 1; i < 9; i++)
		cout << a[i] << " ";

	
	return 0;
}
<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、付费专栏及课程。

余额充值