题目来源
https://pintia.cn/problemsets/994805046380707840/problems/994805065406070784
题目描述
题解思路
知道中序和前序,就可以唯一确定二叉树.
1 2 3 4 5 6 7 中序
4 1 3 2 6 5 7 前序
样例中,4为整棵树的根节点,从4进入,在中序中找到4,因为中序遍历先访问左子树,再根节点,再右子树,因此中序中4左侧就为左子树结点,记此时根节点左子树结点数为a,右侧为右子树结点,记此时根节点右子树结点数为b。而前序遍历先访问根,再左子树再右子树,所以在前序中从根下一个节点开始算,接下去a个数则为4的左子树结点,在左子树结束的下一个到结束则为右子树结点。设定好边界,接下去递归处理左子树右子树。题中的反转,只需要在递归时,将lchild和rchild时候反过来即可。最后利用队列进行层序遍历。
题解代码
#include <iostream>
#include <queue>
using namespace std;
const int N=100010;
int sz1[1010],sz2[1010];
int n,flag;
typedef struct node
{
int data;
struct node *lchild;
struct node* rchild;
}node,*root;
root build(int l1,int r1,int l2,int r2)//在前序中树范围为l1到r1,中序中树的范围为l2到r2
{
if(l1>r1)return NULL;
int pos=l2;
while(pos<=r2&&sz1[l1]!=sz2[pos])pos++;//找到中序中在l2到r2之间和此时的根节点sz1[l1]相等的坐标pos
node *no=(root)malloc(sizeof(node));
no->data=sz1[l1];//根节点创建按
no->rchild=build(l1+1,l1+pos-l2,l2,pos-1);//反转后右子树指针指向左子树的递归。
no->lchild=build(l1+pos-l2+1,r1,pos+1,r2);
return no;
}
void fun(root p)
{
//cout<<p->data<<" ";
queue<root>q;
q.push(p);
while(q.size())
{
root now=q.front();
q.pop();
if(!flag)cout<<now->data,flag=1;
else cout<<" "<<now->data;
if(now->lchild!=NULL)q.push(now->lchild);
if(now->rchild!=NULL)q.push(now->rchild);
}
}
int main(void)
{
cin>>n;
for(int i=1;i<=n;i++)cin>>sz2[i];
for(int i=1;i<=n;i++)cin>>sz1[i];
node *roo=build(1,n,1,n);//创建二叉树
fun(roo);//层序遍历
//system("pause");
return 0;
}