解题思路
- 大根堆有很好的性质,有助于升序排序
- 大根堆的根节点一定是最大的,可以用作“选择排序”,一次性选出最大的元素放到末尾
- 每次调整大根堆的时间复杂度为
O(logN)
复杂度分析
时间复杂度:O(NlogN)
空间复杂度:O(1)
是否稳定:不稳定(调整堆的过程中,需要选择交换哪个元素,导致了不稳定性)
代码
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
// 将数组中的元素nums[i]放到大根堆中的合适位置
void adjustHeap(vector<int>& nums, int i, int length) {
// 先将nums[i]取出
int temp = nums[i];
// k用来层层遍历左右儿子节点
// i用来找temp的合适的插入位置
for (int k = 2 * i + 1; k < length; k = 2 * k + 1) {
if (k + 1 < length && nums[k + 1] > nums[k]) {
++k;
}
// 子节点比父节点大,说明需要向下调整
if (nums[k] > temp) {
nums[i] = nums[k];
// 再往下找合适的插入位置
i = k;
} else {
break;
}
}
nums[i] = temp;
}
void heapSort(vector<int>& nums) {
int size = nums.size();
// nums[size/2-1]是第一个非叶节点
for (int i = size / 2 - 1; i >= 0; --i) {
adjustHeap(nums, i, size);
}
for (int i = size - 1; i >= 0; --i) {
swap(nums[0], nums[i]);
adjustHeap(nums, 0, i);
}
}
int main(void) {
vector<int> input {9,8,7,6,5,4,3,2,1};
heapSort(input);
for (const auto& n : input) {
cout << n << " ";
}
return 0;
}