问题描述:
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
分析:
使用递归来实现这个问题
代码实现:
typedef struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
}TreeNode;
TreeNode* ConstructCore(int* startPreorder, int* endPreorder, int* startInorder,int* endInorder)
{
//先序遍历的第一个节点就是根节点
int rootVal = startPreorder[0];
TreeNode* root = new TreeNode();
root->val = rootVal;
root->left = root->right = NULL;
if (startPreorder == endPreorder) //先序遍历只有一个节点,递归的出口
{
if (startInorder == endInorder && *startPreorder == *startInorder) //中序遍历只有一个节点,且先序和中序相等
return root;
else
throw std::exception("Invalid input.");
}
//在中序序列中找根节点
int* rootInorder = startInorder;
while (rootInorder <= endInorder && *rootInorder != rootVal)
++rootInorder;
if (rootInorder == endInorder && *rootInorder != rootVal) //在中序中找不到根节点,则输入数据错误
throw std::exception("Invalid input.");
//确定先序和中序中 左树和右树的区间
int leftLength = rootInorder - startInorder; //中序中,左子树的长度
int *leftPreorderEnd = startPreorder + leftLength; //先序中,左子树的结束为止
if (leftLength > 0) //构建左子树(左子树还有节点)
root->left = ConstructCore(startPreorder + 1, leftPreorderEnd, startInorder, rootInorder - 1);
if (leftLength < endPreorder - startPreorder) //构建右子树(右子树还有节点)
{
root->right = ConstructCore(leftPreorderEnd + 1, endPreorder, rootInorder + 1, endInorder);
}
return root;
}
TreeNode* Construct(int* preOrder, int* inOrder, int length)//构建
{
if (preOrder == NULL || inOrder == NULL || length <= 0)
return NULL;
return ConstructCore(preOrder, preOrder + length - 1, inOrder, inOrder + length - 1);
}
int main()
{
int preOrder[] = { 1, 2, 4, 7, 3, 5, 6, 8 };
int inOrder[] = { 4, 7, 2, 1, 5, 3, 8, 6 };
int len = sizeof(preOrder) / sizeof(preOrder[0]);
TreeNode* root = Construct(preOrder, inOrder, len);
return 0;
}
思考:
1. 中序和后续结合重建?
2. 字符串表示的中序和后续结合的重建
3. 通过有2i+1 / 2i+2关系的数组进行重建
4. 输入时便创建