堆排序(Heap Sort)

第一步:构建大顶堆

在这里插入图片描述

第二步:将堆顶元素取出(破坏了堆序性),堆尾元素放到堆顶,对新的堆顶元素进行下滤(恢复堆序性),重复此操作。

每次取出的堆顶元素,就是该无序序列的最大值,依次放进堆数组中对应堆尾的下标位置。
这也就是代码中体现的,直接在堆数组中将堆顶元素与堆尾元素交换,再对剔除堆尾的堆进行下滤的过程。
在这里插入图片描述

排序思路
首先,这里采用大顶堆是为了最后升序,显然如果采用小顶堆,最终就是降序;因为排序一般默认都是升序,所以我就选择大顶堆啦。

  1. 将待排序序列构造成一个大顶堆,此时,整个序列的最大值就是堆顶的根节点
  2. 将其与末尾元素进行交换,此时末尾元素就为最大值 ;
  3. 将剩余n-1个元素重新构造成一个堆(注:只有堆顶元素不满足堆序性,所以只需对堆顶元素进行下滤操作),这样操作之后堆顶元素就又是这n-1个元素的最大值。如此反复执行,便能得到一个有序序列了。
/*交换子节点和根节点元素*/
void swap(int* a, int* b) {
	int temp = *a;
	*a = *b;
	*b = temp;
}
/*1:堆化-->构建大顶堆*/
void maxHeapify(int* arr, int N){
	/*对下标为1~N-1的元素分别进行上滤操作(省去新建临时堆空间,挨个插入元素的操作)*/
	for(int i = 1, j; i < N; i++){
		/*上滤*/
		j = i;
		while(j){
			/*左子节点与根节点比较*/
			if(j%2 == 1 && arr[j] > arr[(j-1)/2]){
				swap(&arr[j], &arr[(j-1)/2]);
				j = (j-1)/2;
				continue;
			}
			/*右子节点与根节点比较*/
			if(j%2 == 0 && arr[j] > arr[(j-2)/2]){
				swap(&arr[j], &arr[(j-2)/2]);
				j = (j-2)/2;
				continue;
			}
			/*无元素交换则结束上滤操作*/
			break;
		}
	}
}
/*2:对堆顶元素进行下滤*/
void heapAdjust(int* arr, int index, int N){
	int maxIndex = index;
	int max = arr[index];
	if(2*index + 1 < N && arr[index] < arr[2*index + 1]){
		if(max < arr[2*index + 1]){
			maxIndex = 2*index + 1;
			max = arr[2*index + 1];
		}
	}
	if(2*index + 2 < N && arr[index] < arr[2*index + 2]){
		if(max < arr[2*index + 2]){
			maxIndex = 2*index + 2;
			max = arr[2*index + 2];
		}
	}
	if(maxIndex == index)
		return;
	swap(arr + index, arr + maxIndex);
	heapAdjust(arr, maxIndex, N);
}
/*堆排序*/
void heapSort(int* arr, int N) {
	/*构建大顶堆*/
	maxHeapify(arr, N);
	while(N){ 
		/*堆顶元素与堆尾元素交换*/
		swap(arr, arr+ N - 1);
		/*除去堆尾,对堆顶元素进行下滤,重新调整为大顶堆*/
		heapAdjust(arr, 0, --N);
	}
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值