【笔记】遍历二叉树的应用

1.二叉树的计数

  二叉树的计数也可以通过遍历二叉树来实现,关于二叉树计数的算法有求二叉树叶子节点的个数、非叶子节点的个数。

  • 计算二叉树叶子结点个数

  求二叉树的叶子节点的个数递归定义如下。

leaf(T)=0,1,leaf(T>lchild)+leaf(T>rchild),T=NULLT

  当二叉树为空时,叶子节点个数为0;当二叉树只有一个根节点时,根节点就是叶子节点,叶子节点个数为1;其他情况下,计算左子树与右子树中叶子节点的和。由此可得到统计叶子节点个数的算法。

int LeafCount(BiTree T)
/*统计二叉树中叶子结点数目*/
{
    if(!T)                                  /*如果是空二叉树,返回0*/
      return 0;
    else
      if(!T->lchild&&!T->rchild)            /*如果左子树和右子树都为空,返回1*/
        return 1;
      else
        return LeafCount(T->lchild)+LeafCount(T->rchild); /*将左子树叶子结点个数与右子树叶子结点个数相加*/
}
  • 求二叉树的非叶子节点个数

  二叉树的非叶子节点的个数的递归定义如下:

Notleaf(T)=0,0,Notleaf(T>lchild)+Notleaf(T>rchild)+1,T=NULLT

  当二叉树为空时,非叶子结点的个数为0;当二叉树只有根节点时,根节点为叶子结点,非叶子节点个数为0;其他情况下,非叶子结点个数为左子树与右子树中非叶子节点的个数再加1(根结点)。

int NotLeafCount(BiTree T)
/*统计二叉树中非叶子结点数目*/
{
    if(!T)                                  /*如果是空二叉树,返回0*/
        return 0;
    else if(!T->lchild&&!T->rchild)         /*如果是叶子结点,返回0*/
        return 0;
    else
        return NotLeafCount(T->lchild)+NotLeafCount(T->rchild)+1; /*左右子树的非叶子结点数目加上根结点的个数*/
}
  • 计算二叉树的所有结点数

  二叉树的所有结点的个数的递归定义如下:

Allnodes(T)=0,1,Allnodes(T>lchild)+Allnodes(T>rchild)+1,T=NULLT

  若二叉树为空,则结点个数为0;在二叉树不为空的情况下,若左、右子树为空,则结点数为1;否则, 二叉树的结点数为左、右子树的结点数之和加1。

int AllNodes(BiTree T)
/*求二叉树中所有结点的个数*/
{
    if(!T)                         /*如果是空二叉树返回0*/
        return 0;
    else if(!T->lchild&&!T->lchild)/*如果是叶子结点返回1*/
        return 1;
    else                           /*如果是非叶子节点,也不是根节点*/
        return AllNodes(T->lchild)+AllNodes(T->rchild)+1;/*左右子树结点个数加根节点个数*/

}
  • 计算二叉树的深度

  二叉树的深度递归定义如下:

depth(T)=0,1,max(depth(T>lchild),depth(T>rchild))+1,T=NULLT

  当二叉树为空时,其深度为0;当二叉树只有根节点时,即结点的左、右子树均为空时,二叉树的深度为1;在其他情况下,求二叉树的左、右子树的最大值再加1(根节点)。由此,得到二叉树的深度的算法如下:

int BitTreeDepth(BiTree T)
/*计算二叉树的深度*/
{
    if(T == NULL)
        return 0;
    return
        BitTreeDepth(T->lchild)>BitTreeDepth(T->rchild)?1+BitTreeDepth(T->lchild):1+BitTreeDepth(T->rchild);
}

2.求叶子节点的最大最小枝长

  求二叉树的所有叶子节点的最大枝长的递归模型如下:

