堆排序是将数组构建成大顶堆,即根节点是数组中最大元素,将根节点与堆底最后一个元素交换,使得最大值排到末尾,即已排序好。将剩下的n-1个元素重新调整为大顶堆,在堆顶/根节点处得到第二大的值,与堆底最后一个元素交换,便又排序好一个元素。
算法描述
- 将数组构建成大顶堆
- 交换堆顶元素和堆底元素
- 调整堆,使其重新成为大顶堆
- 重复步骤2和步骤3 n-1次,排序完成。n为数组长度。
堆分为两类:
- 最大堆(大顶堆):堆的每个父节点都大于其孩子节点;
- 最小堆(小顶堆):堆的每个父节点都小于其孩子节点;
堆的存储:
一般都用数组来表示堆,i结点的父结点下标就为(i – 1) / 2。它的左右子结点下标分别为2 * i + 1和2 * i + 2。
堆排序的步骤分为三步:
- 建堆(升序建大堆,降序建小堆);
- 交换数据;
- 向下调整。
#include<bits/stdc++.h>
using namespace std;
void swap(vector<int>& arr, int i, int j) {
	int tmp = arr[i];
	arr[i] = arr[j];
	arr[j] = tmp;
}
//i位置与其父节点的位置进行比较,如果大于父节点,就交换
void heapInsert(vector<int>& arr, int i) {
	while (arr[i] > arr[(i - 1) / 2]) {
		swap(arr, i, (i - 1) / 2);
		i = (i - 1) / 2;
	}
}
//当大顶堆中某一个元素发生变化的时候,取该元素的左右子节点较大的一个,
//这个最大子节点再和这个修改的元素作比较,子节点大则交换。
void heapify(vector<int>& arr, int size) {
	int i = 0;
	int left = 1;
	int largest;
	while (left < size) {
	    //取该元素的左右子节点较大的一个
		largest = left + 1 < size && arr[left + 1] > arr[left] ? left + 1 : left;
		//比较子节点和被修改元素的大小
		largest = arr[i] > arr[largest] ? i : largest;
		if (largest == i) {
			break;
		}
		swap(arr, largest, i);
		i = largest;
		left = i * 2 + 1;
	}
}
void heapSort(vector<int>& arr) {
	for (int i = 0; i < arr.size(); ++i) {
		heapInsert(arr, i);
	}
	for (int i = arr.size() - 1; i >= 0; --i) {
		swap(arr, 0, i);
		heapify(arr, i);
	}
}
int main() {
	int n;
	cin >> n;
	vector<int> arr(n);
	for (int i = 0; i < n; ++i) {
		cin >> arr[i];
	}
	heapSort(arr);
	for (int i = 0; i < n; ++i) {
		cout << arr[i] << " ";
	}
	cout << endl;
	return 0;
}



 Hewie  回复 @拉大锯
 Hewie  回复 @拉大锯 
















