PTA 浪漫侧影(25分)
题目
“侧影”就是从左侧或者右侧去观察物体所看到的内容。例如上图中男生的侧影是从他右侧看过去的样子,叫“右视图”;女生的侧影是从她左侧看过去的样子,叫“左视图”。
520 这个日子还在打比赛的你,也就抱着一棵二叉树左看看右看看了……
我们将二叉树的“侧影”定义为从一侧能看到的所有结点从上到下形成的序列。例如下图这棵二叉树,其右视图就是 { 1, 2, 3, 4, 5 },左视图就是 { 1, 6, 7, 8, 5 }。
于是让我们首先通过一棵二叉树的中序遍历序列和后序遍历序列构建出一棵树,然后你要输出这棵树的左视图和右视图。
输入格式:
输入第一行给出一个正整数 N (≤20),为树中的结点个数。随后在两行中先后给出树的中序遍历和后序遍历序列。树中所有键值都不相同,其数值大小无关紧要,都不超过 int 的范围。
输出格式:
第一行输出右视图,第二行输出左视图,格式如样例所示。
输入样例:
8 6 8 7 4 5 1 3 2 8 5 4 7 6 3 2 1
输出样例:
R: 1 2 3 4 5 L: 1 6 7 8 5
可能网上的大佬觉得题目太简单了,都说的非常地简洁,让我们这些“黑铁”难以理解。
首先题目意思要明白。从一侧自上向下看下去,意思就是,每一层只有两个节点!!!!
下面左边那个二叉树是我们平时的,右边就是题目中所说的了吧。(我反正是这么理解的。。这一题题目意思有一点点的难以理解)
弄清楚了这个,剩下的就好办了,根据中序、后序建树,然后bfs每一层。由于bfs按从左到右的顺序来的,所以每一层先入队的就是左侧影,反之,亦然。
首先说一下建树的大致过程:
中序:6 8 7 4 5 1 3 2
后序:8 5 4 7 6 3 2 1
后序遍历是:左右根,即最右边是根节点,先在后序遍历中找到根,然后在中序数组中定位根的位置,这样就可以在中序、后序数组中将左子树,右子树,根给区分开来:
根据前中序求后序
#include <iostream>
#include <string>
using namespace std;
string mid, pre;
//ml,mr表示中序的l,r;pl,pr同理
void f( int ml, int mr, int pl, int pr)
{
if ( ml <= mr && pl <= pr )
{
int root = pre[pl], i = ml;
int len = 0;
//根据前中序来找root,
while ( mid[i] != root ) {
i++;
len++;
}
//cout << len << '\n';
//递归左子树
f( ml, ml+len-1, pl+1, pl+len);
//递归右子树
f( i+1, mr, pl+len+1, pr);
cout << (char)root;
}
}
/*
总结就是:参数满足条件的话,找根,让i定位到中序的根上,然后分开左右子树,递归左右子树,输出根节点*/
int main()
{
cin >> mid >> pre;
f(0,mid.length()-1, 0, pre.length()-1);
return 0;
}
本题代码
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
//中序,后序
int in[35], po[35];
//每一层
vector<int> c[30];
typedef struct node {
int data, ceng; //数据域,ceng代表在第几层
node *l, *r;
}Node;
/*
题目给的中序、后序, 那么就前序建树。 <=========(前序:根左右,先处理根,再处理左右子树)
若给的是中序、前序, 那么就后序建树
*/
void create(Node* &root, int il, int ir, int pl, int pr ) {
if ( il > ir ) return;
//@@@@@@@@@@@@@@先处理根
//后序找根
int data = po[pr], j = il;
//j定位到in数组的根所在位置
while ( j <= ir && in[j] != data ) ++j;
int num = j - il; //看上面的图就理解了吧
if ( root == NULL ) {
root = new Node;
root->data = data;
root->l = root->r = NULL;
}
//@@@@@@@@@@@@@@@@再处理左右子树
create(root->l, il, j-1, pl, pl+num-1 ); //递归左树
create(root->r, j+1, ir, pl+num, pr-1); //递归右树
}
void bfs( Node* &root) {
queue<Node*> q;
root->ceng = 0;
q.push(root);
while ( !q.empty() ) {
Node *temp = q.front();
q.pop();
c[temp->ceng].push_back(temp->data); //所在的层push_back进去
if ( temp->l ) { //如果有左
temp->l->ceng = temp->ceng + 1; //+1就不用说了吧
q.push(temp->l);
}
if ( temp->r ) { //如果有右
temp->r->ceng = temp->ceng + 1;
q.push(temp->r);
}
}
}
int main()
{
int n;
cin >> n;
for ( int i = 0; i < n; ++i ) {
cin >> in[i];
}
for ( int i = 0; i < n; ++i ) {
cin >> po[i];
}
Node *root = NULL;
//建树
create(root, 0, n-1, 0, n-1);
//bfs
bfs(root);
//输出:
printf("R:");
for(int i = 0; i < 30; i++){
if( c[i].empty() ) break;
printf(" %d", c[i].back() );
}
cout << "\n";
printf("L:");
for(int i = 0; i < 30; i++){
if( c[i].empty() ) break;
printf(" %d", c[i][0]);
}
return 0;
}