scau 19069 二叉树的右视图

scau 19069 二叉树的右视图,第1张

Description
字节跳动2021面试题

给定一个二叉树的根节点 root,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。
比如此树
   1            <---
 /   \
2     3         <---
 \     
  5             <---
从右侧看过去,答案是1,3,5。
实际上右视图就是二叉树层次遍历时每一层最右侧节点序列。
#include 
#include 
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(fdata);
        p=r;//p临时记录r
        while(flchild)//有左孩子
               Q[r++]=Q[f]->lchild;//该结点左孩子入队
            if(Q[f]->rchild)//有右孩子
               Q[r++]=Q[f]->rchild;//右孩子入队
            f++;//头指针+1,原结点出队,只留下原结点的左右孩子
        }
    }
}

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

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

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

#include 
#include 
#include 
#include 

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(fdata);
        p=r;//p临时记录r
        while(flchild)//有左孩子
               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;
}

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/langs/733555.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-04-27
下一篇2022-04-27

发表评论

登录后才能评论

评论列表(0条)

    保存