已知二叉树的前序与中序遍历序列,求重建后的二叉树(即是二叉树的重建)

来源:互联网 发布:义和团红卫兵知乎 编辑:程序博客网 时间:2024/05/16 11:04
        关于二叉树的概念,想必大家基本上都已经很清楚了,那么在这里我就不再一一赘述了。那么请看下面这道题:
如果已知某二叉树的前序遍历结果为{1,2,4,7,3,5,6,8},中序遍历序列为{4,7,2,1,5,3,8,6},求此重建后的二叉树。
1、实现思路:
      我们都知道前序遍历是先访问根节点,然后是左子树,接着是右子树,因此在前序遍历序列中,第一个节点值就是根结点的值。但是在中序遍历中根节点是处在序列的中间,左子树的节点的值是位于根节点的左边,右子树的节点的值位于根结点值的右边,因此我们可以通过扫描中序遍历的序列来确定根节点的值和它的右子树和左子树。
分析过程如下图所示:

具体的代码实现如下图所示:
#include<iostream>
usingnamespacestd;

//结点信息
structBinaryTreeNode
{
          int_value;
          BinaryTreeNode* _left;
          BinaryTreeNode* _right;
};

BinaryTreeNode* RebuiltTree(int*preorder,int*inorder,intlength)
{
          //判空
          if(preorder==NULL||inorder==NULL||length<= 0)
          {
                   returnNULL;
    }

          return_RebuiltTree(preorder,preorder+length- 1,inorder,inorder+length- 1);
          
}

//重建二叉树--->传入前序遍历序列的头指针与尾指,中序遍历序列的头指针与尾指针针
BinaryTreeNode* _RebuiltTree(int*startpreorder,int*endpreorder,int*startinorder,int*endinorder)
{
          introotvalue =startpreorder[0];//前序遍历序列的第一个值为重建后二叉树的根节点的值
          BinaryTreeNode* root =newBinaryTreeNode();//创建一个指针,并为它申请一块空间,并且这个指针有此二叉树每个节点应有的全部内容
          //将根结点的值赋给root->_value,并且将root->_left 与 root->_right都赋为空
          root->_value = rootvalue;
          root->_left = root->_right =NULL;

          //在前序遍历序列中找根节点
          if(startpreorder==endpreorder)
          {
                   if(startinorder==endinorder&& *startpreorder== *startinorder)//如果此条件满足,则找到根结点的值
                   {
                             returnroot;
                   }
                   else
                   {
                             cout<<"非法输入"<<endl;
                   }
          }

          //在中序遍历中找到根结点的值,然后将中序遍历序列划分为两个区间,一个是根节点左边的左子树区间,一个是根节点右边的右子树区间
          int* _startinorder =startinorder;//让_startinorder指向startinorder,以防后面改变startinorder,从而在后面无法确定左子树的区间。
          
          //在中序遍历序列中查找根结点的值
          while(_startinorder <=endinorder&& *_startinorder != rootvalue)
          {
                   ++_startinorder;
          }
          //_startinorder与endinorder相等,并且*_startinorder != rootvalue说明中序遍历序列中没有根节点。
          if(_startinorder ==endinorder&& *_startinorder != rootvalue)
          {
                   cout <<"非法输入"<< endl;
          }
          //走到这里说明_startinorder指针已经走到根结点的位置
          intleftlength = _startinorder -startinorder;//求出左子树的长度及结点个数
          int* leftpreorderEnd =startpreorder+ leftlength;
          if(leftlength > 0)
          {
              //构建左子树
                   root->_left = _RebuiltTree(startpreorder+ 1, leftpreorderEnd,startinorder, _startinorder - 1);
          }
          if(leftlength <endpreorder-startpreorder)
          {
              //构建右子树
                   root->_right = _RebuiltTree(leftpreorderEnd + 1,endpreorder, _startinorder+1,endinorder);
          }
          returnroot;
}
voidTest()
{
          BinaryTreeNode* ret =NULL;
          intpreorder[] = { 1, 2, 4, 7, 3, 5, 6, 8 };
          intinorder[] = { 4, 7, 2, 1, 5, 3, 8, 6 };
          ret = RebuiltTree(preorder, inorder, 8);
          cout <<"ret="<< ret << endl;
}

1 0