重建二叉树

二叉树的遍历方式有4种:先序遍历,中序遍历,后序遍历以及层次遍历

根据中序遍历和另外任意一种遍历方式都可以唯一的重建二叉树!

如果没有中序遍历,其余任意两种组合均无法实现二叉树的重建,为什么?

其实原因很简单,先中后说的均为根结点的顺序,那么左子树一定先于右子树遍历到,中序遍历可以根据根结点,将左右子树分开!

那么如何根据中序遍历和后序遍历,重建出二叉树?

思路:假设递归过程中,某一步的后序序列区间为[postL,postR],中序序列区间为[inL,inR];

    1. 根据后序遍历的特点可知,postR位置为根结点;

    2. 从中序序列中,寻找出root的位置k,k左边的均为左子树,右边的均为右子树;

    3. 将左子树区间[postL,k-1]作为新的后序和中序序列,进行递归。

代码如下:

/*
 * 给定一个二叉树的后序遍历和中序遍历,重建这个二叉树
 */
/*
 * 思路:根据后序遍历找到根结点,根据中序遍历,根结点左边为左子树,根结点右边为右子树
 * 边界条件:后序区间为空
 */

#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;

const int maxn=50;
struct node{
    int data;
    node* lchild;
    node* rchild;
};

int pre[maxn],in[maxn],post[maxn];
int n;

node* create(int postL,int postR,int inL,int inR) //后序和中序的区间
{
    if(postL>postR)
        return NULL; 
    node* root=new node;
    root->data=post[postR];  //后序序列中,最后一个节点为根节点
    int k;
    for(k=inL;k<=inR;k++)
    {
        if(in[k]==root->data)
            break;
    }
    int numLeft=k-inL;  //左子区间为左子树0
    root->lchild=create(postL,postL+numLeft-1,inL,k-1);
    root->rchild=create(postL+numLeft,postR-1,k+1,inR);
    return root;
}

int num=0;

void BFS(node *root){
    //层次遍历
    queue<node*> q;
    q.push(root);
    while(!q.empty()){
        node* now=q.front();
        q.pop();
        printf("%d",now->data);
        num++;
        if(num<n)
            printf(" ");
        if(now->lchild!=NULL)
            q.push(now->lchild);
        if(now->rchild!=NULL)
            q.push(now->rchild);
    }
}
int main()
{
    scanf("%d",&n);
    int i;
    for(i=0;i<n;i++){
        scanf("%d",&post[i]);
    }

    for(i=0;i<n;i++){
        scanf("%d",&in[i]);
    }

    node* root=create(0,n-1,0,n-1);
    BFS(root);
prinf("\n");
return 0; }

仅供学习参考!

测试用例:【PAT A1020】

 

posted @ 2019-05-25 10:29  _小学生  阅读(2672)  评论(0编辑  收藏  举报