跟郝斌老师复习数据结构part5--非线性结构--树

    技术2022-07-10  138

    一、定义

    1 专业定义

    有且只有一个称为根的节点有若干各互不相交的子树,这些子树本身也是一棵树

    2 通俗定义

    树是由节点和边组成。每个节点只有一个父节点,但是可以由多个字节点。但有一个节点例外,该节点没有父节点,此节点称为根节点。

    3 专业术语

    节点 父节点 子节点 子孙 堂兄弟 深度:从根节点到最底层节点的层数称为深度(根节点是第一层) 叶子节点:没有子节点的节点 非终端节点:非叶子节点 度:子节点的个数称为度 数的度:含有最大子节点的个数即最大的度就是数的度

    二、分类

    1 一般树

    任意一个节点的子节点的个数都不受控制

    2 二叉树

    任意一个节点的子节点个数最多两个,且子节点的位置不可更改

    分类:

    3 森林

    n个互不相交的树的集合

    三、树的存储

    3.1二叉树的存储

    连续存储【完全二叉树】 优点:查找某个节点的父节点和子节点(也包括判断有没有节点)很快 缺点:耗用内存空间很大

    链式存储

    3.2一般树的存储

    双亲表示法 求父节点方便

    孩子表示法 求子节点方便

    双亲孩子表示法 求父节点和子节点都很方便

    二叉树表示法 把一个普通树转换成二叉树来存储 具体转换方法: 设法保证任意一个节点的左指针域指向它的第一个孩子,右指针域指向它的兄弟 只要满足此条件,就可以把一个普通树转化为二叉树 一个普通树转化成的二叉树一定没有右子树

    3.3森林的存储

    将各个树的根节点看作一组兄弟节点,把森林转化成二叉树,再存储

    四、操作

    4.1遍历

    先序遍历(先访问跟节点) 先访问根节点, 再先序访问左子树, 再先序访问右子树 中序遍历(中间访问根节点) 中序遍历左子树 再访问根节点 再中序遍历右子树 B-D-C-E-A-L-F-N-Q-M

    B-D-C-A-M-Q-E-L-N

    后序遍历(最后访问根节点) 中序遍历左子树 中序遍历右子树 再访问根节点 B-D-M-F-L-E-C-A

    N-W-T-S-F-P-L-Q-M

    4.2已知两种遍历序列求原始二叉树

    通过先序和中序 或者 中序和后序,我们可以还原出原始的二叉树; 但是通过先序和后序是无法还原出原始的二叉树。

    或者说:只有通过先序和中序,或者通过中序和后序,我们才可以唯一的确定一个二叉树

    已知先序和中序求后序: 示例1: D-E-C-B-H-G-F-A

    示例2: 先序:A-B-D-G-H-C-E-F-I 中序:G-D-H-B-A-E-C-I-F 求后序:G-H-D-B-E-I-F-C-A

    已知后序和中序求先序: 后序最后出现的是根节点 示例1: 中序:B-D-C-E-A-F-H-G 后序:D-E-C-B-H-G-F-A 求先序:A-B-C-D-E-F-G-H

    五、应用

    树是数据库中数据组织的一种重要形式 操作系统子父进程关系本身就是一棵树 面向对象语言中类的继承关系本身就是一棵树 赫夫曼树

    六、代码实现

    #include<stdio.h> #include<malloc.h> struct BTNode{ char data; struct BTNode * pLchild;//p是指针,L是左,child是孩子 struct BTNode * pRchild; }; struct BTNode * CreateBTree(void); void PreTraverseBTree(struct BTNode * pT); void InTraverseBTree(struct BTNode * pT); void PostTraverseBTree(struct BTNode * pT); int main(void){ struct BTNode * pT=CreateBTree(); printf("先序遍历:\n"); PreTraverseBTree(pT); printf("中序遍历:\n"); InTraverseBTree(pT); printf("后序遍历:\n"); PostTraverseBTree(pT); return 0; } void PreTraverseBTree(struct BTNode * pT){ if(pT!=NULL){ printf("%c\n",pT->data); if(NULL!=pT->pLchild){ PreTraverseBTree(pT->pLchild); } if(NULL!=pT->pRchild){ PreTraverseBTree(pT->pRchild); } } } void InTraverseBTree(struct BTNode * pT){ if(pT!=NULL){ if(NULL!=pT->pLchild){ InTraverseBTree(pT->pLchild); } printf("%c\n",pT->data); if(NULL!=pT->pRchild){ InTraverseBTree(pT->pRchild); } } } void PostTraverseBTree(struct BTNode * pT){ if(pT!=NULL){ if(NULL!=pT->pLchild){ PostTraverseBTree(pT->pLchild); } if(NULL!=pT->pRchild){ PostTraverseBTree(pT->pRchild); } } printf("%c\n",pT->data); } struct BTNode * CreateBTree(void){ struct BTNode * pA=(struct BTNode *)malloc(sizeof(struct BTNode)); struct BTNode * pB=(struct BTNode *)malloc(sizeof(struct BTNode)); struct BTNode * pC=(struct BTNode *)malloc(sizeof(struct BTNode)); struct BTNode * pD=(struct BTNode *)malloc(sizeof(struct BTNode)); struct BTNode * pE=(struct BTNode *)malloc(sizeof(struct BTNode)); pA->data='A'; pB->data='B'; pC->data='C'; pD->data='D'; pE->data='E'; pA->pLchild=pB; pA->pRchild=pC; pB->pRchild=pB->pLchild=NULL; pC->pLchild=pD; pC->pRchild=NULL; pD->pLchild=NULL; pD->pRchild=pE; pE->pRchild=pE->pLchild=NULL; return pA; }

    Processed: 0.017, SQL: 9