重建二叉树

关于二叉树的重建,我总结如下,并以图文的形式展示:

一颗二叉树,已知先序遍历和中序遍历,要求还原出二叉树,问题不难,关键是细节:

思想:

1、先序遍历序列的第一个元素一定定是根节点,可以由此获取二叉树的根节点。

2、在中序遍历序列中查找到根节点,由中序遍历的性质可知,中序遍历中该根节点左边的序列一定在根节点的左子树中,而根节点右边的序列一定在右子树中。由此可以知道先序遍历中左子树以及右子树的起止位置。

3、分别对左子树和右子树重复上述的过程,直至所有的子树的起止位置相等时,说明已经到达叶子节点。

以上过程,递归就显得很重要:

先上一张图:


假设这是需要我们重新构建的二叉树。

此二叉树的前序遍历为:1,2,4,7,3,5,6,8

                   中序遍历为:4,7,2,1,5,3,8,6

再看:


同样的方法在子树中递归重建子树,以下是代码:

//声明重构
BinaryTreeNode* ConstructCore(int* startPreorder, int* endPreorder, int* startInorder, int* endInorder);

//重构
BinaryTreeNode* 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);
}

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 == *startInorder)
		{
            return root;
		}
    }

    // 在中序遍历中找到根结点的值
    int* rootInorder = startInorder;
	while (rootInorder <= endInorder && *rootInorder != rootValue)
	{
        ++ rootInorder;
	}

	if (rootInorder == endInorder && *rootInorder != rootValue)
	{
		cout << "非法序列" << endl;
		return;
	}

	//while循环结束,跳过,意思是找到了根节点
	//求出左子树的长度leftLength
    int leftLength = rootInorder - startInorder;  //虽然是指针相减,但指针内部也是整数
    int* leftPreorderEnd = startPreorder + leftLength; //找到前序遍历左子树最后一个节点
    if(leftLength > 0)
    {
        // 构建左子树
		//startPreorder + 1 原来前序的头往前走一个
        root->m_pLeft = ConstructCore(startPreorder + 1, leftPreorderEnd, 
            startInorder, rootInorder - 1);
    }

    if(leftLength < endPreorder - startPreorder)
    {
        // 构建右子树
        root->m_pRight = ConstructCore(leftPreorderEnd + 1, endPreorder,
            rootInorder + 1, endInorder);
    }
    return root;
}
赐教!




posted @ 2016-05-03 11:34  云端止水  阅读(264)  评论(0编辑  收藏  举报