C++堆排序

"本文详细介绍了堆排序算法的原理与步骤,包括如何构建最大堆和如何通过交换堆顶元素实现排序。堆排序的时间复杂度为O(nlogn),空间复杂度为O(1)。提供了一个完整的C++实现示例,展示了从数组{20,30,90,40,70,110,60,10,100,50,80}
摘要由CSDN通过智能技术生成

第一步:
我们将待排序数组形象成一个堆结构,并将其调整为最大堆(堆结构:左孩子的下标是2*i+1,右孩子下标2*i+2)
(最大堆的特点:在这个堆结构里,任何一个父节点的值都大于其子节点的值)
t的值)
第二步:
将堆顶元素与待排序数组(假设待排序的数据数量为nums)最后一个元素进行交换,swap(a[0], a[nums-1]);
第三步:
待排序的数据量减少一个,即num--;将待排序数组重新调整成最大堆结构,重复第二步,循环n-1次,将所有数据排序完成。
初始化堆(讲数组调整成最大堆)
从最后一个父节点开始调整(即i= n/2-1)
下面演示将数组{20,30,90,40,70,110,60,10,100,50,80}转换为最大堆{110,100,90,40,80,20,60,10,30,50,70}的步骤。


 注释代码

//交换函数
void adjustHeap(vector<int> &arr,int start,int end) {
	int father = start;
	int child = 2 * father + 1;//左孩子下标
	while (child < end) {
		//通过这个if条件比较完,child记录的就是较大那个孩子的下标
		//同时还要判断child+1会不会越界
		if (child + 1 < end && arr[child] < arr[child + 1]) {//若右孩子大于左孩子,则左孩子下标+1=右孩子下标
			child++;
		}
		if (arr[child] > arr[father]) {//判断较大的孩子的值是否大于父节点的值,若大,则完成交换
			swap(arr[child], arr[father]);
		}
		else//如果不大于父节点的值,则直接跳出循环,因为尽管以下还有数据,但都是已经交换好的了,因为本函数是从最后一个父节点开始遍历的
		{
			return;
		}
		//如果发生了交换则将当前孩子的下标作为父节点下标
		father = child;
		child = 2 * father + 1;
	}
}

void heapSort(vector<int> &arr) {
	int n = arr.size();
	//从最后一个父节点开始向前调整
	for (int i = n / 2 - 1; i >= 0; i--) {
		adjustHeap(arr, i, n);
	}
	//完成从小到大的排列,每次首尾交换
	//n个数会完成n-1次交换
	while (n - 1) {
		swap(arr[0], arr[n - 1]);
		//从0开始一直排到最后一个数,0即根节点
		adjustHeap(arr, 0, n - 1);
		n--;
	}
}

 完整代码:与上面的大体一样,只是重敲一遍

#include<iostream>
#include<vector>
using namespace std;
void adjustHeap(vector<int>& arr, int start, int end) {
	int father = start;
	int child = 2 * father + 1;
	while (child < end) {
		if (child + 1 < end&&arr[child + 1] > arr[child]) {
			child++;
		}
		if (arr[father] < arr[child]) {
			swap(arr[father], arr[child]);
		}
		else {
			return;
		}
		father = child;
		child = 2 * father + 1;
	}
}
void HeapSort(vector<int>& arr) {
	int n = arr.size();
	if (n <= 1) {
		return;
	}
	for (int i = n / 2; i >= 0; i--) {
		adjustHeap(arr, i, n);
	}
	while (n - 1) {
		swap(arr[0], arr[n - 1]);
		adjustHeap(arr, 0, n - 1);
		n--;
	}
}
void printArr(vector<int>& arr) {
	int n = arr.size();
	for (int i = 0; i < n; i++) {
		cout << arr[i] << "    ";
	}
	cout << endl;
}
int main() {
	vector<int> arr = { 7,9,4,9,8,5 };
	HeapSort(arr);
	printArr(arr);
	return 0;
}

 

堆排序

构建出最大堆的时间复杂度为n

由于是完全二叉树,分log2n层,每次遍历n次

时间复杂度:

因为选择是没有顺序的,所以选择排序不能提前退出,不管是什么序列,都需要执行完整的排序过程。

最优:O(nlogn)

最差:O(nlogn)

平均:O(nlogn)

空间复杂度:

不需要额外的空间占用,所以为O(1)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值