树结构是以分支关系定义的一种层次结构。(应用数结构组织起来的数据应当具有层次关系)
树的定义
树:由n个结点组成的有穷集合。
在任意的一颗非空树中:
1) 有且仅有一个称为根的结点
2) 当n>1时,其余结点分为m个互不相交的有限集,T1,T2……Tm,其中每一个集合本身又是一颗树,并称为根的子树。
树的存储形式:多重链表存储形式。在多重链表中,每个结点由一个数据域和若干个指针域组成,其中每一个指针域的指针指向该结点的一个孩子结点。
多重链表的结点类型:
1 2 3 4 5 6 | #define MaxChild 10 typedef struct node { dataType data; struct node *child[MaxChild]; } |
二叉树定义
对于二叉树,一个结点至多可以有2个孩子结点,或者只有一个孩子结点,或者没有孩子结点。
二叉树:或者为空,或者由一个根结点加上两颗分别称为左子树和右子树的互不相交的二叉树组成。这个定义是递归的。
1 2 3 4 | typedef struct BiTNode { ElemType data; //结点的数据域 struct BITNode *lchild,*rchild; //指向左孩子和右孩子 }BiTNode, *BiTree; |
上述代码定义了一个二叉树的结点类BiTNode,即说二叉树的每一个结点都属于BiTNode类型。另外定义了BiTree类型,是一个指向BiTNode类型数据的指针类型,变量声明 BiTree t;等价于 BiTNode *t; 通过BiTree类型的变量t就可以访问二叉树中的结点。
二叉树的遍历:前序、中序、后续
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | PreOrderTraverse(Bitree T) { //先序 if (T) { //递归结束条件,T为空 visit(T->data); //访问根结点 PreOrderTraverse(T->lchild); //先序遍历T的左子树 PreOrderTraverse(T->rchild); //先序遍历T的右子树 } } InOrderTraverse(BiTree T) { if (T){ InOrderTraverse(T->lchild); visit(T->data); InOrderTraverse(T->rchild); } } PosOrderTraverse(BiTree T){ if (T) { PosOrderTraverse(T->lchild); PosOrderTraverse(T->rchild); visit(T->data); } } |
创建二叉树:
1 2 3 4 5 6 7 8 9 10 11 | CreatBitree(BiTree *T) { char c; scanf (“%c”,&c); if (c == ' ' ) *T=NULL; else { *T = (BiTNode *) malloc ( sizeof (BiTNode)); //创建根结点 (*T)->data=c; //向根结点中输入数据 CreatBitree(&((*T)->lchild)); //递归创建左子树 CreatBitree(&((*T)->rchild)); //递归创建右子树 } } |
实例:用先序序列创建一颗二叉树,并输出字符D位于二叉树的层数。输入:ABC##D##E#F##(#代表空格),输出字符D所在的层数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | #include"stdio.h" typedef struct BiTNode { ElemType data; //结点的数据域 struct BiTNode *lchild,*rchild; //指向左孩子和右孩子 }BiTNode, *BiTree; CreatBitree(BiTree *T) { char c; scanf (“%c”,&c); if (c == ' ' ) *T=NULL; else { *T = (BiTNode *) malloc ( sizeof (BiTNode)); //创建根结点 (*T)->data=c; //向根结点中输入数据 CreatBitree(&((*T)->lchild)); //递归创建左子树 CreatBitree(&((*T)->rchild)); //递归创建右子树 } } visit( char c, int level) { if (c== 'D' ) printf ( "%c is at %dth level of BiTree\n" ,c,level); } PreOrderTraverse(Bitree T, int level) { //先序 if (T) { //递归结束条件,T为空 visit(T->data,level); //访问根结点 PreOrderTraverse(T->lchild,level+1); //先序遍历T的左子树 PreOrderTraverse(T->rchild,level+1); //先序遍历T的右子树 } } int mian() { int level=1; BiTree T=NULL; CreatBiTree(&T); PreOrderTraverse(T,level); getche(); return 0; } |
注意:level作为一个局部变量每次作为参数传递时都加1,因此递归深入一层,变量level的值就自动加1,。而一旦递归从下一层返回到上一层时,上一层的level值仍然会保持原来的值不变,因为这里的变量level的传递仅仅是单项值传递,并不是指针传递,它在每层中的局部值都不会受到下一层任何操作的影响。
根据书中所述,代码编译有错。 待以后复习纠错。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?