MaxLeaf(b)={0,Max(Maxleaf(b>left),Maxleaf(b>right))+1,b=NULLbNULL

  求二叉树的所有叶子节点的最小枝长的递归模型如下:

MinLeaf(b)={0,Min(Minleaf(b>left),Minleaf(b>right))+1,b=NULLbNULL

void MaxMinLeaf(BitTree T,int *max,int *min)
{
    int m1,m2,n1,n2;
    if(T==NULL)
    {
        *max=0;
        *min=0;
    }
    else
    {
        MaxMinLeaf(T->lchild,m1,n1);
        MaxMinLeaf(T->rchild,m2,n2);
        *max=(m1>m2?m1:m2)+1;
        *min=(m1<m2?m1:m2)+1;
    }
}

3.判断两颗二叉树是否相似

  两颗二叉树相似的定义:或者 T1 T2 都是空树,或者 T1 T2 的根节点相似,且 T1 T2 的左子树和右子树都相似。
  判断两颗二叉树是否相似可在用同样的次序遍历这两颗二叉树的过程中进行,因此可用递归算法实现。设t1和t2分别是指向二叉树 T1 T2 中当前结点的指针,初始时指向根节点。若t1和t2皆为空,则这两棵二叉树相似,返回1;若t1和t2中有一个为空,而另一个不为空,则这两棵二叉树不相似,返回0;否则遍历这两颗而二叉树的左子树,检查是否相似,然后遍历右子树,检查是否相似。

int BiTree_Like(BiTree t1,BiTree t2)
{
    if(t1==NULL && t2==NULL)
        return 1;
    if((t1!=NULL && t2==NULL)||(t1==NULL && t2!=NULL))
        return 0;
    if(BiTree_Like(t1->rchild,t2->rchild))
        /*若左子树相似*/
        return (BiTree_Like(t1->rchild,t2->rchild))
    else
        return 0;
}

4.交换二叉树的左右子树

  同样,在遍历二叉树的过程中也可以交换各个结点的左右子树。

void Bitree_Swap(BiTree T)
{
    BiTree p;
    if(!T=NULL)
        if(T->lchild!=NULL||T->rchild!=NULL)
    {
        p=T->rchild;
        T->lchild=T->rchild;
        T->rchild=p;
    }
    if(T->lchild!=NULL)/*若T的左子树不为空,则将左右子树交换*/
        Bitree_Swap(T->lchild);
    if(T->rchild!=NULL)/*若T的右子树不为空,则将左右子树交换*/
        Bitree_Swap(T->rchild);
}

  也可以用后序遍历的方式实现交换左右两颗子树,但不宜用中序遍历的方式实现,因为若用中序遍历的算法,则仅交换了根节点的左右孩子。

5.求根节点到r结点之间的路径

  假设二叉树采用二叉链表方式存储,root指向根节点,r所指结点为任一结点。由于后序遍历的过程中,访问到r所指结点时,此时栈中所有结点均为r所指的祖先,这些祖先便构成了一条从根节点到r所指结点之间的路径,故可采用后序遍历。

void path(BiTree root,BitNode *r)
{
    BitNode *p,*q;
    int i ,top=0;
    BitNode *s[StackSize];
    q=NULl;
    p=root;
    while(p!=NULL||top!=0)
    {
        while(p!NULL)
        /*遍历左子树*/
        {
            top++;
            if(top>=StackSize)
                exit(-1);
            s[top]=p;
            p=p->lchild;
        }
        if(top>0)/*若栈不为空*/
        {
            p=s[top];
            if(p->lchild == NULL ||p->rchild==q)/*根节点*/
            {
                if(p==r)/*找到r所指结点,则输出从根节点到r所指结点之间的结点*/
                {
                    for(i=1;i<=top;i++)
                    {
                        printf("%4d",s[i]->data);
                        top=0;
                    }
                }
                else
                {
                    q=p;/*用q保存刚刚遍历过的结点*/
                    top--;
                    p=NULL;
                }
            }
            else
                p=p->rchild;/*遍历右子树*/
        }
    }
}

  
  
  

  • 4
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值