鱼C论坛

 找回密码
 立即注册
查看: 80|回复: 0

[学习笔记] 堆和优先队列

[复制链接]
发表于 2025-10-9 15:49:58 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 pyzyd 于 2025-10-11 15:56 编辑

堆有最大堆和最小堆,

堆是完全二叉树,
要求:
1.每个父节点大于(或小于)等于其子节点,左右子节点没有大小要求
2.堆最多只能有一个单个的左子节点,不能有多个结点,不能是单个的右子节点
  1.      90
  2.     /  \
  3.    70   80
  4.   / \   / \
  5. 60  20 75 50

  6. 这就是一个最大堆

  7. 错误示例
  8.      1
  9.     / \
  10.    2   3
  11.   /   /
复制代码


堆的代码实现
  1. /*
  2. 堆是特殊的树,
  3. 堆是完全二叉树,
  4. 堆中每一个节点的值都大于或等于其左右孩子节点的值,称为大顶堆(最大堆);
  5. 堆中每一个节点的值都小于或等于其左右孩子节点的值,称为小顶堆(最小堆)。
  6. 堆可以用数组表示,数组中第i个元素,其左孩子为2i+1,右孩子为2i+2。
  7. */

  8. #include <cstring>
  9. #include <iomanip>
  10. #include <iostream>
  11. #include <string>
  12. #include <cmath>

  13. #define DEFAULT_CAPCITY 128

  14. typedef int DataType;

  15. typedef struct _Heap {
  16.     DataType *data;
  17.     int size;
  18.     int capacity;
  19. } Heap;

  20. bool initHeap(Heap &heap, int *original, int size);
  21. bool insert(Heap &heap, DataType value);
  22. static void buildHeap(Heap &heap);
  23. static void adjustDown(Heap &heap, int index);
  24. static void adjustUp(Heap &heap, int index);


  25. int main() {
  26.     Heap hp;
  27.     int origVals[] = {1, 2, 3, 87, 93, 82, 92, 86, 95};
  28.     if (!initHeap(hp, origVals, sizeof(origVals) / sizeof(origVals[0]))) {
  29.         std::cerr << "init heap failed!" << std::endl;
  30.         return -1;
  31.     }

  32.     if (typeid(1.0) == typeid(float)) {
  33.         std::cout << "1.0 is float" << std::endl;
  34.     } else {
  35.         std::cout << "1.0 is double" << std::endl;
  36.     }
  37.     insert(hp, 100);
  38.     return 0;
  39. }


  40. bool initHeap(Heap &heap, int *original, int size) {
  41.     if (original == nullptr || size <= 0) {
  42.         return false;
  43.     }
  44.     heap.capacity = DEFAULT_CAPCITY > size ? DEFAULT_CAPCITY : size;
  45.     heap.data = new DataType[heap.capacity];
  46.     if (!heap.data) {
  47.         return false;
  48.     }
  49.     memcpy(heap.data, original, size * sizeof(int));
  50.     heap.size = size;
  51.     buildHeap(heap);
  52.     return true;
  53. }

  54. bool insert(Heap &heap, DataType value) {
  55.     if (heap.size == heap.capacity) {
  56.         return false;
  57.     }
  58.     int index = heap.size++;
  59.     heap.data[index] = value;
  60.     adjustUp(heap, index);
  61.     return true;
  62. }

  63. /*
  64. 从最后一个非叶子结点(父节点 size / 2 - 1
  65. 的位置)逐个往前调整所有父节点(直到根节点),
  66. 确保每一个父节点都是一个最大堆,最终整个堆就是一个最大堆。
  67. */
  68. static void buildHeap(Heap &heap) {
  69.     int i;
  70.     for (i = heap.size / 2 - 1; i >= 0; i--) {
  71.         adjustDown(heap, i);
  72.     }
  73. }

  74. /*
  75. 将当前节点和子节点调整成最大堆
  76. */
  77. static void adjustDown(Heap &heap, int index) {
  78.     int cur = heap.data[index];
  79.     int parent, child;
  80.     for (parent = index; (parent * 2 + 1) < heap.size; parent = child) {
  81.         child = parent * 2 + 1;
  82.         // 比较左子节点和右子节点,取较大的那个
  83.         if ((child + 1) < heap.size &&
  84.             heap.data[child] < heap.data[child + 1]) {
  85.             child++;
  86.         }
  87.         // 如果当前节点大于等于最大子节点,则不需要调整
  88.         if (cur >= heap.data[child]) {
  89.             break;
  90.         } else {
  91.             // 否则,将当前节点和最大子节点交换
  92.             heap.data[parent] = heap.data[child];
  93.             heap.data[child] = cur;
  94.         }
  95.     }
  96. }

  97. static void adjustUp(Heap &heap, int index) {
  98.     if (index < 0 || index >= heap.size) {
  99.         return;
  100.     }
  101.     while (index > 0) {
  102.         int parent = (index - 1) / 2;
  103.         if (heap.data[index] <= heap.data[parent]) {
  104.             break;
  105.         }

  106.         // 交换当前节点与父节点
  107.         int temp = heap.data[index];
  108.         heap.data[index] = heap.data[parent];
  109.         heap.data[parent] = temp;

  110.         index = parent;
  111.     }
  112. }
复制代码


小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-10-17 04:18

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表