题目描述
给出一棵二叉树的中序与后序排列。求出它的先序排列。(约定树结点用不同的大写字母表示,长度≤8 \le 8≤8)。
输入格式
222行,均为大写字母组成的字符串,表示一棵二叉树的中序与后序排列。
输出格式
111行,表示一棵二叉树的先序。
输入输出样例
输入 #1
BADC
BDCA
输出 #1
ABCD
思路
给定二叉树的中序遍历和后序遍历,以此来重建这棵二叉树,重建完后进行一次先序遍历就ok了
中序遍历(左-根-右)是用来确定左子树和右子树的节点个数,先序遍历和后序遍历来确定根节点, 因为先序遍历的特性是(根-左-右),因此第一个结点必定是根节点;后序遍历的特性是(左-右-根)因此最后一个节点必定是根节点。用以上方法来重建这棵二叉树。最后进行一次先序遍历。
PS:今天终于发现了这个代码的错误之处,每次这个代码结果都是对的,但全是WA,之前我一口咬定是评测系统的问题 ,但是经过好几个oj都是错的,逐渐让我意识到事情的严重性 。。。今天把中序遍历和后序遍历输入时的字符串改为cin输入就AC了,之前用的getline,能出结果而且结果都是对的,但就是全WA,不知道什么原因。。。。
代码
#include <iostream>
#include <algorithm>
#include <string>
#include <queue>
#include <cstring>
#include <cmath>
#include <vector>
using namespace std;
struct node{ //结构体:数据,左孩子,右孩子
char data;
node* left;
node* right;
};
string zhong,hou,ans; //中序后序输入
char post[10],mid[10]; //后续,中序
node *create(int zz,int zy,int hz,int hy) //(中序遍历最左边,中右,后左,后右 )
{
if(hz>hy) //如果后序遍历的长度<=0,那么二叉树就不存在,返回NULL
return NULL;
node* root = new node; //新建一个结点,存放根节点
root->data = post[hy]; /*后序遍历最后一个数是根节点
(后顺序:左-右-根) */
int k;
for(k=zz;k<=zy;k++) //找中序遍历的根节点位置
{
if(mid[k]==post[hy]) //找到就退出,k为中序遍历的根节点位置
break;
}
int numleft=k-zz; /*中序遍历左边为左树,右边为右树 (中顺序:左-根-右)
由此计算出左边树的结点数(k-1-zz+1 == k-zz) */
root->left = create(zz,k-1,hz,hz+numleft-1); //创建左树
//将左子树根节点位置返回给root左指针
root->right = create(k+1,hy,hz+numleft,hy-1); //创建右树
//将右子树根节点位置返回给root右指针
return root; //返回根节点
}
void xian(node *root) //先序遍历(顺序:根-左-右)
{
if(root == NULL) //结点不存在就返回
return;
cout<<root->data; //直接输出根的data
xian(root->left); //走左孩子
xian(root->right); //右孩子
}
int main()
{
cin>>zhong>>hou; /*别用getline,不知道为啥,但是
被狠狠的教训过,结果是对的,但是各种WA*/
for(int i=0;i<zhong.size();i++)
mid[i]=zhong[i]; //将字符串放到数组中
for(int i=0;i<hou.size();i++)
post[i]=hou[i];
int len=zhong.size();
node* root = create(0,len-1,0,len-1);
//用root接受返回值, create(中左,中右,后左,后右)
xian(root);
//最后走一个先序遍历
return 0;
}