scau 19069 二叉树的右视图

Description

字节跳动2021面试题

给定一个二叉树的根节点 root,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。
比如此树
   1            <---
 /   \
2     3         <---
 \     
  5             <---
从右侧看过去,答案是1,3,5。
实际上右视图就是二叉树层次遍历时每一层最右侧节点序列。
#include <stdio.h>
#include <malloc.h>
typedef long long ll;
using namespace std;
typedef struct BiTNode
{
    char data;
    struct BiTNode *lchild,*rchild;//左右孩子指针
} BiTNode,*BiTree;
void  CreateBiTree(BiTree &T)
{ /**< 先序建树算法 */
    char ch;
    scanf("%c",&ch);
    if (ch=='#') T = NULL;
    else
    {
        T = (BiTNode *)malloc(sizeof(BiTNode));
        T->data=ch;
        CreateBiTree(T->lchild);
        CreateBiTree(T->rchild);
    }
}
void Rview(BiTree T)
{/**< 右视图算法,用队列作为辅助存储结构 */
   _______________________
}
int main()
{
    BiTree T;
    CreateBiTree(T);
    Rview(T);
    return 0;
}
 

输入格式

输入二叉树的先序序列(只包含大写字母和#,大写字母代表树节点)。

输出格式

输出右视图的结果序列。

输入样例

AB##C##

输出样例

AC

       这道题把我折腾的不轻……整整两个小时……

       想必大家对先序、中序和后序遍历都比较熟了。那么对于这道题,首先,我们要先知道什么是二叉树的层次遍历,网上有很多博主解释的都非常清晰易懂,可以去搜来看看。我在这里简单介绍一下好了。层次遍历就是一层一层的输出,从上到下,从左到右。

拿这棵很丑的二叉树来说,它的层次遍历就是A   B C   D E F。

层次遍历的实现过程
1、首先将二叉树的根节点push到队列中,判断队列是否为空,不空就输出队头的元素,
2、判断结点是否有孩子,有的话就把结点的孩子push到队列中,
3、遍历过的结点出队
4、循环以上操作,直到Tree == NULL。

       这道题用到了层次遍历的思想,但又有点不同,因为这道题求的是树的右视图,也就是每一层的最右的结点,题目已经给了提示。所以只要把层次遍历改一点点就行了。


(我的水平比较有限,可能光讲听不懂,需要大家便看解释边看代码呜呜)

void Rview(BiTree T)
{
    BiTree Q[1005];//队列
    int f=0,r=0,p;//f为头指针,r为尾指针  出队时f++,入队时q[r++]
    Q[r++]=T;//先把根结点写进队列
    while(f<r)//当队列不为空时
    {
        printf("%c",Q[r-1]->data);
        p=r;//p临时记录r
        while(f<p)//每一层
        {
            if(Q[f]->lchild)//有左孩子
               Q[r++]=Q[f]->lchild;//该结点左孩子入队
            if(Q[f]->rchild)//有右孩子
               Q[r++]=Q[f]->rchild;//右孩子入队
            f++;//头指针+1,原结点出队,只留下原结点的左右孩子
        }
    }
}

       代码段的前两行大家应该是很熟悉的啦,队列是先进先出的嘛,入队的时候尾指针+1,出队的时候头指针+1

       那么根结点是比较特别的,所以把根结点先写进队列,不知道Q[r++]=T这里大家明不明白,因为我到后面就有点乱了,Q[]其实就是一个指针,指向了根结点

       然后是循环,while(f<r)是判断队列是否为空,对吧,当头尾指针相同的时候队列就是空队列了。首先输出上一层的最右侧结点,即Q[r-1]->data,r-1前面的就不用理它了用一个p临时记录r来一个循环,这个循环是用来把每一层的结点的左右孩子写进队列的,当把一个结点的孩子写进队列后,f++,把原结点出队,也就是开了新的一层。不管这个结点有没有左右孩子,f++都会执行,把这个结点出队,这样的话循环条件的范围就会变小了嘛,也就是f越来越接近r了。(就比如说f=1,p=3,那么内层循环就会进行两次,也就是会把第二层的两个结点的左右孩子入队,第一次内循环结束后把第二层的左结点出队,第二次内循环结束后把第二层的右结点出队。这有点像废话,大家还是自己画一棵二叉树,在纸上写写循环过程吧)当最外层的while循环一次后,就会输出每一层的最右侧结点,再开始新的一层。

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <malloc.h>

using namespace std;

typedef struct BiTNode
{
    char data;
    struct BiTNode *lchild,*rchild;//左右孩子指针
} BiTNode,*BiTree;

void  CreateBiTree(BiTree &T)
{
    /**< 先序建树算法 */
    char ch;
    scanf("%c",&ch);
    if (ch=='#') T = NULL;
    else
    {
        T = (BiTNode *)malloc(sizeof(BiTNode));
        T->data=ch;
        CreateBiTree(T->lchild);
        CreateBiTree(T->rchild);
    }
}

void Rview(BiTree T)
{
    BiTree Q[1005];//队列
    int f=0,r=0,p;//f为头指针,r为尾指针  出队时f++,入队时q[r++]
    Q[r++]=T;//先把根结点写进队列
    while(f<r)//当队列不为空时
    {
        printf("%c",Q[r-1]->data);
        p=r;//p临时记录r
        while(f<p)//每一层
        {
            if(Q[f]->lchild)//有左孩子
               Q[r++]=Q[f]->lchild;//该结点左孩子入队
            if(Q[f]->rchild)//有右孩子
               Q[r++]=Q[f]->rchild;//右孩子入队
            f++;//头指针+1,原结点出队,只留下原结点的左右孩子
        }
    }
}

int main()
{
    BiTree T;
    CreateBiTree(T);
    Rview(T);
    return 0;
}
  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现平衡二叉树的各种算法(如AVL树、红黑树等)可以应用在SCAU(South China Agricultural University,华南农业大学)的数据结构与算法课程中。这些算法的目标是确保二叉树的左子树高度差不超过1,从而使树的高度保持相对较小的水平,提高插入、删除和查找等操作的效率。 一种常见的平衡二叉树算法是AVL树。实现AVL树的关键是通过旋转操作来保持树的平衡。在SCAU,可以使用多种编程语言(如C++、Java等)实现AVL树算法。插入新节点时,首先按照二叉查找树的方式找到合适的插入位置,然后通过不同的旋转操作调整树的平衡。具体的实现包括左旋、旋、左旋和左旋等操作。 另一种常见的平衡二叉树算法是红黑树。SCAU可以使用编程语言(如C++、Java等)实现红黑树算法。红黑树通过使用辅助信息(即节点的颜色)来维持树的平衡。红黑树的插入操作包括节点的颜色变换和旋转操作。具体实现包括左旋、旋、颜色变换等操作。 无论是AVL树还是红黑树,它们的实现都需要处理平衡调整,在插入或删除节点时通过旋转和颜色变换等操作来保持树的平衡。实现这些算法需要对平衡树的定义和性质有深入的理解,并具备编程技巧和数据结构基础。SCAU的学生在学习数据结构与算法课程时,可以通过理论学习和实践编程来掌握实现平衡二叉树的各种算法。除了课程的学习,还可以通过参考相关的教材、博客、论文等来加深对平衡二叉树算法实现的理解。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值