• 八大排序算法----堆排序


    堆排序的基本步骤:(以从大到小的顺序排序为例)

    1.构建大顶堆每个结点的值都大于或等于其左右孩子结点的值

    2.排序:每次堆顶的元素取出来(整个堆中值最大),与最后一个节点做交换,使末尾元素最大

    3.交换完之后,需要重新维护堆中剩下的其他节点,保证每次的堆顶都是最大值,重复2,3,直到序列完全有序

    Code:

    1. //维护堆的性质
    2. //大顶堆:父节点的左右孩子都比父节点小
    3. //小顶堆:父节点的左右孩子都比父节点大
    4. void heapify(vector<int>& nums, int n, int i)
    5. {
    6. int large = i;//保存父节点
    7. int left = 2 * i + 1;//左孩子
    8. int right = 2 * i + 2;//右孩子
    9. //判断左孩子是否比父节点大? 大的话,就更新父节点的下标
    10. if (leftnums[large])
    11. large = left;
    12. //判断右孩子是否比父节点大? 大的话,就更新父节点的下标
    13. if (rightnums[large])
    14. large = right;
    15. //到此,已经找到了当前父节点和其左右孩子中最大的节点的下标
    16. //判断父节点的下标是否发生变化,如果不相等,说明左右孩子中有比父节点大的
    17. if (large != i)
    18. {
    19. //交换节点,维护大顶堆
    20. swap(nums[large], nums[i]);
    21. //继续维护剩下的节点
    22. heapify(nums, n, large);
    23. }
    24. }
    25. void heapsort(vector<int>& nums, int n)
    26. {
    27. //建堆:从最后一个有孩子的父节点开始建立
    28. //这里为什么是i = n / 2 - 1? 因为左孩子的下标可以表示为2*i+1,此时最后一个孩子的下标为n-1
    29. //推导过来,找到最后一个有孩子的父节点的下标为n / 2 - 1
    30. for (int i = n / 2 - 1; i >= 0; i--)
    31. {
    32. heapify(nums, n, i);
    33. }
    34. //排序:将大顶堆的顶与最后一个叶子节点进行交换,也就是每次找到当前堆中最大的元素,放在数组的最后面
    35. for (int i = n - 1; i > 0; i--)
    36. {
    37. //交换
    38. swap(nums[i], nums[0]);
    39. //继续维护大顶堆中剩下节点,要始终保持是大顶堆的顺序
    40. heapify(nums, i, 0);
    41. }
    42. }
    43. int main()
    44. {
    45. int n;
    46. cin >> n;
    47. vector<int> nums(n);
    48. for (int i = 0; i < n; i++)
    49. {
    50. cin >> nums[i];
    51. }
    52. heapsort(nums, n);
    53. cout << "按升序顺序排序" << endl;
    54. for (auto& i : nums)
    55. {
    56. cout << i << " ";
    57. }
    58. return 0;
    59. }

    这里如果要按照从小到大的顺序进行堆排序的话,只需要将维护堆的函数中if判断条件做一点小改动即可。

    1. void heapify(vector<int>& nums, int n, int i)
    2. {
    3. int small = i;//保存父节点
    4. int left = 2 * i + 1;//左孩子
    5. int right = 2 * i + 2;//右孩子
    6. if (left
    7. small = left;
    8. if (rightnums[small])
    9. small = right;
    10. //判断父节点的下标是否发生变化,
    11. if (small != i)
    12. {
    13. //交换节点,维护大顶堆
    14. swap(nums[small], nums[i]);
    15. //继续维护剩下的节点
    16. heapify(nums, n, small);
    17. }
    18. }

    堆排序是不稳定的排序算法。

    堆排序的时间复杂度:O(nlogn) 

  • 相关阅读:
    Spring定时器@Scheduled
    Modbus协议
    OpenCV [c++](图像处理基础示例小程序汇总)
    QT基础第三天(3)widget,dialog和mainwindow
    初学者学习JS很吃力怎么办?到底该如何学习JS?
    微服务概述
    小黑leetcode之旅:95. 至少有 K 个重复字符的最长子串
    c++11 动态内存管理-分配器 (std::allocator)
    Linux基础教程:9、linux进程管理(2)
    C#下WinForm多语种切换
  • 原文地址:https://blog.csdn.net/m0_58681055/article/details/132718867