剑指Offer之二叉树重构

这题指的是给定一个前序和一个后序二叉树遍历序列,根据这两个序列构建出这个二叉树。

假设前序为:1 2 4 7 3 5 6 8

        中序为:4 7 2 1 5 3 8 6

构建二叉树必须得提供中序,原因就是如果只有前序或者后序是无法确定左右子树的,而中序遍历的准则是遍历左孩子,左孩子为NULL时遍历右孩子。因此,中序列中,在某一i节点的左边,说明此节点在该节点的左边,同理右侧也一样。

构建过程:

前序列pre中pre[0]=1;即为根节点,因此在中序列中查找根节点。中序列头部标记*inorderstart++,直到查找到1为*rootinorder。则左树长度为4,7,2为3。对应的前序列为2,4,7将2,4,7与中序4,7,2按此过程递归下去,同理右侧也一样。

#include <stdio.h>
#include <iostream>
using namespace std;
struct BinaryTreeNode
{
    int data;
    BinaryTreeNode *lchild;
    BinaryTreeNode *rchild;
};
BinaryTreeNode *ConStructCore(int *prestart,int *prend,int *inorderstart,int *inorderend)
{
   
    int rootValue=prestart[0];
    BinaryTreeNode* root=new BinaryTreeNode();
    root->data=rootValue;
    root->lchild=NULL;
    root->rchild=NULL;
    if(prestart==prend)
    {
        if(inorderend==inorderstart&&*inorderstart==*inorderend)
            return root;
        else
       
            throw  std::exception();
        
    }
    //统计左子树
    int *mLeftCourse=inorderstart;
    while(mLeftCourse<inorderend&&*mLeftCourse!=rootValue)
        mLeftCourse++;
    if(mLeftCourse==inorderend&&*mLeftCourse!=rootValue)
    throw  std::exception();
    //计算左子树长度
    int lcount=mLeftCourse-inorderstart;
    //计算右子树长度
    int rcount=inorderend-mLeftCourse;
    //左子树终点
    int *midend=prestart+lcount;
    if(lcount>0)
    {
        root->lchild=ConStructCore(prestart+1, midend, inorderstart, mLeftCourse-1);
    }
    if(lcount<prend-prestart)
    {
        root->rchild=ConStructCore(midend+1, prend, mLeftCourse+1, inorderend);
    }
    return root;
    
}
BinaryTreeNode *Construct(int *pre,int *inorder,int length)
{
    if(pre==NULL||inorder==NULL||length<=0)
        return NULL;
    return ConStructCore(pre, pre+length-1, inorder, inorder+length-1);
}
void PrintOrder(BinaryTreeNode *t)
{
    if(t==NULL) return;
   
    PrintOrder(t->lchild);
    
    PrintOrder(t->rchild);
    printf("%d ",t->data);
}
int main()
{
    freopen("/Users/sanyinchen/Workspaces/oc/conse/B_ali/B_ali/in.txt","r",stdin);
    int mPrevOrder[1001];   //二叉树的先序遍历
    int mInOrder[1001];     //二叉树的中序遍历
    int nodeNum ;//节点
    while(cin>>nodeNum)
    {
    for(int i=0;i<nodeNum;i++)
    scanf("%d",&mPrevOrder[i]);
    for(int i=0;i<nodeNum;i++)
    scanf("%d",&mInOrder[i]);
    BinaryTreeNode *root=Construct(mPrevOrder, mInOrder, nodeNum);
    PrintOrder(root);
    printf("\n");
    
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值