• 【数据结构与算法】<==>二叉树下


     

    目录

    堆的应用

    1.堆排序:

    1. 建堆

    2.向下调整的时间复杂度

    3.向上调整建堆的时间复杂度

    二叉树链式结构的实现

    遍历操作

    其他操作


    堆的应用

    1.堆排序

    堆排序即利用堆的思想来进行排序,总共分为两个步骤:

    1. 建堆

    升序:建大堆

    序:建大堆(如果建小堆的话,小堆不一定有序,只是堆顶最小,那下一个最小的数呢?如何依次选最小的数据?就算是选出来了之后,结点之间的关系就全乱了,无法继续利用优势,只能重新建堆O(N),选出次小的数据,效率太低了)建大堆直接交换堆顶和最后一个,进行向下调整即可

    降序:建小堆
    2.堆利用堆删除思想来进行排序
    建堆和堆删除中都用到了向下调整,因此掌握了向下调整,就可以完成堆排序。回顾一下向下调整的过程:
    image-20220809232058329

    这里的建堆,是直接用数组进行建堆,可以用向上调整算法进行建堆,也可以利用向下调整建堆,有什么区别?我们先来看代码的实现:

    1. //建堆——a,利用向上调整建堆——O(N*logN)
    2. //直接插入
    3. /*for (int i = 1; i < n; i++)
    4. {
    5. AdjustUp(a, i);
    6. }*/
    7. //建完堆之后无序,我们排个序
    8. //建堆——向下调整建堆(从最后一个节点的父亲开始,开始向下调整,直到根)——O(N)
    9. for (int i = (n-1-1)/2; i>=0; i--)
    10. {
    11. AdjustDown(a, n, i);
    12. }

    两种的时间复杂度不一样:向上调整建堆的时间复杂度是O(N*logN);向下调整建堆的时间复杂度是O(N)。所以我们选用的是向下调整算法进行建堆,关于向下调整算法时间复杂度的推导过程:

    2.向下调整的时间复杂度

    因为堆是完全二叉树,而满二叉树也是完全二叉树,此处为了简化使用满二叉树来证明 ( 时间复杂度本来看的 就是近似值,多几个节点不影响最终结果)

    因此:建堆的时间复杂度为O(N) 

    3.向上调整建堆的时间复杂度

     

    了解完后我们下面来实现排序

    1. #define _CRT_SECURE_NO_WARNINGS 1
    2. #include<stdio.h>
    3. //向下调整
    4. void swap(int* p1, int* p2)
    5. {
    6. int tmp = *p1;
    7. *p1 = *p2;
    8. *p2 = tmp;
    9. }
    10. void adjustdown(int* a, int n, int parent)
    11. {
    12. //默认左孩子为最小值
    13. int minchild = parent * 2 + 1;
    14. while (minchild < n)
    15. {
    16. if (minchild + 1 < n && a[minchild] > a[minchild + 1])
    17. {
    18. minchild++;
    19. }
    20. if (a[minchild] < a[parent])
    21. {
    22. swap(&a[minchild], &a[parent]);
    23. parent = minchild;
    24. minchild = parent * 2 + 1;
    25. }
    26. else
    27. {
    28. break;
    29. }
    30. }
    31. }
    32. //建堆
    33. void HeapSort(int* a, int n)
    34. {
    35. //建堆——a,利用向上调整建堆
    36. //直接插入
    37. /*for (int i = 1; i < n; i++)
    38. {
    39. AdjustUp(a, i);
    40. }*/
    41. //建完堆之后无序,我们排个序
    42. //建堆——向下调整建堆(从最后一个节点的父亲开始,开始向下调整,直到根)
    43. int i = 0;
    44. for (i = (n - 1 - 1) / 2; i >= 0; i--)
    45. {
    46. adjustdown(a, n, i);
    47. }
    48. //选数
    49. i = 1;
    50. while (i < n)
    51. {
    52. swap(&a[0], &a[n - i]);
    53. adjustdown(a, n - i, 0);
    54. i++;
    55. }
    56. }
    57. int main()
    58. {
    59. int a[] = { 15,1,19,25,8,34,65,4,27,7 };
    60. HeapSort(a, sizeof(a) / sizeof(int));
    61. for (int i = 0; i < sizeof(a) / sizeof(int); i++)
    62. {
    63. printf("%d ", a[i]);
    64. }
    65. printf("\n");
    66. return 0;
    67. }

    这里建的是小堆所以是降序 

     

    二叉树链式结构的实现

    在学习二叉树的基本操作前,需先要创建一棵二叉树,然后才能学习其相关的基本操作。为了降低学习成本,此处手动快速创建一棵简单的二叉树,这里以简单的实现为主。后续在来讨论其创建方式

    image-20220810163832470

    1. #define _CRT_SECURE_NO_WARNINGS 1
    2. #include <stdio.h>
    3. #include <assert.h>
    4. #include <stdlib.h>
    5. typedef int BTDataType;
    6. typedef struct BinaryTreeNode
    7. {
    8. BTDataType data;
    9. struct BinaryTreeNode* left;
    10. struct BinaryTreeNode* right;
    11. }BTNode;
    12. BTNode* CreatTree()
    13. {
    14. BTNode* n1 = (BTNode*)malloc(sizeof(BTNode));
    15. assert(n1);
    16. BTNode* n2 = (BTNode*)malloc(sizeof(BTNode));
    17. assert(n2);
    18. BTNode* n3 = (BTNode*)malloc(sizeof(BTNode));
    19. assert(n3);
    20. BTNode* n4 = (BTNode*)malloc(sizeof(BTNode));
    21. assert(n4);
    22. BTNode* n5 = (BTNode*)malloc(sizeof(BTNode));
    23. assert(n5);
    24. BTNode* n6 = (BTNode*)malloc(sizeof(BTNode));
    25. assert(n6);
    26. n1->data = 1;
    27. n2->data = 2;
    28. n3->data = 3;
    29. n4->data = 4;
    30. n5->data = 5;
    31. n6->data = 6;
    32. n1->left = n2;
    33. n1->right = n4;
    34. n2->left = n3;
    35. n2->right = NULL;
    36. n3->left = NULL;
    37. n3->right = NULL;
    38. n4->left = n5;
    39. n4->right = n6;
    40. n5->left = NULL;
    41. n5->right = NULL;
    42. n6->left = NULL;
    43. n6->right = NULL;
    44. return n1;
    45. }
    46. int main()
    47. {
    48. BTNode* root = CreatTree();
    49. return 0;
    50. }

    这就大概搭建起了二叉树的框架,下面,来说一说其操作:

    遍历操作

    先序、中序、后序遍历递归操作:
    1. //前序
    2. void PreOrder(BTNode* root)
    3. {
    4. if (root == NULL)
    5. {
    6. printf("NULL ");
    7. return;
    8. }
    9. printf("%d ", root->data);
    10. PreOrder(root->left);
    11. PreOrder(root->right);
    12. }
    13. //中序
    14. void InOrder(BTNode* root)
    15. {
    16. if (root == NULL)
    17. {
    18. printf("NULL ");
    19. return;
    20. }
    21. InOrder(root->left);
    22. printf("%d ", root->data);
    23. InOrder(root->right);
    24. }
    25. //后续
    26. void PostOrder(BTNode* root)
    27. {
    28. if (root == NULL)
    29. {
    30. printf("NULL ");
    31. return;
    32. }
    33. PostOrder(root->left);
    34. PostOrder(root->right);
    35. printf("%d ", root->data);
    36. }

    我们不难发现,二叉树的遍历操作通过递归实现非常地简单,实现并不难,但是你真的理解了吗函数怎么执行的(我们这里以前序遍历为例)

    image-20220810165526334

    image-20220810165556180

     完整代码

    1. #define _CRT_SECURE_NO_WARNINGS 1
    2. #include <stdio.h>
    3. #include <assert.h>
    4. #include <stdlib.h>
    5. typedef int BTDataType;
    6. typedef struct BinaryTreeNode
    7. {
    8. BTDataType data;
    9. struct BinaryTreeNode* left;
    10. struct BinaryTreeNode* right;
    11. }BTNode;
    12. BTNode* CreatTree()
    13. {
    14. BTNode* n1 = (BTNode*)malloc(sizeof(BTNode));
    15. assert(n1);
    16. BTNode* n2 = (BTNode*)malloc(sizeof(BTNode));
    17. assert(n2);
    18. BTNode* n3 = (BTNode*)malloc(sizeof(BTNode));
    19. assert(n3);
    20. BTNode* n4 = (BTNode*)malloc(sizeof(BTNode));
    21. assert(n4);
    22. BTNode* n5 = (BTNode*)malloc(sizeof(BTNode));
    23. assert(n5);
    24. BTNode* n6 = (BTNode*)malloc(sizeof(BTNode));
    25. assert(n6);
    26. n1->data = 1;
    27. n2->data = 2;
    28. n3->data = 3;
    29. n4->data = 4;
    30. n5->data = 5;
    31. n6->data = 6;
    32. n1->left = n2;
    33. n1->right = n4;
    34. n2->left = n3;
    35. n2->right = NULL;
    36. n3->left = NULL;
    37. n3->right = NULL;
    38. n4->left = n5;
    39. n4->right = n6;
    40. n5->left = NULL;
    41. n5->right = NULL;
    42. n6->left = NULL;
    43. n6->right = NULL;
    44. return n1;
    45. }
    46. //前序
    47. void PreOrder(BTNode* root)
    48. {
    49. if (root == NULL)
    50. {
    51. printf("NULL ");
    52. return;
    53. }
    54. printf("%d ", root->data);
    55. PreOrder(root->left);
    56. PreOrder(root->right);
    57. }
    58. //中序
    59. void InOrder(BTNode* root)
    60. {
    61. if (root == NULL)
    62. {
    63. printf("NULL ");
    64. return;
    65. }
    66. InOrder(root->left);
    67. printf("%d ", root->data);
    68. InOrder(root->right);
    69. }
    70. //后续
    71. void PostOrder(BTNode* root)
    72. {
    73. if (root == NULL)
    74. {
    75. printf("NULL ");
    76. return;
    77. }
    78. PostOrder(root->left);
    79. PostOrder(root->right);
    80. printf("%d ", root->data);
    81. }
    82. int main()
    83. {
    84. BTNode* root = CreatTree();
    85. PreOrder(root);
    86. printf("\n");
    87. InOrder(root);
    88. printf("\n");
    89. PostOrder(root);
    90. return 0;
    91. }

    其他操作

    结点个数

    1. //结点个数
    2. int TreeSize(BTNode* root)
    3. {
    4. if (root == NULL)
    5. return 0;
    6. return TreeSize(root->left) +
    7. TreeSize(root->right) + 1;
    8. }

     叶结点个数

    1. //叶子结点个数
    2. int TreeLeafSize(BTNode* root)
    3. {
    4. if (root == NULL)
    5. return 0;
    6. if (root->left == NULL && root->right == NULL)
    7. return 1;
    8. return TreeLeafSize(root->left) + TreeLeafSize(root->right);
    9. }

    高度

    1. //高度
    2. int TreeHeighrt(BTNode* root)
    3. {
    4. if (root == NULL)
    5. {
    6. return 0;
    7. }
    8. int left = TreeHeighrt(root->left);
    9. int right = TreeHeighrt(root->right);
    10. return left > right ? left + 1 : right + 1;
    11. }

     

    求第K层结点个数

    1. //k层的结点数
    2. int TreeLeveL(BTNode* root, int k)
    3. {
    4. assert(k > 0);
    5. if (root == NULL)
    6. {
    7. return 0;
    8. }
    9. if (k == 1)
    10. {
    11. return 1;
    12. }
    13. return TreeLeveL(root->left, k - 1) + TreeLeveL(root->right, k - 1);
    14. }

     

    返回x所在的结点

    1. //返回X所在的结点
    2. BTNode* TreeFind(BTNode* root, BTDataType x)
    3. {
    4. if (root == NULL)
    5. return NULL;
    6. if (root->data == x)
    7. return root;
    8. //先去左树找
    9. BTNode* left = TreeFind(root->left, x);
    10. if (left != NULL)
    11. return left;
    12. //左树找不到,在去右树找
    13. BTNode* right = TreeFind(root->right, x);
    14. if (right != NULL)
    15. return right;
    16. return NULL;
    17. }

     

    完整代码

    1. #define _CRT_SECURE_NO_WARNINGS 1
    2. #include <stdio.h>
    3. #include <assert.h>
    4. #include <stdlib.h>
    5. typedef int BTDataType;
    6. typedef struct BinaryTreeNode
    7. {
    8. BTDataType data;
    9. struct BinaryTreeNode* left;
    10. struct BinaryTreeNode* right;
    11. }BTNode;
    12. BTNode* CreatTree()
    13. {
    14. BTNode* n1 = (BTNode*)malloc(sizeof(BTNode));
    15. assert(n1);
    16. BTNode* n2 = (BTNode*)malloc(sizeof(BTNode));
    17. assert(n2);
    18. BTNode* n3 = (BTNode*)malloc(sizeof(BTNode));
    19. assert(n3);
    20. BTNode* n4 = (BTNode*)malloc(sizeof(BTNode));
    21. assert(n4);
    22. BTNode* n5 = (BTNode*)malloc(sizeof(BTNode));
    23. assert(n5);
    24. BTNode* n6 = (BTNode*)malloc(sizeof(BTNode));
    25. assert(n6);
    26. n1->data = 1;
    27. n2->data = 2;
    28. n3->data = 3;
    29. n4->data = 4;
    30. n5->data = 5;
    31. n6->data = 6;
    32. n1->left = n2;
    33. n1->right = n4;
    34. n2->left = n3;
    35. n2->right = NULL;
    36. n3->left = NULL;
    37. n3->right = NULL;
    38. n4->left = n5;
    39. n4->right = n6;
    40. n5->left = NULL;
    41. n5->right = NULL;
    42. n6->left = NULL;
    43. n6->right = NULL;
    44. return n1;
    45. }
    46. //前序
    47. void PreOrder(BTNode* root)
    48. {
    49. if (root == NULL)
    50. {
    51. printf("NULL ");
    52. return;
    53. }
    54. printf("%d ", root->data);
    55. PreOrder(root->left);
    56. PreOrder(root->right);
    57. }
    58. //中序
    59. void InOrder(BTNode* root)
    60. {
    61. if (root == NULL)
    62. {
    63. printf("NULL ");
    64. return;
    65. }
    66. InOrder(root->left);
    67. printf("%d ", root->data);
    68. InOrder(root->right);
    69. }
    70. //后续
    71. void PostOrder(BTNode* root)
    72. {
    73. if (root == NULL)
    74. {
    75. printf("NULL ");
    76. return;
    77. }
    78. PostOrder(root->left);
    79. PostOrder(root->right);
    80. printf("%d ", root->data);
    81. }
    82. //结点个数
    83. int TreeSize(BTNode* root)
    84. {
    85. if (root == NULL)
    86. return 0;
    87. return TreeSize(root->left) +
    88. TreeSize(root->right) + 1;
    89. }
    90. //叶子结点个数
    91. int TreeLeafSize(BTNode* root)
    92. {
    93. if (root == NULL)
    94. return 0;
    95. if (root->left == NULL && root->right == NULL)
    96. return 1;
    97. return TreeLeafSize(root->left) + TreeLeafSize(root->right);
    98. }
    99. //高度
    100. int TreeHeighrt(BTNode* root)
    101. {
    102. if (root == NULL)
    103. {
    104. return 0;
    105. }
    106. int left = TreeHeighrt(root->left);
    107. int right = TreeHeighrt(root->right);
    108. return left > right ? left + 1 : right + 1;
    109. }
    110. //k层的结点数
    111. int TreeLeveL(BTNode* root, int k)
    112. {
    113. assert(k > 0);
    114. if (root == NULL)
    115. {
    116. return 0;
    117. }
    118. if (k == 1)
    119. {
    120. return 1;
    121. }
    122. return TreeLeveL(root->left, k - 1) + TreeLeveL(root->right, k - 1);
    123. }
    124. //返回X所在的结点
    125. BTNode* TreeFind(BTNode* root, BTDataType x)
    126. {
    127. if (root == NULL)
    128. return NULL;
    129. if (root->data == x)
    130. return root;
    131. //先去左树找
    132. BTNode* left = TreeFind(root->left, x);
    133. if (left != NULL)
    134. return left;
    135. //左树找不到,在去右树找
    136. BTNode* right = TreeFind(root->right, x);
    137. if (right != NULL)
    138. return right;
    139. return NULL;
    140. }
    141. int main()
    142. {
    143. BTNode* root = CreatTree();
    144. PreOrder(root);
    145. printf("\n");
    146. InOrder(root);
    147. printf("\n");
    148. PostOrder(root);
    149. printf("\n");
    150. printf("Size:%d\n", TreeSize(root));
    151. printf("LeafSize:%d\n", TreeLeafSize(root));
    152. printf("LeafHeighrt:%d\n", TreeHeighrt(root));
    153. printf("TreeLeveL:%d\n", TreeLeveL(root,3));
    154. printf("Tree Find:%p\n", TreeFind(root, 8));
    155. return 0;
    156. }

     

     

  • 相关阅读:
    极智Coding | OpenMP 多线程使用
    IT人必看 | 2022年春招市场行情报告——高薪职业榜首是这些!
    物理学专业英语(词汇整理)--------07
    Java实现ORM第一个api-FindAll
    透过等待看数据库
    Springboot企业的信息管理系统5qs0a计算机毕业设计-课程设计-期末作业-毕设程序代做
    记一次地级市某行业专项攻防演练
    数仓4.0(可视化报表)
    Qt ffmpeg音视频转换工具
    【汇编】其他转移指令、call指令和ret指令
  • 原文地址:https://blog.csdn.net/weixin_67900732/article/details/126378925