• 堆排序代码模板


     

     

    1. #include
    2. using namespace std;
    3. const int N = 1e5 + 9;
    4. int h[N], n, m, Size;//小根堆
    5. //u表示三个点中的根节点
    6. void down(int u)
    7. {
    8. int t = u;//设t为三个点中最小的那个点
    9. //如果左儿子存在并且小于根节点就将左儿子赋值给t
    10. if (u * 2 <= Size && h[u * 2] < h[t]) t = u * 2;
    11. //右儿子
    12. if (u * 2 + 1 <= Size && h[u * 2 + 1] < h[t]) t = u * 2 + 1;
    13. //如果传入的节点不是最小值就交换
    14. if (u != t)
    15. {
    16. swap(h[u], h[t]);
    17. down(t);//将原本的根节点沉下来
    18. }
    19. }
    20. int main()
    21. {
    22. ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    23. cin >> n >> m;
    24. //开始创建堆的时候,元素是随机插入的,所以不能从根节点开始down
    25. //而是要找到满足下面三个性质的结点:
    26. //1.左右儿子满足堆的性质。
    27. //2.下标最大(因为要往上遍历)
    28. //3.不是叶子节点(叶子节点一定不满足堆的性质)
    29. for (int i = 1; i <= n; ++i) cin >> h[i];
    30. Size = n;
    31. //时间复杂度为O(n)
    32. //在堆中,每个节点的左子节点的下标为2i,右子节点的下标为2i+1
    33. //假设堆中有n个节点,下标从1到n。我们知道叶子节点是没有子节点的
    34. //所以最后一个非叶子节点的下标一定小于等于n/2。
    35. //首先要明确要进行down操作时必须满足左儿子和右儿子已经是个堆
    36. for (int i = n / 2; i; --i) down(i);
    37. //应该是不能从头往下down吧,down操作是把小数扔上来
    38. //大数扔下去,从头往下down把第一个三角里的最小值扔到第一个位置
    39. //就不再管他了,但是并不能保证其能小于剩下的所有值
    40. //但从下往上down可以保证建堆时全部点完全从小到大
    41. //for (int i = 1; i <= n; i++) down(i);//错误
    42. //for (int i = n; i >= 0; i--) down(i);//正确
    43. //for (int i = n / 2; i >= 0; i--) down(i);//也正确
    44. while (m--)
    45. {
    46. //本题输出最小值需要删除前面的最小值
    47. //原本查询最小值只需要h[1],但是现在是前m个数
    48. //所以需要用到删除第一个数的方法
    49. cout << h[1] << " ";
    50. h[1] = h[Size--];
    51. down(1);//将原本在最后的节点往下沉
    52. }
    53. return 0;
    54. }

  • 相关阅读:
    适用于嵌入式单片机的差分升级通用库+详细教程
    C++的一些好用的限定修饰符
    Exgcd扩展欧几里得
    基于Springboot实现漫画网站平台
    jquery转vue项目总结
    openvswitch group hash实现代码分析
    IDEA2023创建SpringMVC项目
    Linux 将文件中部分内容替换大小写
    HDR图像处理软件 Photomatix Pro mac中文版新增功能
    简单工厂模式、工厂方法模式、抽象工厂模式
  • 原文地址:https://blog.csdn.net/qq_73185160/article/details/133895265