• 二叉树的基本性质与遍历


    二叉树

    就是一棵树中每个结点最多只有两个结点,可以没有结点,也可以只有一个结点,也可以为空结点

    下面说一下二叉树的常见形态:

            

    满二叉树与完全二叉树的区别:

            满二叉树就是除了叶子结点之外,每一个结点都有两个孩子

            完全二叉树就是每一个结点不一定有两个孩子,但是如果出现在同一层,完全二叉树结点的i位置与满二叉树结点的 i位置编号相同,就是完全二叉树。

            所以,满二叉树一定是完全二叉树,但是完全二叉树不一定是满二叉树

    然后来说一下二叉树的性质:

            1.在二叉树的i层最多有2^i-1个结点(i>0)

            2.深度为k的二叉树最多有2^k - 1个结点(k>0)

            3.对于任何一棵二叉树,若度为2的结点数有n2个,则叶子数n0必定为n2+1(n0=n2+1)

            4.具有n个结点的完全二叉树深度必为

             5.对于完全二叉树,从上到下,从左到右,则编号为i的结点,其左孩子必为2i,右孩子编号为2*i + 1,其双亲的编号必为i/2(i=1时候为根)

    二叉树的遍历:

            大概会分为三种情况,这三种情况的讨论,就是根据到底是先遍历根,还是在中间遍历根,还是说在最后遍历根,也就分为了先序遍历(DLR),中序遍历(LDR),后序遍历(LRD)

            D:根 L: 左结点 R:右结点

            先来看一个二叉树:

            

            先来说一下先序遍历(DLR)

                    先根在左在右:比如一个函数r(从A传入结点),然后先把A打印,毕竟是先序嘛,然后去遍历左边,也就是走下面遍历

                    

                    这边函数栈就是

                     

             

    话不多说,直接上代码:

            

    1. #include<stdio.h>
    2. #include<string.h>
    3. #include<stdlib.h>
    4. typedef struct _binary_node binary_node;
    5. struct _binary_node
    6. {
    7. char ch;
    8. binary_node *lchild;
    9. binary_node *rchild;
    10. };
    11. void recursion_print(binary_node *node)
    12. {
    13. if (node == NULL) {
    14. return;
    15. }
    16. printf("%c ", node->ch);
    17. recursion_print(node->lchild);
    18. recursion_print(node->rchild);
    19. }
    20. int main()
    21. {
    22. //靠靠靠靠靠靠靠
    23. binary_node node_a = { 'A', NULL, NULL };
    24. binary_node node_b = { 'B', NULL, NULL };
    25. binary_node node_c = { 'C', NULL, NULL };
    26. binary_node node_d = { 'D', NULL, NULL };
    27. binary_node node_e = { 'E', NULL, NULL };
    28. binary_node node_f = { 'F', NULL, NULL };
    29. node_a.lchild = &node_b;
    30. node_a.rchild = &node_c;
    31. node_b.rchild = &node_e;
    32. node_b.lchild = &node_d;
    33. node_c.rchild = &node_f;
    34. //靠靠
    35. recursion_print(&node_a);
    36. return 1;
    37. }

     运行结果:

            

      当然了,二叉树肯定不至于递归,所以,比如计算二叉树叶子的数目,二叉树的高度,又比如拷贝一棵二叉树,下面上完整代码:

    binary_tree.c

    1. #include<stdio.h>
    2. #include<string.h>
    3. #include<stdlib.h>
    4. typedef struct _binary_node binary_node;
    5. struct _binary_node
    6. {
    7. char ch;
    8. binary_node *lchild;
    9. binary_node *rchild;
    10. };
    11. void recursion_print(binary_node *node)
    12. {
    13. if (node == NULL) {
    14. return;
    15. }
    16. printf("%c ", node->ch);
    17. recursion_print(node->lchild);
    18. recursion_print(node->rchild);
    19. }
    20. void calc_leaf_num(binary_node *node,int *p)
    21. {
    22. //程序的结束条件
    23. if(node == NULL) {
    24. return ;
    25. }
    26. //left and right is null
    27. if(node->lchild == NULL && node->rchild == NULL) {
    28. (*p)++;
    29. }
    30. calc_leaf_num(node->lchild,p);//传入计算数量变量的地址
    31. calc_leaf_num(node->rchild,p);
    32. }
    33. //计算树高度
    34. int get_tree_high(binary_node *node)
    35. {
    36. if(node == NULL) {
    37. return 0;
    38. }
    39. //递归计算左右两边树的高度
    40. int left_high = get_tree_high(node->lchild);
    41. int right_high = get_tree_high(node->rchild);
    42. return left_high > right_high ? left_high + 1 : right_high + 1;
    43. }
    44. //拷贝二叉树就是在堆上面开辟一个空间
    45. //来存放二叉树的每一个结点
    46. //最后返回头部结点
    47. binary_node* copy_tree(binary_node *node)
    48. {
    49. if(node == NULL){
    50. return NULL;
    51. }
    52. //还是要遍历左树,在遍历右树
    53. binary_node* lnode = copy_tree(node->lchild);
    54. binary_node* rnode = copy_tree(node->rchild);
    55. //每一个结点都要干一件事儿
    56. binary_node *new_node = (binary_node*)malloc(sizeof(binary_node));
    57. if(new_node != NULL) {
    58. new_node->ch = node->ch;
    59. new_node->lchild = lnode;
    60. new_node->rchild = rnode;
    61. }
    62. return new_node;
    63. }
    64. //释放拷贝的这棵树
    65. void free_tree(binary_node *node)
    66. {
    67. if(node == NULL) {
    68. return;
    69. }
    70. free_tree(node->lchild);
    71. free_tree(node->rchild);
    72. //在此之前看一下被释放的结点
    73. printf("%c被释放了\n",node->ch);
    74. free(node);//释放这个结点
    75. }
    76. int main()
    77. {
    78. binary_node node_a = { 'A', NULL, NULL };
    79. binary_node node_b = { 'B', NULL, NULL };
    80. binary_node node_c = { 'C', NULL, NULL };
    81. binary_node node_d = { 'D', NULL, NULL };
    82. binary_node node_e = { 'E', NULL, NULL };
    83. binary_node node_f = { 'F', NULL, NULL };
    84. node_a.lchild = &node_b;
    85. node_a.rchild = &node_c;
    86. node_b.rchild = &node_e;
    87. node_b.lchild = &node_d;
    88. node_c.rchild = &node_f;
    89. recursion_print(&node_a);
    90. int leaf_num = 0;
    91. calc_leaf_num(&node_a,&leaf_num);
    92. printf("叶子结点数目为:%d\n",leaf_num);
    93. int tree_high = get_tree_high(&node_a);
    94. printf("叶子数目为:%d\n",tree_high);
    95. //拷贝二叉树
    96. binary_node *node = copy_tree(&node_a);
    97. //然后递归遍历一下这个二叉树
    98. printf("\n-------------\n");
    99. recursion_print(node);
    100. printf("\n-----\n");
    101. //释放拷贝的每一个结点
    102. //二叉树非递归遍历
    103. free_tree(node);
    104. return 1;
    105. }

            

         

  • 相关阅读:
    RustGUI学习(iced)之小部件(二):如何使用滑动条部件
    【MyBatis】一、MyBatis概述与基本使用
    python excel 读取及写入固定格式
    C#when关键字
    unity基础1-事件执行顺序、自定义事件
    【JavaScript】Generator函数
    JAVA美发门店管理系统计算机毕业设计Mybatis+系统+数据库+调试部署
    nocos注册中心使用教程
    nginx搭建直播rtmp推流,httpflv拉流环境
    数字孪生、AR和VR如何改进数据中心设计
  • 原文地址:https://blog.csdn.net/Pxx520Tangtian/article/details/125341050