当前位置:   article > 正文

二叉树的创建以及四种遍历方式_二叉树的创建和遍历代码

二叉树的创建和遍历代码

1.树

树形结构:一对多,第一个节点没有前驱,最后一个节点没有后继,中间节点有唯一前驱,可以有多个后继,也可以没有

2.树的概念

由m(>=0)个互不相交的有限集合组成的集合

一个节点的子树个数称为该节点的度数。树的度数由树中最大的度数来决定。

度数为0的节点称为树叶,叶节点或终端节点。度数不为0的称为分支节点,除了根节点以外的分支节点称为内部节点。

路径:路径上的节点ki是ki+1的父节点(叶节点的个数也就是路径的个数)路径的长度称为边数。

层数:同一父节点的节点为同一层。根节点为第一层,树中节点的最大层数称为树的高度或者深度

树的左右节点有序,从左到右不可交换,则称为有序树

m(m>=0)棵互不相交的树的集合称为森林。树去掉根节点就称为森林

兄弟分为:亲兄弟,堂兄弟

3.二叉树

二叉树的定义:二叉树是n(n>=0)个节点的有限集合,它或者是空集(n=0),或者是由一个根节点以及两棵不互相交的、分别称为左子树与柚子树的二叉树组成,二叉树与普通有序树不同,二叉树严格区分左孩子和右孩子,即使只有一个节点也要区分左右,度数最大为2.

性质:

第i层上的节点最多为2^(i-1)

知道最大层数,总的节点最多为2^i-1

树叶的数目比度数为2的节点的数目多1

(n0表示没有子节点的节点总数,n1表示有一个子节点的节点总数,n2表示有两个子节点的节点总数)

n=n0+n1+n2①        

n=n1+2*n2+1②

n0=n2+1

满二叉树,每一层的孩子都存满(可以顺序存储,空间不浪费)

完全二叉树:只有最下面两层有度数小于2的节点,只有一个孩子时,孩子为左孩子

4.二叉树的顺序存储

先将二叉树补成完全二叉树,再从上到下,从左到右将所有节点编号,依次存放在缓冲区中。

完全二叉树节点编号,从上到下,从左到右,根节点为一号,设节点数为n,某编号为i。

性质:

当i>1时,有父节点,其编号为i/2;

当2* i<=n时,有左孩子,其编号为2*i,否则没有左孩子,本身是叶节点;

当2* i+1<=n时,有右孩子,其编号为2*i+1,否则没右孩子,本身是叶节点;

当i为奇数(右节点)且不为1时,有左兄弟,其编号为i-1,否则没有左兄弟;

当i为偶数(左节点)且小于n时,有右兄弟,其编号为i+1,否则没有右兄弟

  1. /*===============================================
  2. * 文件名称:seqtree.c
  3. * 创 建 者:
  4. * 创建日期:2022年08月02日
  5. * 描 述:
  6. ================================================*/
  7. #include <stdio.h>
  8. int main(int argc, char *argv[])
  9. {
  10. char buf[16]={0},ch,i=1,n=1;
  11. printf("请输入完全二叉树的元素(#结束)\n");
  12. while((ch=getchar())!='#')//一个一个输入
  13. {
  14. buf[i]=ch;
  15. i++;
  16. }
  17. for(i=0;i<16;i++)//显示
  18. {
  19. if(i>n-1)
  20. {
  21. puts("");
  22. n=2*n;
  23. }
  24. if(buf[i]=='@')
  25. {
  26. printf(" ");
  27. continue;
  28. }
  29. printf("%c",buf[i]);
  30. }
  31. puts("");
  32. return 0;
  33. }

 5.树的链式存储

树中每个节点相关的结构体:

  1. typedef int data_t;
  2. typedef struct tree_node
  3. {
  4.     data_t data;//数据域
  5.     struct tree_node *l_child;//左节点
  6.     struct tree_node *r_child;//右节点
  7. }T_node;

6.二叉树的遍历

先序遍历:根左右

中序遍历:左根右

后序遍历:左右根

二叉树的层次遍历:

根先入队,然后循环到队列为空。

入队:判断一次根的左右节点是否存在,存在就入队(先左后右)

出队:打印根的数据域,根出队

6.1头文件

头文件定义了树的存储类型,结构体的设计,以及将要实现的功能函数。

  1. /*===============================================
  2. * 文件名称:linktree.h
  3. * 创 建 者:
  4. * 创建日期:2022年08月02日
  5. * 描 述:
  6. ================================================*/
  7. #ifndef __LINKTREE__
  8. #define __LINKTREE__
  9. typedef char data_t;
  10. typedef struct tree_node
  11. {
  12. data_t data;
  13. struct tree_node *l_child;
  14. struct tree_node *r_child;
  15. }T_node;
  16. T_node *Create_Linktree();//创建一个二叉树
  17. void Linktree_Show0(T_node *root);//先序遍历
  18. void Linktree_Show1(T_node *root);//中序遍历
  19. void Linktree_Show2(T_node *root);//后序遍历
  20. void Nooread(T_node *root);//层次遍历
  21. #endif

