• 数据结构之堆的实现(图解➕源代码)


    一、堆的定义

            首先明确堆是一种特殊的完全二叉树,分为大根堆和小根堆,接下来我们就分别介绍一下这两种不同的堆。

    1.1 大根堆(简称:大堆)

            在大堆里面:父节点的值 ≥ 孩子节点的值

            我们的兄弟节点没有限制,只要保证每个父节点都≥孩子节点就行。

    1.2 小根堆(简称:小堆)

            在小堆里面:父节点的值  孩子节点的值

            同样兄弟节点也没有限制,只要保证每个父节点都≤孩子节点就行。

    这里就又用到了我们的父节点和孩子节点的位置关系了,我们可以用顺序结构来模拟完全二叉树,也就是数组来实现,话不多说,直接给公式和图形:

    parent = (child-1)/2;   (任意一个child节点)

    child1 = parent*2 + 1;

    child2 = parent*2 + 2;

    这里是运用数组下标进行计算

    二、堆的实现

            我们形成堆有两种方法,一种是向下调整,一种是向上调整,在未来,经常会用到向下调整,所以我们只介绍这种方法。

    2.1 向下调整法

            什么是向下调整呢?就是把我们的完全二叉树从从上往下建堆,使用向下调整法的前提就是根的左右子树必须是堆。

    首先我们要建小堆,先找到同一层的小的那个和父节点交换,以此类推,直到10到叶节点或者没有比他小的。

    2.2 堆的定义

    在这里我们的堆的存储结构都是数组,所以在定义的时候跟定义顺序表一样,只不过在插入删除上有区别

    1. typedef struct Heap
    2. {
    3. int* arr;
    4. int capacity; //数组的容量
    5. int size; //有效的元素个数
    6. }Heap;

    2.3 堆的初始化

    1. //堆的初始化
    2. void HeapInit(Heap* php)
    3. {
    4. assert(php);
    5. php->arr = NULL;
    6. php->capacity = 0;
    7. php->size = 0;
    8. }

    2.4 堆的创建

    1. //堆的创建
    2. void HeapCreate(Heap* php)
    3. {
    4. assert(php);
    5. if(php->size == php->capacity)
    6. {
    7. int newCapacity = php->capacity == 0 ? 4 : (php->capacity)*2;
    8. int* data = (int*) realloc(php->arr,sizeof (int)*newCapacity);
    9. if(data == NULL)
    10. {
    11. perror("malloc fail");
    12. exit(-1);
    13. }
    14. php->arr = data;
    15. php->capacity = newCapacity;
    16. }
    17. }

    2.5 堆的销毁

    1. //堆的销毁
    2. void HeapDestroy(Heap* php)
    3. {
    4. assert(php);
    5. free(php->arr);
    6. php->arr = NULL;
    7. php->size = 0;
    8. php->capacity = 0;
    9. }

    2.6 堆的插入

    在插入这里我们就要建堆了,但是由于我们的数据是顺序插入的,所以没有办法进行向下调整,这里使用向上调整的方法,原理都是一样的,向上调整就要保证插入的节点以上是堆。

    1. void Swap(int* x,int* y)
    2. {
    3. int tmp = *x;
    4. *x = *y;
    5. *y = tmp;
    6. }
    7. //建立大堆,向上调整
    8. void AdjustUp(int* arr,int child)
    9. {
    10. int parent = (child-1)/2;
    11. while (child > 0)
    12. {
    13. if(arr[child] > arr[parent])
    14. {
    15. Swap(&arr[child],&arr[parent]);
    16. child = parent;
    17. parent = (child-1)/2;
    18. }
    19. else
    20. break;
    21. }
    22. }
    23. //堆的插入
    24. void HeapPush(Heap* php,int x)
    25. {
    26. HeapCreate(php);
    27. php->arr[php->size] = x;
    28. php->size++;
    29. //建立大堆
    30. AdjustUp(php->arr,php->size-1);
    31. }

    2.7 删除根节点

    1. void Swap(int* x,int* y)
    2. {
    3. int tmp = *x;
    4. *x = *y;
    5. *y = tmp;
    6. }
    7. //建立大堆,向下调整
    8. void AdjustDown(int*arr,int parent,int size)
    9. {
    10. int child = parent*2 + 1;
    11. while (child < size)
    12. {
    13. if(child + 1 < size && arr[child] > arr[child+1])
    14. {
    15. child = child + 1;
    16. }
    17. if(arr[child] < arr[parent])
    18. {
    19. Swap(&arr[child],&arr[parent]);
    20. parent = child;
    21. child = parent*2 + 1;
    22. }
    23. else
    24. break;
    25. }
    26. }
    27. //堆的删除
    28. void HeapPop(Heap* php)
    29. {
    30. assert(php);
    31. assert(!HeapEmpty(php));
    32. Swap(&php->arr[0],&php->arr[php->size-1]);
    33. php->size--;
    34. AdjustDown(php->arr,0,php->size);
    35. }

    2.8 取堆顶的数据

    1. //堆的根节点
    2. int HeapTop(Heap* php)
    3. {
    4. assert(php);
    5. assert(!HeapEmpty(php));
    6. return php->arr[0];
    7. }

    2.9 判断堆是否为空

    1. //判断堆是否为空
    2. bool HeapEmpty(Heap* php)
    3. {
    4. assert(php);
    5. return php->size == 0;
    6. }

    2.10 堆的数据个数

    1. //堆的节点个数
    2. int HeapSize(Heap* php)
    3. {
    4. assert(php);
    5. return php->size;
    6. }

  • 相关阅读:
    ASP.NETCore统一处理404错误都有哪些方式?
    uniapp h5使用原生的input标签
    Thymeleaf语法详解
    Docker私库
    交易所通用质押式回购
    SpringBoot注解
    BUUCTF Misc ningen1 & 小明的保险箱1 & 爱因斯坦1 & easycap1
    如何使用 nvm-windows 这个工具来管理你电脑上的Node.js版本
    Python爬虫协程批量下载图片
    用python解决这个问题
  • 原文地址:https://blog.csdn.net/2302_76941579/article/details/134209256