解题思路

  • 大根堆有很好的性质,有助于升序排序
    • 大根堆的根节点一定是最大的,可以用作“选择排序”,一次性选出最大的元素放到末尾
    • 每次调整大根堆的时间复杂度为O(logN)

复杂度分析

时间复杂度:O(NlogN)
空间复杂度:O(1)
是否稳定:不稳定(调整堆的过程中,需要选择交换哪个元素,导致了不稳定性)

代码

  1. #include <vector>
  2. #include <algorithm>
  3. #include <iostream>
  4. using namespace std;
  5. // 将数组中的元素nums[i]放到大根堆中的合适位置
  6. void adjustHeap(vector<int>& nums, int i, int length) {
  7. // 先将nums[i]取出
  8. int temp = nums[i];
  9. // k用来层层遍历左右儿子节点
  10. // i用来找temp的合适的插入位置
  11. for (int k = 2 * i + 1; k < length; k = 2 * k + 1) {
  12. if (k + 1 < length && nums[k + 1] > nums[k]) {
  13. ++k;
  14. }
  15. // 子节点比父节点大,说明需要向下调整
  16. if (nums[k] > temp) {
  17. nums[i] = nums[k];
  18. // 再往下找合适的插入位置
  19. i = k;
  20. } else {
  21. break;
  22. }
  23. }
  24. nums[i] = temp;
  25. }
  26. void heapSort(vector<int>& nums) {
  27. int size = nums.size();
  28. // nums[size/2-1]是第一个非叶节点
  29. for (int i = size / 2 - 1; i >= 0; --i) {
  30. adjustHeap(nums, i, size);
  31. }
  32. for (int i = size - 1; i >= 0; --i) {
  33. swap(nums[0], nums[i]);
  34. adjustHeap(nums, 0, i);
  35. }
  36. }
  37. int main(void) {
  38. vector<int> input {9,8,7,6,5,4,3,2,1};
  39. heapSort(input);
  40. for (const auto& n : input) {
  41. cout << n << " ";
  42. }
  43. return 0;
  44. }

参考资料