题目:
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含有重复的数字。例如,前序遍历序列:{1,2,3,7,3,5,6,8},中序遍历序列:{4,7,2,1,5,3,8,6},请重建出如图所示的二叉树。
分析:
如图所示,前序遍历序列的第一个数字1就是跟结点的值。扫描中序遍历序列,就能确定跟结点的值的位置。根据中序遍历特点,在根结点的值1前面的3个数字都是左子树结点的值,为于1后面的数字都是右子树的值。在中序遍历中,有3个数字是左子树的值,因此左子树总共有3个左子结点。同样,在前序遍历中,根结点后面的3个数字就是3个左子树节点的值,同后面的所有数字都是右子树节点的值。既然分别找到了左右子树的前序遍历序列和中序遍历序列,我们可以用同样的方法去构建左右字树。用递归的方法。
代码:
struct BinaryTreeNode
{
int m_nValue ;
BinaryTreeNode * m_pLeft;
BinaryTreeNode * m_pRight;
}
BinaryTreeNode * constuct(int* preorder, int* inorder, int length) { if(preorder == NULL || inorder == NULL || length <= 0) { return NULL; } return construct_method(preorder, preorder+length-1, inorder,inorder+length-1); }
BinaryTreeNode * construct_method(int* preorder, int* endpreorder, int* inorder, int* endinorder){ int root_value = preorder[0];BinaryTreeNode * root = new BinaryTreeNode();root->m_nValue = root_value ;root->left = NULL; root->right = NULL;if(preorder == endpreorder) { //如果只有一个结点,则返回该结点的指针。if(inorder == endinorder && *preorder == *endpreorder)return root;
else
throw std::exception("Invalid input."); }//在中序遍历中查找根结点的值 int* rootInorder = inorder; while(*rootInorder != root_value && rootInorder < endinorder) rootInorder++; int left_len = rootInorder - inorder; int* left_preorder_end = preorder + left_len; //构建左子树 if(left_len > 0) { root->m_pLeft = construct_method(preorder+1, left_preorder_end, inorder, rootInorder-1); } //构建右子树 if(left_len < endpreorder - preorder) { root->m_pRight = construct_method(left_preorder_end+1, endpreorder, rootInorder+1, endinorder); } return root; }
//测试
int main() { int pre[8] = {1,2,4,7,3,5,6,8}; int in[8] = {4,7,2,1,5,3,8,6}; binary_tree_node* root = binary_tree_constuct(pre, in, 8); }