• 【数据结构】二叉树中 堆的实现方法


    目录

    一. 树以及树相关的概念

    二. 二叉树的概念以及结构;

    三. 堆与二叉树:

    1.什么是堆?与二叉树有什么关系?

    2.堆的存储结构:

     3.堆的实现:

    1. 创建结构体变量:

    2. Push插入函数

    3.Printf打印函数:

    4.Pop删除函数:

    5.其他简单函数:

    6.检验案例:


    一. 树以及树相关的概念

    树是一种非线性的数据结构,它是由N个有限节点组成的具有层次关系的集合。同时树形结构中不能具有交集,否则就不是树形结构。

    像这样下图的上三个都不能被称作树;

    节点的度:一个节点含有的子树的个数称为该节点的度;

    叶节点或终端节点:度为0的节点称为叶节点;

    双亲节点或父节点:若一个节点含有子节点,则这个节点称为其子节点的父节点;

    孩子节点或子节点:一个节点含有的子树的根节点称为该节点的子节点;

    兄弟节点:具有相同父节点的节点互称为兄弟节点;

    节点的层次:从根开始定义起,根为第1层,根的子节点为第2层,以此类推;

    树的高度或深度:树中节点的最大层次;

    森林:由M(M > 0)棵互不相交的树的集合称为森林;

    二. 二叉树的概念以及结构;

    一棵二叉树是结点的一个有限集合,该集合:
    1. 为空;
    2. 由一个根节点加上两棵别称为左子树和右子树的二叉树组成;

     由图可以看出来:二叉树节点的度都不能大于 2;二叉树有左子树右子树之分,是有序树;

    还有两个特殊的二叉树:

    满二叉树:根据名字很容易理解,就是每个枝桠上都用两个分桠(最后一层除外)它的总节点数为 2^k - 1 K为层数。

    完全二叉树:完全二叉树是效率很高的数据结构,完全二叉树是由满二叉树而引出来的。对于层数为K的,有n个结点的二叉树,当且仅当其每一个结点都与层数为K的满二叉树中编号从1至n的结点一一对应时称之为完全二叉树。 要注意的是满二叉树是一种特殊的完全二叉树,它的总结点数的范围为[2^(k-1) - 1 ,  2^k - 1]。

    三. 堆与二叉树:

    1.什么是堆?与二叉树有什么关系?

    堆:有一组集合 的元素按照完全二叉树的顺序储存方式存储到一个一维数组中,根据存储的顺序不同分为小堆与大堆。

    2.堆的存储结构:

    堆 形象逻辑上的 结构是树形的 如下图的(a) 抽象的实际的储存结构是 以顺序表的形式 来存储的。

    下标的表示方法 从上到下 从左到右依次变大;

    任何一个孩子与双亲节点都有下面这种关系:

     3.堆的实现:

    1. 创建结构体变量:

    1. typedef struct Heap
    2. {
    3. int* a;
    4. int capacity;
    5. int size;
    6. }Heap;

    2. Push插入函数

    先来看 Push 函数; 我们的堆 当进行插入的时候还要必须保持堆的结构;当我们插入的数 并不符合 这个 堆的结构的时候 我们要思考如何将 新插入的数与原堆融为一体?我们需要将 不符合结构的这个数与它的双亲节点进行互换 就行了; 用代码来实现就是这样:

    我们将向上调整的方法进行封装成函数,有了利于实现 低耦合 高内聚 的特点;

    1. swap(int* x, int* y)
    2. {
    3. assert(x && y);
    4. int tmp = *x;
    5. *x = *y;
    6. *y = tmp;
    7. }
    8. void Adjustup(int* a, int size, int x)
    9. {
    10. assert(a);
    11. int child = size - 1;
    12. int parent = (child - 1) / 2;
    13. while (child > 0)
    14. {
    15. if (a[child] < a[parent])
    16. {
    17. swap(&a[child], &a[parent]);
    18. child = parent;
    19. parent = (child - 1) / 2;
    20. }
    21. else
    22. {
    23. break;
    24. }
    25. }
    26. }
    1. void HeapPush(Heap* SL, int x)
    2. {
    3. assert(SL);
    4. if (SL->capacity == SL->size)
    5. {
    6. int newcapacity = SL->capacity == 0 ? 4 : (SL->capacity * 2);
    7. int* newnode = (int*)realloc(SL->a, sizeof(int) * newcapacity);
    8. if (newnode == NULL)
    9. {
    10. perror("realloc fail");
    11. exit(-1);
    12. }
    13. SL->capacity = newcapacity;
    14. SL->a = newnode;
    15. }
    16. SL->a[SL->size] = x;
    17. SL->size++;
    18. Adjustup(SL->a, SL->size, x);
    19. }

    3.Printf打印函数:

    1. void HeapPrintf(Heap* SL)
    2. {
    3. assert(SL);
    4. int i = 0;
    5. for (i = 0; i < SL->size; i++)
    6. {
    7. printf("%d ", SL->a[i]);
    8. }
    9. printf("\n");
    10. }

    4.Pop删除函数:

    同样的 我们对堆 进行删除的时候 同样会破坏对的结构;有一种解决思路是这样的:

    将 根节点 与 尾节点 进行互换 把Size减减;再重新向下调整更新一下堆, 把新的头调整到适当的位置。具体做法 我们来看代码的实现:

    1. void AdjustDown(int* a,int size)
    2. {
    3. assert(a);
    4. int parent = 0;
    5. int minchild = parent * 2 + 1;
    6. while (minchild < size - 1)
    7. {
    8. if (a[minchild + 1] < a[minchild])
    9. {
    10. minchild++;
    11. }
    12. if (a[parent] > a[minchild])
    13. {
    14. swap(&a[parent], &a[minchild]);
    15. parent = minchild;
    16. minchild = parent * 2 + 1;
    17. }
    18. else
    19. {
    20. break;
    21. }
    22. }
    23. }
    24. void HeapPop(Heap* SL)
    25. {
    26. assert(SL);
    27. if (SL->size == 0)
    28. {
    29. return;
    30. }
    31. swap(&SL->a[0], &SL->a[(SL->size) - 1]);
    32. SL->size--;
    33. AdjustDown(SL->a,SL->size);
    34. }

    5.其他简单函数:

    1. bool HeapEmpty(Heap* SL)
    2. {
    3. assert(SL);
    4. return SL->size == 0;
    5. }
    6. int HeapTop(Heap* SL)
    7. {
    8. assert(SL);
    9. return SL->a[0];
    10. }
    11. void HeapDestory(Heap* SL)
    12. {
    13. assert(SL);
    14. free(SL->a);
    15. SL->a = NULL;
    16. SL->capacity = SL->size = 0;
    17. }

    6.检验案例:

    1. #include"标头.h"
    2. test()
    3. {
    4. Heap SL;
    5. HeapInit(&SL);
    6. HeapPush(&SL, 6);
    7. HeapPush(&SL, 7);
    8. HeapPush(&SL, 10);
    9. HeapPush(&SL, 23);
    10. HeapPush(&SL, 2);
    11. HeapPush(&SL, 35);
    12. HeapPrintf(&SL);
    13. HeapPop(&SL);
    14. HeapPrintf(&SL);
    15. int a = HeapEmpty(&SL);
    16. printf("%d\n", a);
    17. int b = HeapTop(&SL);
    18. printf("%d\n", b);
    19. HeapDestory(&SL);
    20. }
    21. int main()
    22. {
    23. test();
    24. return 0;
    25. }

    运行结果:

  • 相关阅读:
    UE 调整材质UV贴图长宽比例
    多商户商城系统功能拆解20讲-平台端分销概况
    UI自动化测试-web浏览器-鼠标和键盘操作
    利用PDA手持终端做好库存管理精细化运营
    【解决】Github Pages搭建的网页访问加载缓慢
    第五届美团网络安全高校挑战赛团体初赛writeup
    LLM(大语言模型)常用评测指标之F1-Score
    Linux下安装Mysql5.7,超详细完整教程,以及云mysql连接
    【扩散模型】4、Improved DDPM | 引入可学习方差和余弦加噪机制来提升 DDPM
    Linux bond0 配置方法
  • 原文地址:https://blog.csdn.net/weixin_57560405/article/details/126230752