题目:输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1, 2, 4, 7, 3, 5, 6, 8}和中序遍历列{4, 7, 2, 1, 5, 3, 8, 6},则重建出图 所示的二叉树并输出它的头结点。二叉树结点的定义如下:
Struct BinaryTreeNode
{
int m_nValue;
int BinaryTreeNode* m_pLeft;
int BinaryTreeNode* m_pRight;
};
在前序遍历当中,第一个数总是树的根节点数值;在中序遍历当中,中间的数是树的根节点的数值,它左边的数是根节点左节点的数值,它右边的数是根节点右节点的数值。所以可以通过中序遍历来寻找根节点的数值。
由于在中序遍历序列中,有 3 个数字是左子树结点的值,因此左子树总共有 3 个左子结点。同样,在前序遍历的序列中,根结点后面的 3 个数字就是 3 个左子树结点的值,再后面的所有数字都是右子树结点的值。前序遍历和中序遍历两个序列中,分别找到了左右子树对应的子序列。
既然我们已经分别找到了左、右子树的前序遍历序列和中序遍历序列,我们可以用同样的方法分别去构建左右子树。也就是说,接下来的事情可以用递归的方法去完成。
在想清楚如何在前序遍历和中序遍历的序列中确定左、右子序列之后,我们可以写出如下的递归代码:
BinaryTreeNode* Construct(int* preorder,int* inorder,int length)
{
//如果指针为空,就返回空指针
if(preorder==NULL || inorder==NULLl || length<=0)
return NULL;
return(ConstructCore(preorder,preorder+length-1),)
BinaryTreeNode* ConstructCore
(
int* startPreorder,int* endPreorder,
int* startInorder,int* endInorder
)
//前序遍历序列的第一个数字是根节点的值
int rootValue=startPreorder[0];
BinaryTreeNode* root=new BinaryTreeNode();
root->m_nValue=rootValue;
root->m_pLeft=root->m_pRight=null;
//判断是否只有一个数
if(startPreorder==endPreorder)
if(startInorder==endInorder && *startPreorder==*endPreorder)
return root;
else
throw std::exception("Invalid input.");
}
//在中序遍历中找到根节点的值
int * rootInorder=startInorder;
while(rootInorder<=endInorder && * rootInorder!= rootValue)
rootInorder++;
//没找到根节点
if(rootInorder==endInorder && * rootInorder!= rootValue)
throw std:exception("Invalid input");
int leftLength=rootInorder-startInorder;//根节点的左子树的个数
int *leftPreorderEnd=startPreorder+leftLength;//在序列中根节点左边的一个数
if(leftLength>0)
{
//构建左子树
root->m_pLeft=ConstructCore(startPreorder+1,leftPreorderEnd,startInorder,rootInorder-1);
}
if(leftLength<endPreorder-startPreorder)
{
//构建右子树
root->m_pRight=ConstructCore(leftPreorderEnd+1,endPreorder,rootInorder+1,endInorder);
}