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

版权声明:本文为博主原创文章,未经许可,不得转载! https://blog.csdn.net/bin_ge_love/article/details/51921666
依据前序遍历序列和中序序列重构二叉树
前序遍历:1,2,3,4,5,6,7

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


首先分析前序遍历和中序遍历序列的特点:
前序遍历:遍历的第一个为根节点
中序遍历:以根节点为分隔,根节点之前的全部为左子树,根节点之后的全部为右子树

依据这两个性质,要重建二叉树的话,我们就是先找到根节点,然后再分别找出它的左右子树,然后再分别以左右孩子为根节点,确定它的左右孩子

我们可以运用递归的思想来解决此题



下边是代码:

#include<iostream>
#include<stack>
using namespace std;

struct BinaryTreeNode
{
	BinaryTreeNode* _left;
	BinaryTreeNode* _right;
	int _value;
};


BinaryTreeNode* _RebuildTree(int* startPrev,int* endPrev,int* startIn,int* endIn)
{
	int rootValue = startPrev[0];    //前序遍历的第一个数字就是根节点的值
	BinaryTreeNode* root = new BinaryTreeNode;

	root->_value = rootValue;
	root->_left = NULL;
	root->_right = NULL;

	if (startPrev == endPrev)  //只有一个节点情况
	{
		if (startIn == endIn && *startPrev == *startIn)
		{
			return root;
		}
		else
		{
			throw exception("Invalid input!");
		}
	}

	//在中序遍历中找根节点的值
	int* rootIn = startIn;
	while (rootIn <= endIn && *rootIn != rootValue)
	{
		++rootIn;
	}

	if (rootIn == endIn && *rootIn != rootValue)//在中序遍历中没有找到的情况
	{
		throw exception("Invalid input!");
	}

	int leftLength = rootIn - startIn;
	int* leftPrevEnd = startPrev + leftLength;

	if (leftLength > 0)   //递归构建左子树
	{
		root->_left = _RebuildTree(startPrev + 1, leftPrevEnd, startIn, rootIn - 1);
	}

	if (leftLength < endPrev - startPrev)//递归构建右子树
	{
		root->_right = _RebuildTree(leftPrevEnd + 1, endPrev, rootIn + 1, endIn);
	}

	return root;
}

BinaryTreeNode* RebuildTree(int* prev, int* in, int len)
{
	if (prev == NULL || in == NULL || len <= 0)
	{
		return NULL;
	}

	return _RebuildTree(prev, prev + len - 1, in, in + len + -1);
}


void PreOrder(BinaryTreeNode* root)
{
	if (root == NULL)
		return;
	cout << root->_value << " ";
	PreOrder(root->_left);
	PreOrder(root->_right);

}

void PostOrder(BinaryTreeNode* root)
{
	if (root == NULL)
		return;
	PostOrder(root->_left);
	PostOrder(root->_right);
	cout << root->_value << " ";
}


void RebuildTreeTest()
{
	int prev[] = { 1, 2, 3, 4, 5, 6, 7 };
	int in[] = { 3, 2, 4, 1, 6, 5, 7};

	BinaryTreeNode* ret = RebuildTree(prev, in, 7);
	cout << "前序遍历: ";
	PreOrder(ret);
	cout << endl;
	cout << "后序遍历: ";
	PostOrder(ret);
	cout << endl;
}

int main()
{
	RebuildTreeTest();
	return 0;
}
这个代码关键之处是在于递归时函数传参问题,下边给出图片帮助理解。



下边是运行结果截图,为了检验其正确性,可以用后序遍历和监视窗口来检验。



猜你喜欢

转载自blog.csdn.net/bin_ge_love/article/details/51921666