已知中序排列和后序排列求先序排列

Name: 已知先后序和中序,求出它的先序排列

  Copyright: 始发于goal00001111的专栏;允许自由转载,但必须注明作者和出处

  Author: goal00001111

  Date: 11-12-08 10:58

题目描述:      

给出一棵二叉树的中序与后序排列。求出它的先序排列。(约定树结点用不同的大写字母表示,长度≤8)。

输入格式 Input Format      

 第一行为二叉树的中序序列,第二行为二叉树的后序序列

输出格式 Output Format    

 一行,为二叉树的先序序列

样例输入 Sample Input      

BADC

BDCA

样例输出 Sample Output    

ABCD

题目分析:

已知中序和前序排列,或者已知中序和后序序列,都能够构造一棵二叉树,此题考查后者。

前序遍历的规律是:输出根结点,输出左子树,输出右子树; 

中序遍历的规律是:输出左子树,输出根结点,输出右子树;

后序遍历的规律是:输出左子树,输出右子树,输出根结点;

根据中序和后序序列的规律,我们可以知道构造二叉树的过程是一个递归的过程,根据给定的 中序和后序序列,建立二叉树的根结点,并将中序序列划分为左子树序列和右子树序列,然后分别把左子树序列和右子树序列递归的构造左子树和右子树。

具体的算法是分别用数组mid[lm..rm]和post[tp..rp]存储给定的中序和后序序列。易知post[rp]为根结点,创建二叉树的根结点t,设t->data = post[rp];遍历mid,寻找根结点post[rp]的下标pos,则mid[lm..pos-1]为左子树序列,mid[pos+1..rm]为右子树序列;左子树序列的长度lenL= pos - lm,右子树序列的长度lenR= rm - pos。

很明显,若pos == lm,则lenL = 0,说明根结点无左子树;若pos == rm,则lenR = 0,说明根结点无右子树; 

根据后序序列的规律,可以知道根结点t的左子树的后序排列为post[lp..lp+lenL-1];

根结点t的右子树的后序排列为post[lp+lenL..rp-1]。

采用同样的方法递归构造根结点t的左右子树。

以样例输入为例:

中序序列:BADC

后序序列:BDCA  

1.得到根结点t->data = 'A';

2.遍历中序序列mid,得到mid[pos] = 'A',lenL = 1;

3.得到根结点t的左子树的中序序列为mid[lm..pos-1] = "B",右子树的中序序列为mid[pos+1..rm] = "DC";根结点t的左子树的后序序列为post[lp..lp+lenL-1] = "B",右子树的后序序列为post[lp+lenL..rp-1] = "DC";

4.递归构造根结点t的左子树t->lc,设t= t->lc:

           1.得到根结点t->data = 'B';

           2.遍历中序序列mid,得到mid[pos] = 'B',lenL = 0;

           3.得到根结点t的左右子树均为空,返回调用函数。

5. 递归构造根结点t的右子树t->rc,设t= t->rc:

           1.得到根结点t->data = 'C';

           2.遍历中序序列mid,得到mid[pos] = 'C',lenL = 1;

           3.得到根结点t的左子树的中序序列为"D",后序序列为"D";右子树为空,

           4.递归构造根结点t的左子树t->lc;

6.最后得到整棵二叉树,前序遍历二叉树,得到前序序列:ABCD。

说明:

算法思想:递归和分治。

数据结构:数组,二叉树。

时间复杂度:O(N);

空间复杂度:O(N);

附注:

若题目改为已知中序和前序序列,输出后序序列,因为先序序列pre[lp..rp]中根结点是第一个元素,所以只需将函数中的根结点数据由t->data = post[rp] 改为t->data = pre[lp]; 然后在递归构造左右子树时注意左子树中序序列为mid[lm+1..pos-1],右子树中序序列为mid[pos+1..rm],左子树先序序列为pre[lp+1..lp+lenL],右子树先序序列为pre[lp+lenL+1..rp],

最后后序遍历二叉树就行了。 

c++代码:

#include
using namespace std;
const int maxn=1e5+4;
typedef struct BTNode
{
    char data;
    struct BTNode *lc,*rc;//左,右孩子执针
}*BTree;
/*
函数名称:PostBtree
函数功能:给出一棵二叉树的中序与后序序列,构造这棵二叉树。
输入参数: BTree & t:二叉树的结点t
          char mid[]:存储了二叉树的中序序列的字符串
          char post[]:存储了二叉树的后序序列的字符串
          int lm, int rm:二叉树的中序序列在数组mid中的左右边界
          int lp, int rp:二叉树的后序序列在数组post中的左右边界
*/
void PostBtree(BTree &t,char mid[],char post[],int lm,int rm,int lp,int rp)
{
    t=new BTNode;//构造二叉树根节点
    t->data=post[rp];
    t->lc=t->rc=NULL;
    int pos=lm;
    while(mid[pos]!=post[rp])  pos++;
    int lenL=pos-lm;
    if(pos>lm) PostBtree(t->lc,mid,post,lm,pos-1,lp,lp+lenL-1);//有左孩子,递归构造左子树
    if(posrc,mid,post,pos+1,rm,lp+lenL,rp-1);//有右孩子,递归构造右子树
}
void Preorder(BTree p)//先序遍历
{
    if(p!=NULL)
    {
        printf("%c",p->data);//输出该节点
        Preorder(p->lc);//遍历左子树
        Preorder(p->rc);//遍历右子树
    }
}
int main()
{
    char mid[maxn];
    char post[maxn];
    BTree root;
    scanf("%s",mid);
    scanf("%s",post);
    PostBtree(root,mid,post,0,strlen(mid)-1,0,strlen(post)-1);
    Preorder(root);
    return 0;
}

 

你可能感兴趣的:(数据结构)