给出一颗二叉树的中序遍历和后序遍历,请你实现以下两个需求:
(1)请你输出这颗二叉树的层序遍历。
(2)请你输出这颗二叉树的树高。
输入格式:
第一行包含一个整数N(N<=1000)。二叉树的节点将从1到N编号。
第二行包含N个节点编号,表示这颗二叉树的中序遍历。
第三行包含N个节点编号,表示这颗二叉树的后序遍历。
输出格式:
第一行输出二叉树的层序遍历,节点编号之间用空格分隔,末尾没有多余空格。
第二行输出一个整数,代表二叉树的树高。
题目不保证输入的序列合法,如果遇到不合法的情况,请在一行中输出"ERROR",直接退出程序。
输入样例:
在这里给出一组输入。例如:
6
6 5 4 3 2 1
5 6 2 3 1 4
输出样例:
在这里给出相应的输出。例如:
4 6 1 5 3 2
4
输入样例:
在这里给出一组输入。例如:
3
2 1 3
3 2 1
输出样例:
在这里给出相应的输出。例如:
ERROR
题解
思路得到了一下这位的启发,首先表示感谢。
https://blog.csdn.net/qq_44378358/article/details/99879072
其实最开始我是用单纯的结构和C++的STL来做的,但一直有段错误。我执行着案例没有问题,但提交就会有段错误的点。
改了好长时间也不对,搁置一段时间后,决定从网上学习一下。
网上都是链表做法,遂学习了一下。
没太多要讲解的,就是根据中序和后序建立二叉树而已,简单注释即可。
ac代码---链表
#include<bits/stdc++.h> //建立一棵二叉树
using namespace std;
int N,in[2000],back[2000]; //N 中序 后序
int flag=1; //判断有问题
int height=-1; //深度
typedef struct BitNode{ //二叉链表结点结构
int data; //结点数据
struct BitNode *lchild,*rchild; //左右孩子指针
}BitNode,* BitTree; //并列改名,定义结点用BitNode,定义结点指针用BitTree
BitTree CreateTree(int inl,int inr,int backl,int backr) //建立二叉树函数
{
if(inl==inr) //只有一个元素
{
if(back[backl]!=in[inl])
{
flag=0; //判断错误
return NULL;
}
}
if(backl>backr) return NULL;
BitTree a = new BitNode; //分配空间(C++用的是new)
a->data = back[backr];
int m;
for(int i=inl;i<=inr;i++) //找根的位置下标
{
if(in[i]==back[backr])
{
m = i;
break;
}
}
//m是中序中的位置,用于后序要慎重!
a->lchild = CreateTree(inl,m-1,backl,backl+m-inl-1); //最后位置不能写back+m-1,应该相对backl控制数量
a->rchild = CreateTree(m+1,inr,backl+m-inl,backr-1); //这里写不好就会一直递归,段错误
return a;
}
void get_height(BitTree a,int ceng) //求深度函数
{
if(a==NULL)
{
if(ceng>height) height = ceng;
return;
}
get_height(a->lchild,ceng+1);
get_height(a->rchild,ceng+1);
ceng++;
}
queue<BitTree>q; //结构指针队列
vector<int>vec; //开个不定长数组
int main()
{
cin>>N;
for(int i=0;i<=N-1;i++)
cin>>in[i];
for(int i=0;i<=N-1;i++)
cin>>back[i];
BitTree root = CreateTree(0,N-1,0,N-1);
if(flag==0)
{
cout<<"ERROR\n";
return 0;
}
//层序遍历
q.push(root);
while(q.size())
{
BitTree a = q.front();
vec.push_back(a->data); //读入
if(a->lchild!=NULL) q.push(a->lchild);
if(a->rchild!=NULL) q.push(a->rchild);
q.pop();
}
for(int i=0;i<=vec.size()-1;i++)
{
if(i==0) cout<<vec[i];
else cout<<" "<<vec[i];
}
cout<<endl;
get_height(root,0);
cout<<height<<endl;
return 0;
}
ac代码---非链表
#include<bits/stdc++.h>
using namespace std;
int N,in[2000],back[2000]; //N 中序 后序
int flag=1; //判断有问题
int height=-1; //深度
struct node{
int l,r;
}p[2000];
int tree(int inl,int inr,int backl,int backr) //a 中序 b 后序
{
if(inl==inr) //只有一个元素
{
if(back[backl]!=in[inl])
{
flag=0; //判断错误
return 0;
}
}
if(backl>backr) return 0;
int item = back[backr];
int m;
for(int i=inl;i<=inr;i++)
{
if(in[i]==item)
{
m = i;
break;
}
}
p[item].l = tree(inl,m-1,backl,backl+m-inl-1);
p[item].r = tree(m+1,inr,backl+m-inl,backr-1);
return item;
}
void get_height(int root,int ceng) //求深度函数
{
if(root==0)
{
if(ceng>height) height = ceng;
return;
}
get_height(p[root].l,ceng+1);
get_height(p[root].r,ceng+1);
ceng++;
}
queue<int>q;
vector<int>vec;
int main()
{
cin>>N;
for(int i=0;i<=N-1;i++)
cin>>in[i];
for(int i=0;i<=N-1;i++)
cin>>back[i];
for(int i=0;i<=N-1;i++) //初始化
{
p[i].l = 0;
p[i].r = 0;
}
int root = tree(0,N-1,0,N-1);
if(flag==0)
{
cout<<"ERROR\n";
return 0;
}
q.push(root);
while(q.size())
{
if(p[q.front()].l!=0) q.push(p[q.front()].l);
if(p[q.front()].r!=0) q.push(p[q.front()].r);
vec.push_back(q.front());
q.pop();
}
for(int i=0;i<=vec.size()-1;i++)
{
if(i==0) cout<<vec[i];
else cout<<" "<<vec[i];
}
cout<<endl;
get_height(root,0);
cout<<height<<endl;
return 0;
}
二者思路完全一致,就是前者用了链表和指针,后者只用了单纯的结构。要是比赛,还是写后者好些。链表细节有点多,还要分配空间,太麻烦了。
如果只是想看正确结果,看前面即可。
接下来放上的,是我的最初解,就是案例ok,但是一直提示段错误的代码。
错误代码
#include<bits/stdc++.h>
using namespace std;
int height=-1;
struct node{
int l,r;
}p[2000];
int tree(string a,string b) //a 中序 b 后序
{
if(a.size()==1&&b.size()==1)
{
return a[0];
}
if(a.size()==0 || b.size()==0)
{
return 0;
}
char ch = b[b.size()-1];
int m = a.find(ch);
p[ch].l = tree(a.substr(0,m),b.substr(0,m));
p[ch].r = tree(a.substr(m+1),b.substr(m,a.size()-m-1));
return ch;
}
void get_height(int root,int ceng) //求深度函数
{
if(root==0)
{
if(ceng>height) height = ceng;
return;
}
get_height(p[root].l,ceng+1);
get_height(p[root].r,ceng+1);
ceng++;
}
queue<int>q;
int main()
{
int N;
cin>>N;
string a="",b="";
char ch;
for(int i=1;i<=N;i++)
{
cin>>ch;
a+=ch;
}
for(int i=1;i<=N;i++)
{
cin>>ch;
b+=ch;
}
for(int i=1;i<=N;i++)
{
p[i].l = 0;
p[i].r = 0;
}
int root = tree(a,b);
q.push(root);
int flag=1;
while(q.size())
{
if(p[q.front()].l!=0) q.push(p[q.front()].l);
if(p[q.front()].r!=0) q.push(p[q.front()].r);
if(flag==1)
{
cout<<q.front()-'0';
flag=0;
}
else
cout<<" "<<q.front()-'0';
q.pop();
}
cout<<endl;
get_height(root,0);
cout<<height<<endl;
return 0;
}
用上STL的find和substr显然降低了思考量,但是没有过(lll¬ω¬)