本题我写了两种算法来实现根据中序后序序列建树,但是原理其实大同小异,都是先从后序序列中去挑选根节点存入树中,再遍历中序序列找到根节点,根据找到的根节点位置去划分出左右子树。所以关键就是如何找到每次的根节点,以及如何确定出中序序列的遍历范围。
代码1
#include<iostream>
#include<vector>
#include<queue>
using namespace std;
template <class T>
struct BiNode{
T data;
BiNode<T> *lchild;
BiNode<T> *rchild;
};
template <class T>
class BiTree{
private:
BiNode<T> *Root;
//post和mid存储了后序和中序序列的信息,root为每次要存进去的根节点,
//start和end为中序序列遍历的起止位置。
//遍历中序序列是为了找到根节点,再根据它划分出左右子树,
//也就是确定下一次递归的根节点位置和中序序列遍历范围
BiNode<T> *CreateByPostMid(vector<T> &post,vector<T> &mid,int root,int start,int end)
{
if(start>end)
return NULL;
BiNode<T> *p=new BiNode<T>;
p->data=post[root];
int i=0;
for(i=start;i<=end;)
{
if(post[root]!=mid[i]) i++;
else break;
}
//因为后序是先左后右再根,所以找左子树的根节点需要跳过右子树的结点个数
p->lchild=CreateByPostMid(post,mid,root-(end-i)-1,start,i-1);
//而找右子树的根节点只需要减1
p->rchild=CreateByPostMid(post,mid,root-1,i+1,end);
return p;
}
public:
BiTree(vector<T> &post,vector<T> &mid)
{
int n=post.size();
Root=CreateByPostMid(post,mid,n-1,0,n-1);
}
void LevelOrder(int N)
{
if(Root==NULL)
return;
queue<BiNode<T> *> Q;
Q.push(Root);
while(!Q.empty())
{
BiNode<T> *p=Q.front();
Q.pop();
cout<<p->data;
N--;
if(N!=0) cout<<" ";
if(p->lchild!=NULL)
Q.push(p->lchild);
if(p->rchild!=NULL)
Q.push(p->rchild);
}
}
};
int main()
{
int N,x;
vector<int> v1,v2;
cin>>N;
for(int i=0;i<N;i++)
{
cin>>x;
v1.push_back(x);
}
for(int i=0;i<N;i++)
{
cin>>x;
v2.push_back(x);
}
BiTree<int> Tree(v1,v2);
Tree.LevelOrder(N);
return 0;
}
代码2
#include<iostream>
#include<vector>
#include<queue>
using namespace std;
template <class T>
struct BiNode{
T data;
BiNode<T> *lchild;
BiNode<T> *rchild;
};
template <class T>
class BiTree{
private:
BiNode<T> *Root;
//这里和上面其实差不多,只是记得不再是中序序列遍历的起始和结束位置,而是树的结点个数
//终止条件也有所不同,结束条件为n==0
BiNode<T> *CreateByPostMid(vector<T> &post,vector<T> &mid,int root,int imid,int n)
{
if(n==0)
return NULL;
BiNode<T> *p=new BiNode<T>;
p->data=post[root];
int i=0;
while(post[root]!=mid[imid+i]) i++;
p->lchild=CreateByPostMid(post,mid,root-(n-i),imid,i);
p->rchild=CreateByPostMid(post,mid,root-1,imid+i+1,n-i-1);
return p;
}
public:
BiTree(vector<T> &post,vector<T> &mid)
{
int n=post.size();
Root=CreateByPostMid(post,mid,n-1,0,n);
}
void LevelOrder(int N)
{
if(Root==NULL)
return;
queue<BiNode<T> *> Q;
Q.push(Root);
while(!Q.empty())
{
BiNode<T> *p=Q.front();
Q.pop();
cout<<p->data;
N--;
if(N!=0) cout<<" ";
if(p->lchild!=NULL)
Q.push(p->lchild);
if(p->rchild!=NULL)
Q.push(p->rchild);
}
}
};
int main()
{
int N,x;
vector<int> v1,v2;
cin>>N;
for(int i=0;i<N;i++)
{
cin>>x;
v1.push_back(x);
}
for(int i=0;i<N;i++)
{
cin>>x;
v2.push_back(x);
}
BiTree<int> Tree(v1,v2);
Tree.LevelOrder(N);
return 0;
}