分治思想。
主要思路:把先序序列的第一个数字当作一个根,在中序序列中寻找根,则中序序列中根前面的序列为根的左子树,后面的序列为右子树。
则再通过先序序列就可以找到当前根的左右节点,递归,将树还原,再后序遍历即可。
这套代码虽然一次性AC,但写的真的很累,太冗杂。引以为戒。
#include<cstdio>
struct BTnode
{
int data;
BTnode* lchild;
BTnode* rchild;
}node[1001];
void recovery(BTnode* node,int* pre,int *mid,int preL,int preR,int midL,int midR)
{
if(preR-preL==1&&midR-midL==1)
{
if(pre[preL]==mid[midL]) node[pre[preL]].rchild=&node[pre[preL+1]];
else node[pre[preL]].lchild=&node[pre[preL+1]];
return;
}
int next_mid,next_preR=preL;
for(int i=midL;i<=midR;i++)
{
if(mid[i]==pre[preL])
{
next_mid=i;
break;
}
for(int j=preL;j<=preR;j++)
{
if(pre[j]==mid[i]&&next_preR<j)
{
next_preR=j;
break;
}
}
}
//printf("%d %d %d\n",next_mid,midR,next_preR);
if(next_mid!=midL) node[pre[preL]].lchild=&node[pre[preL+1]];
if(next_mid!=midR) node[pre[preL]].rchild=&node[pre[next_preR+1]];
if(preL+1<next_preR&&midL<next_mid-1) recovery(node,pre,mid,preL+1,next_preR,midL,next_mid-1);
if(next_preR+1<preR&&next_mid+1<midR) recovery(node,pre,mid,next_preR+1,preR,next_mid+1,midR);
}
bool first;
void visit(BTnode* node)
{
if(node!=NULL)
{
visit(node->lchild);
visit(node->rchild);
if(first==1) {printf("%d",node->data); first=0;}
else printf(" %d",node->data);
}
}
void init()
{
for(int i=1;i<=1000;i++)
{
node[i].data=i;
node[i].lchild=NULL;
node[i].rchild=NULL;
}
}
int main()
{
int n;
while(~scanf("%d",&n))
{
if(n==1) {int temp; scanf("%d",&temp); printf("%d\n",temp); continue;}
init();
int pre[n],mid[n];
for(int i=0;i<n;i++)
scanf("%d",&pre[i]);
for(int i=0;i<n;i++)
scanf("%d",&mid[i]);
recovery(node,pre,mid,0,n-1,0,n-1);
first=1;
visit(&node[pre[0]]);
printf("\n");
// for(int i=1;i<=n;i++)
// {
// printf("%d\n",node[i].data);
// BTnode* temp1=node[i].lchild;
// BTnode* temp2=node[i].rchild;
// if(temp1!=NULL) printf("%d\n",temp1->data);
// else printf("0\n");
// if(temp2!=NULL) printf("%d\n",temp2->data);
// else printf("0\n");
// printf("\n");
// }
}
return 0;
}
7.22重写
#include<cstdio>
#include<cstring>
struct BT
{
int l;
int r;
int val;
BT(int a=0,int b=0,int c=0):l(a),r(b),val(c) {}
}tree[2000];
int Size=0;
int n,pre[2000],in[2000];
int findtree(int *P,int n1,int *I,int n2)
{
int root=Size++;
tree[root].val=P[0];
tree[root].l=-1;
tree[root].r=-1;
if(n1==1&&n2==1)
return root;
int mid;
for(mid=0;mid<n2;mid++)
{
if(I[mid]==P[0]) break;
}
if(mid!=0) tree[root].l=findtree(P+1,mid,I,mid);
if(n1-mid-1!=0) tree[root].r=findtree(P+1+mid,n1-mid-1,I+1+mid,n2-mid-1);
return root;
}
bool first=1;
void postorder(int root)
{
if(tree[root].l!=-1) postorder(tree[root].l);
if(tree[root].r!=-1) postorder(tree[root].r);
if(first) {printf("%d",tree[root].val); first=0;}
else printf(" %d",tree[root].val);
}
int main()
{
while(~scanf("%d",&n))
{
Size=0;
first=1;
for(int i=0;i<n;i++)
{
scanf("%d",&pre[i]);
}
for(int i=0;i<n;i++)
{
scanf("%d",&in[i]);
}
int root=findtree(pre,n,in,n);
postorder(root);
printf("\n");
}
return 0;
}