【树】遍历算法应用

输出二叉树中的结点

【算法思想】
输出二叉树中的结点并无次序要求,因此可用三种遍历算法中的任何一种完成,只需将访问操作具体变为输出操作即可。下面给出采用先序遍历实现的算法。
【算法描述】

void PreOrder(BiTree root)
/* 先序遍历输出二叉树结点, root 为指向二叉树根结点的指针 */
{
    if (root != NULL)
    {
        printf("%c", root->data); /* 输出根结点 */
        PreOrder(root->LChild);   /* 先序遍历左子树 */
        PreOrder(root->RChild);   /* 先序遍历右子树 */
    }
}
输出二叉树中的叶子结点

【算法思想】
输出二叉树中的叶子结点与输出二叉树中的结点相比,它是一个有条件的输出问题,即在遍历过程中走到每一个结点时需进行测试,看是否满足叶子结点的条件。
【算法描述】

void PreOrder(BiTree root)
/* 先序遍历输出二叉树中的叶子结点 , root 为指向二叉树根结点的指针 */
{
    if (root != NULL)
    {
        if (root->LChild == NULL && root->RChild == NULL)
            printf("%c", root->data); /* 输出叶子结点 */
        PreOrder(root->LChild);       /* 先序遍历左子树 */
        PreOrder(root->RChild);       /* 先序遍历右子树 */
    }
}
统计叶子结点数目
  • 方法一

【算法思想】
统计二叉树中的叶子结点数目并无次序要求,因此可用三种遍历算法中的任何一种完成,只需将访问操作具体变为判断是否为叶子结点及统计操作即可。
【算法描述】

/* LeafCount 为保存叶子结点数目的全局变量,调用之前初始化值为 0 */
void leaf(BiTree root)
{
    if (root != NULL)
    {
        leaf(root->LChild);
        leaf(root->RChild);
        if (root->LChild == NULL && root->RChild == NULL)
            LeafCount++;
    }
}
  • 方法二

【算法思想】
给出求叶子点数目的递归定义:
1)如果是空树,返回 0;
2)如果只有一个结点,返回 1;
3)否则为左右子树的叶子结点数之和。
【算法描述】

int leaf(BiTree root)
{
    int LeafCount;
    if (root == NULL)
        LeafCount = 0;
    else if ((root->LChild == NULL) && (root->RChild == NULL))
        LeafCount = 1;
    else /* 叶子数为左右子树的叶子数目之和 */
        LeafCount = leaf(root->LChild) + leaf(root->RChild);
    return LeafCount;
}
建立二叉链表方式存储的二叉树
  • 给定一棵二叉树,我们可以得到它的遍历序列;
  • 反过来,给定一棵二叉树的遍历序列,我们也可以创建相应的二叉链表。

这里所说的遍历序列是一种“扩展的遍历序列”。在通常的遍历序列中,均忽略空子树,而在扩展的遍历序列中,必须用特定的元素表示空子树。例如,图中二叉树的“扩展先序遍历序列”为:AB.DF…G…C.E.H… 其中用小圆点表示空子树。在这里插入图片描述
【算法思想】
采用类似先序遍历的递归算法,首先读入当前根结点的数据,如果是“.”则将当前树根置为空,否则申请一个新结点,存入当前根结点的数据,分别用当前根结点的左子域和右子域进行递归调用,创建左、右子树。
【算法描述】

void CreateBiTree(BiTree *bt)
{
    char ch;
    ch = getchar();
    if (ch == '.')
        *bt = NULL;
    else
    {
        *bt = (BiTree)malloc(sizeof(BiTNode));
        (*bt)->data = ch;
        CreateBiTree(&((*bt)->LChild));
        CreateBiTree(&((*bt)->RChild));
    }
}
求二叉树的高度

二叉树的高度(深度)为二叉树中结点层次的最大值,也可视为其左、右子树高度的最大值加 1。
【算法思想】
二叉树 bt 高度的递归定义如下

  • 若 bt 为空,则高度为 0。
  • 若 bt 非空,其高度应为其左、右子树高度的最大值加 1,如下图所示。
    在这里插入图片描述
    【算法描述】
int PostTreeDepth(BiTree bt) /* 后序遍历求二叉树 bt 高度的递归算法 */
{

    int hl, hr, max;
    if (bt != NULL)
    {
        hl = PostTreeDepth(bt->LChild); /* 求左子树的深度 */
        hr = PostTreeDepth(bt->RChild); /* 求右子树的深度 */
        max = hl > hr ? hl : hr;        /* 得到左、右子树深度较大者*/
        return (max + 1);               /* 返回树的深度 */
    }
    else
        return (0); /* 如果是空树,则返回 0 */
}

求二叉树的高度是也可用前序遍历的方式实现。
【算法思想】
二叉树的高度(深度)为二叉树中结点层次的最大值。设根结点为第一层的结点,所有 h 层的结点的左、右孩子结点在 h+1 层。故可以通过遍历计算二叉树中的每个结点的层次,其中最大值即为二叉树的高度。
【算法描述】

void PreTreeDepth(BiTeee bt, int h)
/* 先序遍历求二叉树 bt 高度的递归算法,h 为 bt 指向结点所在层次,初值为 1*/
/*depth 为当前求得的最大层次,为全局变量,调用前初值为 0 */
{
    if (bt != NULL)
    {
        if (h > depth)
            depth = h;                   /*如果该结点层次值大于 depth,更新 depth的值*/
        PreTreeDepth(bt->Lchild, h + 1); /* 遍历左子树 */
        PreTreeDepth(bt->Rchild, h + 1); /* 遍历右子树 */
    }
}
按树状打印二叉树
假设以二叉链表存储的二叉树中,每个结点所含数据元素均为单字母。 要求实现二叉树的横向显示问题,如下图所示打印结果。

在这里插入图片描述

【算法思想】
(1)二叉树的横向显示应是二叉树竖向显示的 90。旋转。分析上图示可知,这种树形打印格式要求先打印右子树,再打印根,最后打印左子树,按由上而下顺序看,其输出的结点序为:CFEADB,这恰为逆中序顺序。解决二叉树的横向显示问题采用“逆中序”遍历框架,所以横向显示二叉树算法为先右子树、再根结点、再左子树的 RDL 结构。
(2)在这种输出格式中,结点的左、右位置与结点的层深有关,故算法中设置了一个表示当前根结点层深的参数,以控制输出结点的左、右位置,每当递归进层时层深参数加 1。这些操作应在访问根结点时实现。
【算法描述】

void PrintTree(BiTree bt, int nLayer)
/* 按竖向树状打印的二叉树 */
{
    if (bt == NULL)
        return;
    PrintTree(bt->RChild, nLayer + 1);
    for (int i = 0; i < nLayer; i++)
        printf(“ ”);
    printf(% c\n”, bt->data);
    /*按逆中序输出结点,用层深决定的左、右位置*/
    PrintTree(bt->LChild, nLayer + 1);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值