题目描述
输入某二叉树前序遍历和中序遍历的结果,重建该二叉树。
思路
二叉树的构建可以划分为构建左右子树两个小问题,大小问题本质一致,可以递归实现
- 根据前序遍历的第一个数字创建根结点
- 在中序遍历序列找到根结点的位置
- 确定左右子树节点数量
- 时间复杂度:O(N)
- 空间复杂度:O(1)
public BinaryTreeNode Construct(int preorder[],int inorder[]) {
if(preorder==null || inorder==null||preorder.length<=0||inorder.length<=0||preorder.length!=inorder.length)
throw new RuntimeException("数组不符合规范!");
return ConstructCore(preorder,0,preorder.length-1,
inorder,0,inorder.length-1);
}
public BinaryTreeNode ConstructCore(int preorder[],int startPreorder,int endPreorder,
int inorder[],int startInorder, int endInorder)
{
//停止递归的条件
if(startPreorder>endPreorder||startInorder>endInorder)
return null;
BinaryTreeNode root=new BinaryTreeNode(preorder[startPreorder]);
//前向序列和中序序列不匹配
if(startPreorder==endPreorder && startInorder==endInorder) {
if(preorder[startPreorder]!=inorder[startInorder])
throw new RuntimeException("数组不符合规范!");
return root;
}
for(int i=startInorder;i<=endInorder;i++)
{
if(preorder[startPreorder]==inorder[i]) {
//其中(i-startInorder)为中序遍历左子树结点数
//左子树
root.m_pleft=ConstructCore(preorder,startPreorder+1,startPreorder+(i-startInorder),
inorder,startInorder,i-1);
//右子树
root.m_pright=ConstructCore(preorder,startPreorder+(i-startInorder)+1,endPreorder,
inorder,i+1,endInorder);
}
}
return root;
}
测试
- 普通二叉树(完全二叉树,不完全二叉树)
- 特殊二叉树(左斜树,右斜树)
- 特殊输入测试(根结点为null;前序遍历与中序遍历不匹配)
// ======== 测试代码 ========
public void Test(String testName,int preorder[],int inorder[],int length) {
if(testName!=null)
System.out.println(testName+" begins");
System.out.print("The preorder sequence is: ");
for (int i=0;i<preorder.length;i++)
System.out.print(preorder[i]+" ");
System.out.println();
System.out.print("The inorder sequence is: ");
for (int i=0;i<inorder.length;i++)
System.out.print(inorder[i]+" ");
System.out.println();
BinaryTreeNode treeNode=Construct(preorder, inorder);
//T07_BinaryTree print=new T07_BinaryTree();
//print.printTree(treeNode);
}
// ======== 普通二叉树 ========
// 不完全二叉树
// 1
// / \
// 2 3
// / / \
// 4 5 6
// \ /
// 7 8
public void Test1()
{
int length=8;
int[] preorder = {1, 2, 4, 7, 3, 5, 6, 8};
int[] inorder = {4, 7, 2, 1, 5, 3, 8, 6};
Test("Test1",preorder,inorder,length);
}
// 完全二叉树
// 1
// / \
// 2 3
// / \ / \
//4 5 6 7
public void Test2()
{
int length=7;
int[] preorder = {1, 2, 4, 5, 3, 6, 7};
int[] inorder = {4, 2, 5, 1, 6, 3, 7};
Test("Test2",preorder,inorder,length);
}
// ======== 特殊二叉树 ========
// 所有结点都没有右子结点的二叉树
// 1
// /
// 2
// /
// 3
// /
// 4
// /
//5
public void Test3()
{
int length=5;
int[] preorder = {1, 2, 3, 4, 5};
int[] inorder = {5, 4, 3, 2, 1};
Test("Test3",preorder,inorder,length);
}
// 所有结点都没有左子结点
// 1
// \
// 2
// \
// 3
// \
// 4
// \
// 5
public void Test4()
{
int length=5;
int[] preorder = {1, 2, 3, 4, 5};
int[] inorder = {1, 2, 3, 4, 5};
Test("Test4",preorder,inorder,length);
}
// ======== 特殊输入测试 ========
//输入空指针
public void Test5()
{
int length=0;
int[] preorder = {};
int[] inorder = {};
Test("Test5",preorder,inorder,length);
}
//输入的两个序列不匹配
public void Test6()
{
int length=7;
int[] preorder = {1, 2, 4, 5, 3, 6, 7};
int[] inorder = {4, 2, 8, 1, 6, 3, 7};
Test("Test6",preorder,inorder,length);
}
public static void main(String[] args) {
T07_ConstructBinaryTree main=new T07_ConstructBinaryTree();
main.Test1();
//main.Test2();
//main.Test3();
//main.Test4();
//main.Test5();
//main.Test6();
}