05_树(二叉树)

树的定义

树( Tree)是 n(n>=0) 个结点的有限集 。n=0 时称为空树 。 在任意一棵非空树中: ( 1 )有且仅有-个特定的称为根( Root )的结点: (2) 当n>1 时,其余结点可分为 m (m>0) 个互不相交的有限集 T1 、 T2、……、 Tm •,其中每一个集合本身又是一课树,并且称为根的子树( SubTree )。

在这里插入图片描述

节点分类

树的结点包含一个数据元素及若干指向其子树的分支。 结点拥有的子树数称为结点的度(Degree) 。度为 0 的结点称为叶结点(Leaf) 或终端结点;度不为 0 的结点称为非终端结点或分支结点 。 除根结点之外,分支结点也称为内部结点。树的度是树内各结点的度的最大值

在这里插入图片描述

节点关系

结点的子树的根称为该结点的孩子(Child) ,相应地,该结点称为孩子的双亲(Parent) 。同一个双亲的孩子之间直称兄弟(Sibling) 。

在这里插入图片描述

树的其他相关概念

  • 结点的层次( LeveI) 从根开始定义起,根为第一层 , 根的孩子为第二层。

!在这里插入图片描述

  • 如果将树中结点的各子树看成从左至右是有次序的,不能互换的,则称该树为有序树,否则称为无序树 。
  • 森林( Forest) 是 m(m >= 0) 棵互不相交的树的集合。

树的抽象数据类型

ADT 树(tree)
Data
	树是由一个根结点和若干个子树构成。树中结点具有相同数据类型及层次关系。
Operation
	InitTree(*T):构造空树T
	DestoryTree(*T):销毁树T
	CreateTree(*T,definition):按照definition中给出树的定义来构造树。
	ClearTree(*T):若树 T 存在,则将树 T 清为空树。
	TreeEmpty(T):若 T 为空树,返回 true,否则返回false。
	TreeDepth(T):返回 T 的深度。
	Root(T):返回T的根节点
	Value(T,cur_e):cur_e是树T中一个结点,返回此结点的值
	Assign(T,cur_e,value):给树T的结点 cur_e 赋他为value。
	Parent(T,cur_e):若 cur_e 是树T的非根结点,则返回它的双亲,否则返回空。
	LeftChild(T,cur_e):若 cur_e是树T的非叶结点,则返回它的最左孩子,否则返回空。
	RightSibling(T,cur_e):若 cUI_e 有方兄弟,则返回它的右兄弟,否则返回空。
	InsertChild(*T,*p,i,c):其中p指向树 T的某个结点 ,i为所指结点p的度上加1,非空树c与T不相交,操作结果为插入c为树T中p指结点的第i棵子树。
	DeleteChild(*Tm*p,i):其中p指向树T的某个结点,i为所指给点p的度,操作结果为删除T中p所指结点的第i棵子树。
endADT

二叉树

二叉树(Binary Tree)是 n(n>=0)个节点的有限集合,该集合或者为空集(称为空二叉树),或者由一个根节点和两个互不相交的、分别称为根节点的左子树和右子树的二叉树组成。

二叉树的特点

  • 斜树:所有的结点都只有左子树的二叉树叫左斜树。所有结点都是只有右子树的二叉树叫右斜树。这两者统称为斜树。斜树有很明显的特点,就是每一层都只有一个结点,结点的个数与二叉树的深度。其实线性表结构就可以理解为是树的一种极其特殊的表现形式 。

  • 满二叉树:在一棵二叉树中,如果所有分支结点都存在左子树和右子树,并且所有叶子都在同一层上,这样的二叉树称为满二叉树。

    在这里插入图片描述

    • 叶子只能出现在最下一层。出现在其他层就不可能达成平衡。
    • 非叶子结点的度一定是 2 。否则就是"缺胳膊少腿" 了。
    • 在同样深度的二叉树中,满二叉树的结点个数最多,叶子数最多。
  • 完全二叉树:对一棵具有 n 个结点的二叉树按层序编号,如果编号为 i (l<=i<=n) 的结点与同样深度的满二叉树中编号为i 的结点在二叉树中位置完全相同,则这棵二叉树称为完全二叉树

    在这里插入图片描述

    • 叶子节点只能出现在最下两层
    • 最下层的叶子一定集中在左部连续位置
    • 倒数二层,若有叶子节点,一定都在右部连续位置
    • 如果节点度为1,则该节点只有左孩子,即不存在只有右子树的情况
    • 同样节点数的二叉树,完成二叉树的深度最小

