您的位置:首页 > 其它

根据中序和前序遍历重建二叉树

2017-02-01 16:37 351 查看

重建二叉树



我们知道,前序遍历是先访问root,再依次访问左子树和右子树,而中序遍历则是先访问左子树,再依次访问root和右子树。在前序遍历中,第一个总为当前树的根节点root,因此我们可以根据root值在中序遍历序列中划分左右子树。然后再在划分的左右序列中,重复该操作,最终可以得到我们想要的结果。

我们以上面的前序和中序序列为例:

第一次:

在前序遍历,得到1为根节点,根据中序序列,得到4,7,2为左子树,5,3,8,6为右子树。



第二次:

我们此时先看左子树,在前序遍历中,得到2为根节点,根据中序序列,得到4,7为左子树,右子树为空。



第三次:

我们继续看左子树,在前序遍历中,得到4为根节点,根据中序遍历,7在4的右边,所以7为右子树,4前面没有了,因此左子树为空,到这一步我们把这棵树的左子树序列已经得到了。



接下来,我们根据相同的原理可以得到右子树,最终这棵树的样子就可以得到了,如下图:



在上例中,我们都是先根据当前前序遍历的结果得到根节点,再根据根节点在当前中序遍历序列中的位置划分左右子树。

然后在左子树中根据前序遍历的结果得到根节点,再根据根节点在中序遍历序列中的位置划分左右子树这样的一个递归过程完成树的构建。因此我们根据上述原理写出如下的递归代码:

struct Node //定义树的结点和构造函数
{
int _data;
Node *_left;
Node *_right;
Node(int x)
: _data(x)
, _left(NULL)
, _right(NULL)
{}
};

Node* _CBT(int* preStart, int* preEnd, int* inStart, int* inEnd)
{
//根据先序序列得到当前的根节点
int rootValue = preStart[0];
Node *root = new Node(rootValue);
//如果此时先序和中序只有一个结点
if (preStart == preEnd)
{
if (inStart == inEnd && *preStart == *inEnd)
return root;
else//判错处理
{
cerr << "invalid input" << endl;
exit(1);
}
}
//根据根节点值找到它在中序序列的位置
int *inRoot = inStart;
while (inRoot <= inEnd && (*inRoot != rootValue))
++inRoot;
//找不到的话说明输入有错
if (inRoot == inEnd && (*inRoot != rootValue))
{
cerr << "invalid input" << endl;
exit(1);
}
//划分左右子树
int leftLen = inRoot - inStart;
int rightLen = inEnd - inRoot;
if (leftLen > 0)
root->_left = _CBT(preStart + 1, preStart + leftLen, inStart, inStart + leftLen - 1);
if (rightLen > 0)
root->_right = _CBT(preStart + leftLen + 1, preEnd, inStart + leftLen + 1 , inEnd);
return root;
}

Node *CreateBinaryTree(int *pre, int *in, int len)
{
if (pre == NULL || in == NULL || len <= 0)
return NULL;
return _CBT(pre, pre + len - 1, in, in + len - 1);
}


完整的代码以及测试各种情况点击我的github_6_ConstructBinaryTree查看。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: