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

来源:互联网 发布:淘宝我的仓库在哪里 编辑:程序博客网 时间:2024/05/16 09:27

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

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

//    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 1BinaryTreeNode* 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   7const 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//     ///    5const 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//                   \//                    5const 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);}}
    有此可知,基本上由前序后后序只能确定完全二叉树,或者满二叉树。