题目:输入某二叉树的前序遍历和中序遍历的结果,请重建该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如,输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并输出它的头节点。二叉树节点的定义如下:
struct BinaryTreeNode
{
int m_nValue;
BinaryTreeNode* m_pLeft;
BinaryTreeNode* m_pNight;
}
#include<iostream>
using namespace std;
struct BinaryTreeNode
{
int m_nValue;
BinaryTreeNode* m_pLeft;
BinaryTreeNode* m_pRight;
};
BinaryTreeNode* Structure(int* sPreorder, int* ePreorder, int* sInorder, int* eInorder)
//构建函数传入四根指针:前序&中序遍历的开始和结束指针
{
int rootValue = sPreorder[0]; //定义根节点的值
BinaryTreeNode* root = new BinaryTreeNode(); //创建二叉树结构体类型实例作为根节点
root->m_nValue = rootValue;
root->m_pLeft = root->m_pRight = nullptr; //初始化
if(sPreorder == ePreorder)
{
if(sInorder == eInorder && *sInorder == *eInorder)
return root;
else
throw std::runtime_error("Invalid input");
}
int* rootInorder = sInorder; //遍历中序序列找出根节点的值
while(rootInorder <= eInorder && *rootInorder != rootValue)
{
++ rootInorder;
if(rootInorder == eInorder && *rootInorder != rootValue)
{
throw std::runtime_error("Invalid input");
}
}
int leftLen = rootInorder - sInorder; //计算出左子树的长度,在前序遍历序列中分割出左子树和右子树的部分
int* leftPreorderEnd = sPreorder + leftLen;
if(leftLen > 0) //构建左子树
{
root->m_pLeft = Structure(sPreorder + 1, leftPreorderEnd, sInorder, rootInorder - 1);
}
if(ePreorder - leftPreorderEnd > 0) //构建右子树
{
root->m_pRight = Structure(leftPreorderEnd + 1, ePreorder, rootInorder + 1, eInorder);
}
return root;
}
void postOrderTraversal(BinaryTreeNode* root) //后序遍历验证结果
{
if (root == nullptr)
return;
postOrderTraversal(root->m_pLeft);
postOrderTraversal(root->m_pRight);
cout << root->m_nValue << " ";
}
int main()
{
int preorder[] = {1, 2, 4, 7, 3, 5, 6, 8};
int inorder[] = {4, 7, 2, 1, 5, 3, 8, 6};
try //如果在try块中发生了异常,程序会立即跳转到与之匹配的catch块,而不会继续执行try块中余下的代码
{
BinaryTreeNode* root = Structure(preorder, preorder + 7, inorder, inorder + 7);
cout << "Postorder traversal: ";
postOrderTraversal(root);
cout << endl;
}
catch (std::exception& e)
{
cout << "Exception occurred: " << e.what() << endl;
}
return 0;
}
解题思路:前序遍历(根左右),中序遍历(左根右),前序遍历第一个值为根节点,遍历中序序列找出该值,该值前面数字为左子树,后面数字为右子树,再去前序遍历中确定左右子树,然后递归,关键在于传入四根指针。