剑指Offer——由二叉树的前序中序重构

输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树。(测试用例中,"树"的输出形式类似于树的层次遍历,没有节点的用#来代替)先序遍历:先遍历根节点,再遍历左子树,再遍历右子树,对
摘要由CSDN通过智能技术生成

输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。

假设输入的前序遍历和中序遍历的结果中都不含重复的数字。
例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},
则重建二叉树。
(测试用例中,"树"的输出形式类似于树的层次遍历,没有节点的用#来代替)
先序遍历:先遍历根节点,再遍历左子树,再遍历右子树,对子树采用相对规则遍历。
中序序遍历:先遍历左子树,然后遍历右子树,最后遍历根节点,对子树采用相同规则。
分析:
 
1: 前序遍历的第一个元素,一定是这个树的根节点
2:对每棵树 遍历中序遍历序列,找到与根节点元素相等节点的位置pos,根据中序遍历的特点, 根节点向左的序列为左子树的中序遍历序列{4, 7, 2}, 根节点向右的序列为右子树的中序遍历序列{5, 3,  8, 6}.
3:根据根节点的位置可以节点的位置,可以分别求出,左右子树节点数量,这样可以在前序遍历中确认,左右子树的的前序遍历分别为{2, 4, 7},{3, 5, 6, 8}
4:对左右子树重复1,2,3步, 递归求解
5:递归返回条件,一个节点不存在子树时返回。
struct BinaryTreeNode
{
  int val;
  BinaryTreeNode* left;
  BinaryTreeNode* right;
};
void TreeBuild(BinaryTreeNode *root,int *pre,int *mid,int n)
{
    if(n<=0) return;
    int i;
    root->data=pre[0];
    for(i=0;i<n;i++)
    {
        if(mid[i]==root->data)
            break;//在中序遍历中寻找左子树的长度为i.
    }
    if(i>0)//左子树不为空
    {
        root->left=new BinaryTreeNode();
        TreeBuild(root->left,pre+1,mid,i);
    }
    if(i<n-1)//右子树不为空
    {
        root->right=new BinaryTreeNode();
        TreeBuild(root->right,pre+i+1,mid+i+1,n-i-1);
    }
}
//剑指Offer给的解题思路
BinaryTreeNode *TreeBuildCore(int *pre1,int *pre2,int *mid1,int *mid2)//pre1与pre2分别代表二叉树前序遍历的开始和结束指针
{
  int rootval=pre1[0];//头结点的值
  BinaryTreeNode *root=new BinaryTreeNode();//新建根结点
    root->val=rootval;
    root->left=root->right=NULL;
  if(pre1==pre2)
  {
      if(mid1==mid2&&*pre1==*mid1)
        return root;//只有一个结点
      else
        throw std::exception("Invalid input");
  }
  int *rootmid=mid1;
  //在中序遍历中查找根节点位置
  while(rootmid<=mid2&&rootmid!=rootval)
        rootmid++;

  if(rootmid==mid2&&*rootmid!=rootval)//在中序遍历中未找到头结点,报错
     throw std::exception("Invalid input");

  int leftlen=rootmid-mid1;//左子树的长度
  int *leftpre2=pre1+leftlen;
  if(leftlen>0)
  {
      //左子树不为空
      root->left=TreeBuildCore(pre1+1,leftpre2,mid1,rootmid-1);
  }
  if(leftlen<pre2-pre1)
  {
      //右子树不为空
      root->right=TreeBuildCore(leftpre2+1,pre2,rootmid+1,mid2);
  }
  return root;
}
BinaryTreeNode *TreeBulid(int *pre,int *mid,int length)
{
    if(pre==NULL||mid==NULL||length<=0)
        return NULL;
    return TreeBuildCore(pre,pre+length-1,mid,mid+lenght-1);
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值