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;
}