6.2功能函数

二叉树的难点在于创建时的递归调用。从终端输入一串数据以 '#' 结束,数据存储在缓冲区中,然后每次执行创建程序,读一个字符。判断是否是'#',如不是,则向堆区申请空间,把数据存入数据域,指针域则调用创建函数,形成递归,先创建左子树,再创建右子树,当读取到'#'时,标明没有子树。返回NULL。

三种常见的遍历方式先判断是否是空树,不是的话就按照对应的顺序来调用遍历函数,形成递归条件,都是在根节点时打印。

        

最后的层次遍历则利用到了队列,每一个根节点都判断是否有左右子树,有的话就入队,然后把队列的第一个节点也就是这一次循环的根节点打印,然后出队,因为只显示一遍,不需要循环队列。

  1. /*===============================================
  2. * 文件名称:linktree.c
  3. * 创 建 者:
  4. * 创建日期:2022年08月02日
  5. * 描 述:
  6. ================================================*/
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include "linktree.h"
  10. T_node *Create_Linktree()//创建一个二叉树
  11. {
  12. char x;
  13. //printf("请输入节点的值,#表示空\n");
  14. T_node *root;
  15. scanf("%c",&x);
  16. //printf("x=%c\n",x);
  17. //getchar();
  18. if(x!='#')
  19. {
  20. root=(T_node *)malloc(sizeof(T_node));
  21. if(NULL==root)
  22. {
  23. printf("nalloc error");
  24. return NULL;
  25. }
  26. root->data=x;
  27. root->l_child=Create_Linktree();//先左后右
  28. root->r_child=Create_Linktree();
  29. return root;
  30. }
  31. else
  32. {
  33. return NULL;
  34. }
  35. }
  36. void Linktree_Show0(T_node *root)//先序遍历
  37. {
  38. if(root!=NULL) //根
  39. {
  40. printf("%4c",root->data);
  41. Linktree_Show0(root->l_child);//左
  42. Linktree_Show0(root->r_child);//右
  43. }
  44. return;
  45. }
  46. void Linktree_Show1(T_node *root)//中序遍历
  47. {
  48. if(root!=NULL) //根
  49. {
  50. Linktree_Show0(root->l_child);//左
  51. printf("%4c",root->data);
  52. Linktree_Show0(root->r_child);//右
  53. }
  54. return;
  55. }
  56. void Linktree_Show2(T_node *root)//后序遍历
  57. {
  58. if(root!=NULL) //根
  59. {
  60. Linktree_Show0(root->l_child);//左
  61. Linktree_Show0(root->r_child);//右
  62. printf("%4c",root->data);
  63. }
  64. return;
  65. }
  66. void Nooread(T_node *root)//层次遍历
  67. {
  68. int front,rear;//头尾指针
  69. T_node *q[16]; //指针数组
  70. if(root==NULL) //判断树是否为空
  71. {
  72. printf("空树无法遍历\n");
  73. return;
  74. }
  75. for(rear=1;rear<16;rear++)//给指针数组赋初值NULL
  76. {
  77. q[rear]=NULL;
  78. }
  79. front=rear=1;//下标为0的数组元素不用
  80. q[rear]=root;
  81. rear++;
  82. while(q[front]!=NULL)//队列为空则跳出循环
  83. {
  84. if(q[front]->l_child!=NULL)//左孩子存在则入队
  85. {
  86. q[rear]=q[front]->l_child;
  87. rear++; //rear后移
  88. }
  89. if(q[front]->r_child!=NULL)//右孩子存在则入队
  90. {
  91. q[rear]=q[front]->r_child;
  92. rear++; //rear后移
  93. }
  94. printf("%c",q[front]->data);//打印出队节点
  95. front++; //队头节点出队
  96. }
  97. }

6.3主函数

主函数就调用了功能函数,先是创建了二叉树,然后四种遍历方式输出

  1. /*===============================================
  2. * 文件名称:main.c
  3. * 创 建 者:
  4. * 创建日期:2022年08月02日
  5. * 描 述:
  6. ================================================*/
  7. #include <stdio.h>
  8. #include "linktree.h"
  9. int main(int argc, char *argv[])
  10. {
  11. T_node *root=Create_Linktree();
  12. printf("-------------------------------------------\n");
  13. Linktree_Show0(root);
  14. printf("\n-------------------------------------------\n");
  15. Linktree_Show1(root);
  16. printf("\n-------------------------------------------\n");
  17. Linktree_Show2(root);
  18. printf("\n-------------------------------------------\n");
  19. Nooread(root);
  20. puts("");
  21. return 0;
  22. }

 

 

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

闽ICP备14008679号