当前位置:   article > 正文

数据结构-二叉树-堆

数据结构-二叉树-堆

一、物理结构和逻辑结构

在内存中的存储结构,逻辑结构为想象出来的存储结构。

二、完全二叉树的顺序存储结构

parent = (child - 1)/2

leftchild = 2*parent + 1;

rightchild = 2*parent +2

上面的顺序结构只适合存储完全二叉树。如果存储,会浪费很多的空间。

三、堆

1、堆的分类

小根堆:树中所有的父亲都小于或等于孩子。

大根堆:树中所有的父亲都大于或等于孩子。

接下来我们需要定义一个堆。定义过程如下:

创建堆的时候会涉及到一个向上调整的算法:我们可以画图表示这一过程

  1. void UpAdjust(HPDataType* a, int child)
  2. {
  3. assert(a);
  4. int parent = (child - 1) / 2;
  5. //建立大堆
  6. while (child > 0)
  7. {
  8. if (a[child] > a[parent])
  9. {
  10. //交换两个数字
  11. Swap(&a[child], &a[parent]);
  12. child = parent;
  13. parent = (child - 1) / 2;
  14. }
  15. else
  16. {
  17. break;
  18. }
  19. }
  20. }

删除堆顶数据需要涉及到向下调整

这里不能挪动数据。原因有两个,效率低下,父子兄弟关系全乱了。

思路就是:把头部数据和尾部数据交换。删除尾部数据,然后进行向下调整

这样删除的优点是 效率高,保持了大部分堆的父子关系。

向下调整的过程中我们需要和儿子中最大的进行比较。这样才能保证堆的关系不变。

没有孩子时结束,转换一下就是child < size。

  1. void DownAdjust(HPDataType* a,int parent,int size)
  2. {
  3. int child = 2 * parent + 1;
  4. while (child < size)
  5. {
  6. //选出最大的那一个孩子
  7. if (child + 1 < size && a[child] < a[child + 1])
  8. {
  9. child++;
  10. }
  11. if (a[child] > a[parent])
  12. {
  13. //交换两个数字
  14. Swap(&a[child], &a[parent]);
  15. parent = child;
  16. child = 2 * parent + 1;
  17. }
  18. else
  19. {
  20. break;
  21. }
  22. }
  23. }

整体实现

  1. #include "heap.h"
  2. void HeapInit(HP* hp)
  3. {
  4. assert(hp);
  5. hp->a = (HPDataType*)malloc(sizeof(HPDataType) * SIZE);
  6. hp->size = 0;
  7. hp->capacity = SIZE;
  8. }
  9. void AddCapacity(HP* hp)
  10. {
  11. assert(hp);
  12. if (hp->size == hp->capacity)
  13. {
  14. HPDataType* temp = (HPDataType*)realloc(hp->a, sizeof(HPDataType) * hp->capacity * 2);
  15. if (temp == NULL)
  16. {
  17. perror("realloc failed");
  18. return;
  19. }
  20. hp->a = temp;
  21. hp->capacity *= 2;
  22. }
  23. }
  24. void Swap(int* left, int* right)
  25. {
  26. int temp = *left;
  27. *left = *right;
  28. *right = temp;
  29. }
  30. //除了child的位置,前面的数据构成堆
  31. void UpAdjust(HPDataType* a, int child)
  32. {
  33. int parent = (child - 1) / 2;
  34. //建立大堆
  35. while (child > 0)
  36. {
  37. if (a[child] > a[parent])
  38. {
  39. //交换两个数字
  40. Swap(&a[child], &a[parent]);
  41. child = parent;
  42. parent = (child - 1) / 2;
  43. }
  44. else
  45. {
  46. break;
  47. }
  48. }
  49. }
  50. void HeapPush(HP* hp, HPDataType x)
  51. {
  52. //考虑扩容的问题
  53. AddCapacity(hp);
  54. //插入数据
  55. hp->a[hp->size++] = x;
  56. //还需要考虑向上调整的问题。
  57. UpAdjust(hp->a, hp->size - 1);
  58. }
  59. void DownAdjust(HPDataType* a,int parent,int size)
  60. {
  61. int child = 2 * parent + 1;
  62. while (child < size)
  63. {
  64. //选出最大的那一个孩子
  65. if (child + 1 < size && a[child] < a[child + 1])
  66. {
  67. child++;
  68. }
  69. if (a[child] > a[parent])
  70. {
  71. //交换两个数字
  72. Swap(&a[child], &a[parent]);
  73. parent = child;
  74. child = 2 * parent + 1;
  75. }
  76. else
  77. {
  78. break;
  79. }
  80. }
  81. }
  82. //删除头部的数据
  83. void HeapPop(HP* hp)
  84. {
  85. assert(hp);
  86. assert(!HeapEmpty(hp));
  87. //首先交换头和尾的数字
  88. Swap(&hp->a[0], &hp->a[hp->size-1]);
  89. //然后删除尾的数字
  90. hp->size--;
  91. //向下调整恢复堆的原型 向下调整的左右子树一定是堆
  92. DownAdjust(hp->a, 0, hp->size);
  93. }
  94. HPDataType HeapTop(HP* hp)
  95. {
  96. assert(hp);
  97. return hp->a[0];
  98. }
  99. bool HeapEmpty(HP* hp)
  100. {
  101. assert(hp);
  102. return hp->size == 0;
  103. }
  104. int HeapSize(HP* hp)
  105. {
  106. assert(hp);
  107. return hp->size;
  108. }

四、堆排

对数组进行排序。我们可以把它直接搞成一个堆,建堆操作

1、向上调整建堆

(1)把第一个数看成一个堆中的数。后来的数进行向上调整建立堆。 O(nlogn)

(2)排升序需要建大堆,减小堆关系就都乱了

利用向上调整建大堆时我们可以交换堆头和堆尾的值。然后在进行向下调整选出次小的值,如此往复。

堆排的过程如下

堆排代码:

  1. void HeapSort(int* a,int n)
  2. {
  3. //首先建立大堆
  4. for (int i = 1; i < n; i++)
  5. {
  6. UpAdjust(a, i);
  7. }
  8. //交换堆头和堆尾的数字选出最大的数字放到堆尾
  9. //然后向下调整
  10. int end = n - 1;
  11. while (end > 0)
  12. {
  13. Swap(&a[end], &a[0]);
  14. DownAdjust(a, 0, end);
  15. end--;
  16. }
  17. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/513146
推荐阅读
相关标签
  

闽ICP备14008679号