#include<bits/stdc++.h>
using namespace std;
/*已知先序和中序求后序*/
void transfer(char *preorder,char *inorder,int len)
{
int i,left_len,right_len;//left_len,right_len分别表示每次找到根之后左右子树的节点个数
left_len=right_len=0;
char *p,*q;//q指向先序,p指向中序
if(len==0)//长度为0就返回
return;
q=preorder;
p=inorder;
while(*p++!=*q)//循环结束时,说明找到了根的位置,然而此时的p指向根的后面一个元素因为++了,并且可以算出left_len,right_len
left_len++;
right_len=len-left_len-1;
transfer(q+1*sizeof(char),inorder,left_len);//左子树递归
transfer(q+(left_len+1)*sizeof(char),p,right_len);//右子树递归,注意这里的p不需要++,它已经指向刚才相等元素的后一个地址了,因为while语句中写的是*p++
printf("%c",*q);//打印元素,在左右之后打印也符合后序遍历的特点吧
}
int main()
{
char preorder[100],inorder[100];
while(scanf("%s%s",preorder,inorder)!=EOF)
{
transfer(preorder,inorder,strlen(preorder));
printf("\n");
}
}
2018.7.3更新
有一种更为通用的方法,若出的不是字符串就麻烦了,但是基本思路是一样的。
#include <bits/stdc++.h>
using namespace std;
#define MAX 1000
int pre[MAX];//先序遍历输出
int mid[MAX];//中序遍历输出
typedef struct bnode//二叉树结构体定义
{
int data;
struct bnode *lchild,*rchild;
}BNode,*bitree;
/*根据递归定义,这个二叉树是先构造一个根节点,然后它的左指针和它的右指针分别又是递归定义*/
bitree construct_tree(int pre_left,int pre_right,int mid_left,int mid_right)//通过先序和中序构建一个二叉树
{
int index,cn;//index确定根节点在中序遍历中数组下标,cn表示根的左子树的结点个数
bitree bt;
if(pre_left>pre_right||mid_left>mid_right)//边界条件,左边不可能大于右边,顶多等于,因此直接返回为空
return NULL;
bt=new BNode[sizeof(BNode)];//构造一个二叉树
bt->data=pre[pre_left];//这个二叉树的根节点就是先序遍历的第一个元素
if(pre_left==pre_right)//如果此时左右相等,说明此时就只有一个结点,就说明递归到叶子结点了,直接让左右孩子为NULL就行了
{
bt->lchild=bt->rchild=NULL;
return bt;
}
for(index=mid_left,cn=0;index<=mid_right;index++,cn++)//找到中序遍历中根的下标,同时更新cn
{
if(mid[index]==pre[pre_left])
break;
}
bt->lchild=construct_tree(pre_left+1,pre_left+cn,mid_left,mid_left+cn-1);//左子树递归
bt->rchild=construct_tree(pre_left+cn+1,pre_right,index+1,mid_right);//右子树递归
}
void posorder(bitree bt)//后序遍历
{
if(bt)
{
posorder(bt->lchild);
posorder(bt->rchild);
cout<<bt->data<<" ";
}
}
int main()
{
int n,i;
while(cin>>n)
{
bitree bt;
for(i=0;i<n;i++)
cin>>pre[i];
for(i=0;i<n;i++)
cin>>mid[i];
bt=construct_tree(0,n-1,0,n-1);
posorder(bt);
cout<<endl;
}
}
