树也很好理解

​哈喽!小伙伴们,大家好!

又到学习时间啦。今天就轮到树啦,树形结构是一类重要的非线性数据结构。其中以树和二叉树最为常用,直观看来,树是以分支关系定义的层次结构。像族谱,各种社会组织机构这些关系都是树形结构。

那什么是树呢?

树就是由n个结点组成的有限集合。

当n=0的时候,这是棵空树;

当n>0,有且只有一个特定的节点是树的根,它只有直接后继,没有直接前驱;

当n>1的时候,除了根节点之外的其它结点划分为m个互不相交的有限集合,每一个集合都是根的子树。

 

树的特点

 

至少有一个结点——根节点

除叶子结点外,每个结点有一个或多个后继结点

树中各子树互不相交

树最适合表示元素之间具有的分支层次关系的数据

 

一大波术语正在靠近

 

      根    ——    根节点(没有前驱)

    叶子   ——    终端结点(没有后继)

    森林   ——    m棵不相交的树的集合

 有序树   ——    结点各个子树从左到右有序

 无序树   ——    结点各个子树位置可互换

  

    双亲   ——    直接前驱

    孩子   ——    直接后继

    兄弟   ——    直接前驱相同的结点互称为兄弟

 堂兄弟   ——    双亲位于同一层的结点

    祖先   ——    从根节点到该结点所经分支的所有结点

    子孙   ——    该结点下层子树中的任一结点

 

结点的度    ——    直接后继的个数

结点的层次 ——    从根节点到该结点的层数

终端节点     ——    度为0的结点,也就是叶子节点

 

树的度    ——    所有结点中度的最大值

树的深度 ——    所有结点中最大的层数


看看上面这棵树:

    每一个字母都是树的一个结点

    A是树的根节点

    K,L,F,G,M,I,J是叶子节点

    结点A的度是3

    树的度是3

    结点A的层次是1

    结点A的孩子是:B,C,D

    结点A是结点B的双亲

    结点F和G互为堂兄弟

    结点A是F,G的祖先

    树的深度是4

 

两个问题

 

问题1:树的顺序存储方案应该怎样制定?

        如果规定为从上至下、从左至右将树的结点依次存入内存,这样的话不能唯一复原就没有实用价值

    

问题2:树的链式存储方案应该怎样制定?

        可以用多重链表,一个前趋指针,n个后继指针

 

细节问题:树中结点的结构类型样式是应该设计成“等长”还是“不等长”?

           等长结构太浪费,每个结点的度不一定相同;不等长结构太复杂,要定义好多种结构类型

 

解决思路:先研究最简单、最有规律的树,然后设法把一般的树转化为简单树

 

树的运算 

要知道一般树不转化成二叉树,运算很难实现。 二叉树的运算还是插入、删除、修改、查找、排序等,但这些操作必须建立在对树结点能够“遍历”的基础上!

 

二叉树

二叉树是结点的一个有限集合,该集合或者为空,或者是由一个根结点加上两棵分别称为左子树和右子树的互不相交的二叉树组成。

每个结点至多只有两棵子树,二叉树中不存在度大于2的结点

 

二叉树三性质

  • 在二叉树的第 i 层上至多有 2的(i -1)次幂个结点(i >= 1) 

  • 深度为 k 的二叉树至多有 2的( k-1)次幂个结点(k >= 1)

  • 对任何一棵二叉树T, 如果其叶结点数为 n0, 度为2的结点数为 n2,则n0=n2+1

二叉树的两种形态

满二叉树

一棵深度为k且有2的( k-1)次幂个结点的二叉树称为满二叉树

满二叉树的特点:

        叶子结点都在最下一层

        只有度为0和度为2的结点

完全二叉树 

   如果二叉树的高度为h,则共有h层。除第 h 层外,其它各层 (0 到 h-1) 的结点数都达到最大个数,第 h 层从右向左连续缺若干结点,这就是完全二叉树。

完全二叉树的特点:

  •  叶子结点只可能在层次最大的两层出现。

  •   对于最大层次中的叶子结点,都依次排列在该层最左边的位置上。

  •   如果有度为1的结点,只可能有一个,且该结点只有左孩子而无右孩子。

  •   按层序编号后,一旦出现某结点(其编号为i)为叶子结点或只有左孩子,则编           号 大 于 i的结点均为叶子结点。

  • 当结点总数n为奇数时,n1=0,当结点总数n为偶数时,n1=1

满二叉树和完全二叉树有什么区别?

答:满二叉树是叶子一个也不少的树,而完全二叉树虽然前n-1层是满的,但最底层却允许在右边缺少连续若干个结点。满二叉树是完全二叉树的一个特例。满二叉树各层的结点数已达到了二叉树可以容纳的最大值。

二叉树的存储结构

顺序存储结构

按二叉树的结点“自上而下、从左至右”编号,用一组连续的存储单元存储

链式存储结构

一般从根结点开始存储。相应地,访问树中结点时也只能从根开始

二叉树结点数据类型定义:

typedef struct BiTNode{        ElemType data;      BiTNode  *lchild, *rchild;} *BiTree;

二叉树遍历

1、树的遍历就是按一定规律走遍树的各个顶点,且使每一顶点仅被访问一次,也就是找一个完整而有规律的走法,以得到树中所有结点的一个线性排列。    

2、遍历用途——它是树结构插入、删除、修改、查找和排序运算的前提,是二叉树一切运算的基础和核心,对于一棵已知树可求结点的双亲,孩子结点,判定结点所在的层次等。   

3、遍历方法——牢记一种约定,对每个结点的查看都是“先左后右” 。

4、遍历结果使一个非线性的变成一个线性的序列。

 

先序遍历:A  B  D  C

中序遍历:B  D  A  C

后序遍历:D  B  C  A

 

口诀:

        DLR—先序遍历,即先根再左再右

        LDR—中序遍历,即先左再根再右

        LRD—后序遍历,即先左再右再根

 

遍历的算法实现

中序遍历

void InOrder (BiTNode *T ){    if ( T != NULL )      {                  InOrder ( T->lchild );            cout << T->data;           InOrder ( T->rchild );        } }
先序遍历 
void PreOrder (BiTNode *T ) {          if ( T != NULL )       {                   cout << T->data;              PreOrder ( T->lchild );             PreOrder ( T->rchild );         }}

后序遍历

void PostOrder (BiTNode * T ){           if ( T != NULL )       {                    PostOrder ( T->lchild );            PostOrder ( T->rchild );            cout << T->data;          }}

若已知先序/后序遍历结果和中序遍历结果,能否“恢复”出二叉树?

那是当然可以的,不过只凭其中一种遍历方式办不到,得由一棵二叉树的先序(或后序)序列和中序序列可唯一确定这棵二叉树。 

好啦!小伙伴们,今天的分享就到这里,有什么问题可以在微信公众号私信给我。明天见喽!

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值