当前位置:   article > 正文

【数据结构】——堆的实现(赋源码)

【数据结构】——堆的实现(赋源码)

堆的概念与结构

堆(Heap)是计算机科学中一类特殊的数据结构,是最高效的优先级队列。堆通常是一个可以被看作一棵完全二叉树的数组对象。

堆的性质:

  • 堆中某个结点的值总是不大于或不小于其父结点的值;

  • 堆总是一棵完全二叉树。 

    堆的物理结构本质上是顺序存储的,是线性的。但在逻辑上不是线性的,是完全二叉树的这种逻辑储存结构。 堆的这个数据结构,里面的成员包括一维数组,数组的容量,数组元素的个数,有两个直接后继。

 

二叉树性质: 

对于具有 n 个结点的完全⼆叉树,如果按照从上至下从左至右的数组顺序对所有结点从 0 开始编号,则对于序号为 i 的结点有:

1. 若 i>0 , i 位置结点的双亲序号:(i  - 1)/ 2;i 等于0时,i为根结点,没有双亲结点。

2. 若 2i+1 < n,左孩子序列: 2i+1,    2i+1>=n 否则⽆左孩⼦。

3. 若 2i+2 < n,右孩子序列: 2i+2,    2i+2>=n否则无右孩子

堆的实现

堆底层结构为数组,因此定义堆的结构为:

  1. typedef int HPDataType;
  2. typedef struct Heap
  3. {
  4. HPDataType* arr;
  5. int size;
  6. int capacity;
  7. }HP;
  8. //默认初始化堆
  9. void HPInit(HP* php);
  10. //堆的销毁
  11. void HPDestroy(HP* php);
  12. //堆的插⼊
  13. void HPPush(HP* php, HPDataType x);
  14. //堆的删除
  15. void HPPop(HP* php);
  16. //出堆数据
  17. HPDataType HPTop(HP* php);
  18. // 判空
  19. bool HPEmpty(HP* php);
  20. //交换
  21. void swap(int* x, int* y);
  22. //向下调整算法
  23. void AdjustDown(HPDataType* arr, int parent, int n);
  24. //向上调整算法
  25. void AdjustUp(HPDataType* arr, int child);

堆的初始化

  1. void HPInit(HP* php)
  2. {
  3. assert(php);
  4. php->arr = NULL;
  5. php->capacity = php->size = 0;
  6. }

堆的销毁

  1. void HPDestroy(HP* php)
  2. {
  3. assert(php);
  4. if (php->arr)
  5. free(php->arr);
  6. php->arr = NULL;
  7. php->capacity = php->size = 0;
  8. }

交换以及向上、向下调整算法

  1. void swap(int* x, int* y)
  2. {
  3. int tmp = *x;
  4. *x = *y;
  5. *y = tmp;
  6. }
  7. //建大堆还是小堆将两个算法的第一个判断条件修改相反即可
  8. //向上调整
  9. void AdjustUp(HPDataType* arr,int child)
  10. {
  11. int parent = (child - 1) / 2;//根据子结点求父结点
  12. while (child > 0)//直到子结点为根结点即循环停止
  13. {
  14. // >
  15. if (arr[child] < arr[parent])//子结点小就交换,创建小堆
  16. {
  17. swap(&arr[child], &arr[parent]);
  18. child = parent;
  19. parent = (child - 1) / 2;
  20. }
  21. else
  22. {
  23. break;
  24. }
  25. }
  26. }
  27. //向下调整
  28. void AdjustDown(HPDataType* arr, int parent, int n)
  29. {
  30. int child = parent * 2 + 1;
  31. while (child < n)
  32. {
  33. //小堆:找左右孩子中找最小的
  34. //大堆:找左右孩子中找大的
  35. // <
  36. if (child + 1 < n && arr[child] > arr[child + 1])
  37. {
  38. child++;
  39. }
  40. // >
  41. if (arr[child] < arr[parent]) //小堆,什么时候交换? 孩子比父亲小
  42. {
  43. swap(&arr[child], &arr[parent]);
  44. parent = child;
  45. child = parent * 2 + 1;
  46. }
  47. else
  48. {
  49. break;
  50. }
  51. }
  52. }

 堆的插入

  1. void HPPush(HP* php, HPDataType x)
  2. {
  3. assert(php);
  4. //扩容
  5. if (php->capacity == php->size)
  6. {
  7. int newcapacity = php->capacity == 0 ? 4 : 2 * php->capacity;
  8. HPDataType* tmp = (HPDataType*)realloc(php->arr, newcapacity * sizeof(HPDataType));
  9. if (tmp == NULL)
  10. {
  11. perror("realloc fail!");
  12. exit(1);
  13. }
  14. php->arr = tmp;
  15. php->capacity = newcapacity;
  16. }
  17. php->arr[php->size] = x;
  18. AdjustUp(php->arr, php->size);
  19. ++php->size;
  20. }

 堆的删除

  1. void HPPop(HP* php)
  2. {
  3. assert(php && php->size);
  4. swap(&php->arr[0], &php->arr[php->size - 1]);
  5. --php->size;
  6. AdjustDown(php->arr, 0, php->size);
  7. }

判空以及出数据

  1. // 判空
  2. bool HPEmpty(HP* php)
  3. {
  4. assert(php);
  5. return php->size == 0;
  6. }
  7. //出堆数据
  8. HPDataType HPTop(HP* php)
  9. {
  10. assert(php && php->size);
  11. return php->arr[0];
  12. }

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

闽ICP备14008679号