编程之美上有道题是根据前序和中序来构建二叉树,当元素不同时,此树是唯一的。
当要根据前序和后序来构建二叉树时,此时即使元素都不同,也不是唯一的,举个例子
// 1 1// 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); } }有此可知,基本上由前序后后序只能确定完全二叉树,或者满二叉树。