根据前序和后序构建二叉树

编程之美上有道题是根据前序和中序来构建二叉树,当元素不同时,此树是唯一的。

当要根据前序和后序来构建二叉树时,此时即使元素都不同,也不是唯一的,举个例子

//    1     1
//   /         \
//  2         2
// /             \
//3             3
// preorder  1 2 3

// postorder 3 2 1

从上面的例子我们可以看到,此时可以构建出一个映像的二叉树来,即当只有左子树或者右子树的时候,是无法确定二叉树的。

下面是代码

// 3.1重构二叉树,根据前序、后序数列
//    1     1
//   /       \
//  2         2
// /           \
//3             3
// preorder  1 2 3
// postorder 3 2 1
BinaryTreeNode* rebuildCorePP( int *preStart, int *preEnd, int *postStart, int *postEnd )
{
	BinaryTreeNode *pRoot = new BinaryTreeNode(*preStart);
	if ( preStart == preEnd )
	{
		if ( postEnd == postStart && *postStart == *preStart )
			return pRoot;
		else 
			throw exception("Invalid input.");
	}
	int leftRootValue = preStart[1];
	int *postLeftEnd = postStart;
	while ( postLeftEnd < postEnd && leftRootValue != *postLeftEnd )
		++postLeftEnd;
	if ( postLeftEnd >= postEnd )
		throw exception("Invalid input.");

	//int leftLen = postLeftStart - postStart;
	// 如果 postLeftEnd + 1 = postEnd , 此时树不唯一,有两种情况,或者是只有左子树,或者是只有右子树
	if ( postLeftEnd + 1 == postEnd )
		throw exception("tree is not only.");
	int leftLen = postLeftEnd - postStart + 1;

	pRoot->m_pLeft  = rebuildCorePP(preStart+1, preStart+leftLen, postStart, postLeftEnd );
	pRoot->m_pRight = rebuildCorePP(preStart+leftLen+1, preEnd, postLeftEnd+1, postEnd-1 );

	return pRoot;
}


BinaryTreeNode* rebuildBinaryTreeByPP(int *preOrder, int *postOrder, int length )
{
	if ( preOrder == NULL || postOrder == NULL || length <= 0 )
		return NULL;
	return rebuildCorePP( preOrder, preOrder+length-1, postOrder, postOrder+length-1);
}
// ====================测试代码====================
void Test2(char* testName, int* preorder, int* postorder, int length)
{
	if(testName != NULL)
		printf("%s begins:\n", testName);

	printf("The preorder sequence is: ");
	for(int i = 0; i < length; ++ i)
		printf("%d ", preorder[i]);
	printf("\n");

	printf("The postorder sequence is: ");
	for(int i = 0; i < length; ++ i)
		printf("%d ", postorder[i]);
	printf("\n");

	try
	{
		BinaryTreeNode* root = rebuildBinaryTreeByPP(preorder, postorder, length);
		PrintTree(root);
	}
	catch(std::exception& exception)
	{
		printf("Invalid Input.\n");
	}

}
void TestRebuildTreeByPP()
{
	/*
	测试用例
	功能性测试:完全二叉树、满二叉树
	边界测试:没有左子树,没有右子树
	特殊输入测试:NULL,不符合序列

	*/
	{
		// 普通二叉树
		//              1
		//           /     \
		//          2       3  
		//         / \     / \
		//        4   5   6   7
		const int length = 7;
		int preorder[length] =  {1, 2, 4, 5, 3, 6, 7};
		int postorder[length] = {4, 5, 2, 6, 7, 3, 1};
		//int inorder[length] = {4, 2, 5, 1, 6, 3, 7};

		Test2("Test1", preorder, postorder, length);
	}
	{
		// 所有结点都没有右子结点
		//            1
		//           / 
		//          2   
		//         / 
		//        3 
		//       /
		//      4
		//     /
		//    5
		const int length = 5;
		int preorder[length] = {1, 2, 3, 4, 5};
		int postorder[length] = {5, 4, 3, 2, 1};
		//int inorder[length] = {5, 4, 3, 2, 1};

		Test2("Test2", preorder, postorder, length);
	}
	{
		// 所有结点都没有左子结点
		//            1
		//             \ 
		//              2   
		//               \ 
		//                3 
		//                 \
		//                  4
		//                   \
		//                    5
		const int length = 5;
		int preorder[length]  = {1, 2, 3, 4, 5};
		int postorder[length] = {5, 4, 3, 2, 1};
		//int inorder[length] = {5, 4, 3, 2, 1};

		Test2("Test3", preorder, postorder, length);
	}
	{

		// 树中只有一个结点
		const int length = 1;
		int preorder[length] =  {1};
		int postorder[length] = {1};
		//int inorder[length] = {5, 4, 3, 2, 1};

		Test2("Test4", preorder, postorder, length);
	}
}
    有此可知,基本上由前序后后序只能确定完全二叉树,或者满二叉树。


你可能感兴趣的:(根据前序和后序构建二叉树)