根据前序和后序构建二叉树
2013-08-03 20:09
148 查看
编程之美上有道题是根据前序和中序来构建二叉树,当元素不同时,此树是唯一的。
当要根据前序和后序来构建二叉树时,此时即使元素都不同,也不是唯一的,举个例子
// 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);
}
} 有此可知,基本上由前序后后序只能确定完全二叉树,或者满二叉树。
当要根据前序和后序来构建二叉树时,此时即使元素都不同,也不是唯一的,举个例子
// 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);
}
} 有此可知,基本上由前序后后序只能确定完全二叉树,或者满二叉树。
相关文章推荐
- 二叉树系列——根据前序和中序、中序和后序构建二叉树
- 面试题6:根据前序和中序序列构建二叉树(Leetcode-106)
- LeetCode:105_Construct Binary Tree from Preorder and Inorder Traversal | 根据前序和中序遍历构建二叉树 | Medium
- 根据树的前序遍历与中序遍历构建二叉树
- 根据前序和中序创建二叉树及二叉树的前序、中序、后序、层次打印
- 剑指offer04--根据前序和中序构建二叉树
- LeetCode: 106_Construct Binary Tree from Inorder and Postorder Traversal | 根据中序和后序遍历构建二叉树 | Medium
- 根据树的前序遍历与中序遍历构建二叉树
- 根据前序与后序遍历构建二叉树,并以后序遍历结果输出
- poj2255 根据二叉树的前序和中序遍历 求出树的后序遍历
- 【构建二叉树】01根据前序和中序序列构造二叉树【Construct Binary Tree from Preorder and Inorder Traversal】
- 根据前序和中序,构建二叉树
- 根据前序遍历和中序遍历构建二叉树以及根据中序遍历后序遍历构建二叉树
- 根据后序中序序列构建二叉树,按层次打印
- JAVA 根据二叉树的前序和中序获得后序,后序和中序获得前序
- [LeetCode]106 根据中序遍历和后序遍历构建二叉树
- 根据前序 中序 后序 构建二叉树
- Python练手之根据前序和中序&根据中序和后序重建二叉树,输出前序、中序和后序遍历结果
- 数据结构——根据后序遍历与中序遍历构建二叉树
- java实现根据前序遍历构建二叉树(前序遍历、中序遍历、后序遍历)