二叉数据的性质

  • 在二叉树的第 i 层上至多有 2 i − 1 2^{i-1} 2i1个结点(i >= 1)
  • 深度为 k 的二叉树至多有 2 k − 1 2^k-1 2k1个结点(k >= 1)
  • 对任何一棵二叉树 T,如果其终端结点数为 n 0 n_0 n0,度为 2 的结点数为 n 2 n_2 n2,则 n 0 = n 2 + 1 n_0=n_2+1 n0=n2+1
  • 具有 n 个结点的完全二叉树的深度为 [ l o g 2 n ] [log_2n] [log2n] + 1([x]表示不大于x的最大整数)
  • 如果对一棵有 n 个结点的完全二叉树( 其深度为 [ l o g 2 n ] [log_2n] [log2n] + 1 )的结点按层序编号(从第1 层到第 [ l o g 2 n ] [log_2n] [log2n] + 1 层,每层从左到右) ,对任一结点i (1 <=i <= n )有:
    • 如果i=1 ,则结点i 是二叉树的根,无双亲;如果i> 1 ,则其双亲是结点[i/2] 。
    • 如果2i>n ,则结点i 无左孩子(结点i 为叶子结点) ;否则其左孩子是结点2i 。
    • 如果 2i+1>n ,则结点 i 无右孩子;否则其右孩子是结点 2i+1 。

二叉树存储

二叉链表

/* 二叉树的二叉链表结点结构定义 */
typedef struct BiTNode  /* 结点结构 */
{
    TElemType data; /* 结点数据 */
    struct BiTNode * lchild, * rchild;  /* 左右孩子指针*/
} BiTNode,*BiTNode;

二叉树遍历

二叉树的遍历( traversing binary tree) 是指从根结点出发,按照某种次序依次访问二叉树中所有结点.使得每个结点被访问-次旦仅被访问一次 。

前序遍历

规则是若二叉树为空,则空操作返回,否则先访问根结点,然后前序遍历左子树 , 再前序遍历右子树。

在这里插入图片描述

/* 二叉树的前序遍历递归算法 */
void PreOrderTraverse(BiTree *T)
{
    if(T == NULL) return;
    printf("%c",T->data); /* 显示节点数据 */
    PreOrderTraverse(T->lchild);/* 先序遍历左子树 */
    PreOrderTraverse(T->rchild);/* 后先序遍历右子树 */
}
中序遍历

规则是若树为空,则空操作返回,否则从根结点开始(注意并不是先访问根结点) ,中序遍历根结点的左子树,然后是访问根结点,最后中序遍历右子树 。

在这里插入图片描述

/* 二叉树中序遍历递归算法 */
void InOrderTraverse(BiTree *T)
{
    if(T == NULL) return;
    InOrderTraverse(T->lchild); /* 中序遍历左子树 */
    printf("%c",T->data);		/* 显示节点数据 */
    InOrderTraverse(T->rchild); /* 中序遍历右子树 */   
}
后续遍历

规则是若树为空,则空操作返回,否则从左到右先叶子后结点的方式遍历访问左右子树,最后是访问根结点。

在这里插入图片描述

/* 二叉树的后序遍历递归算法 */
void PostOrderTraverse(BiTree *T)
{
    if(T == NULL) return;
    PostOrderTravers(T->lchild);/* 后序遍历左子树 */
    PostOrderTravers(T->rchild);/* 后序遍历右子树 */
    printf("%c",T->data);		/* 显示节点数据 */
}
层序遍历

规则是若树为空 , 则空操作返回,否则从树的第一层,也就是根结点开始访问,从上而下逐层遍历,在同一层中 , 按从左到右的颇用才结点逐个访问 。

在这里插入图片描述

二叉树的建立

/* 按前序输入二叉树中节点的值(一个字符) */
/* #表示空树,构造二叉链表表示二叉树T */
void CreateBiTree(BiTree *T)
{
    TElemType ch;
    scanf("%c",&ch);
    if(ch == "#")
        *T = NULL;
    else{
        *T = (BiTree)malloc(sizeof(BiTNode));
        if(!*T)
            exit(OVERFLOW);
        (*T)->data = ch;  /* 生成根节点 */
        CreateBiTree(&(*T)->lchild); /* 构造左子树 */
        CreateBiTree(&(*T)->rchild); /* 构造右子树 */
    }
}
  • 9
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值