Q:根据前序遍历和后续遍历序列可以唯一确定一颗二叉树吗?
A:先序遍历和后序遍历为什么不能唯一地确定一棵树?
结论是:如果树中所有结点的度为0或者2,则可以唯一还原。
当一个结点只有一个子结点(非空)时,则不能唯一还原。
static class Node
{
public int data;
public Node left;
public Node right;
}
public static Node create(int[] preArr,int[] postArr)
{
if (preArr==null||postArr==null||preArr.length==0||postArr.length==0)
{
return null;
}
return createHelper(preArr,0,preArr.length-1,postArr,0,postArr.length-1);
}
public static Node
createHelper(int[] preArr,int preStart,int preEnd,int[] postArr,int postStart,int postEnd)
{
if (preArr[preStart]!=postArr[postEnd])
{
throw new RuntimeException("Invalid input");
}
Node root=new Node();
//根节点就是前序遍历中开头的节点
root.data=preArr[preStart];
if (preStart==preEnd)
{
if (postStart==postEnd)
{
return root;
}
else
{
throw new RuntimeException("input valid");
}
}
//说明根节点度为1,只有一个孩子节点,这时无法唯一确定这颗二叉树
if (preArr[preStart+1]==postArr[postEnd-1])
{
throw new RuntimeException("Can't determine the tree");
}
//例如前序为:ABDECFG,后序为DEBFGCA
//A肯定是根节点,然后B是左孩子节点,C是右孩子节点
//先找到C在前序遍历序列中的位置:A BDE CFG
//则BDE就是A的左子树,CFG就是A的右子树
//同样在后序遍历序列中:DEB FGC A
//则DEB就是A的左子树,FGC就是A的右子树
//*********************************************************
//找到前序遍历序列中右子结点的位置
int temp=preStart;
while (temp<=preEnd&&preArr[temp]!=postArr[postEnd-1])
{
temp++;
}
if (temp>preEnd)
{
throw new RuntimeException("input valid");
}
int leftLen=temp-preStart-1;
if (leftLen>0)
{
root.left=createHelper(preArr,preStart+1,temp-1,postArr,postStart,postStart+leftLen-1);
}
if (leftLen<postEnd-postStart)
{
root.right=createHelper(preArr,temp,preEnd,postArr,postStart+leftLen,postEnd-1);
}
return root;
}
public static void main(String[] args)
{
//int[] preArr={1,2,4,6,7,5,3};
//int[] midArr={6,7,4,5,2,3,1};
int[] preArr={1,2,4,5,3,6,7};
int[] midArr={4,5,2,6,7,3,1};
Node t=create(preArr,midArr);
preOrder(t);
System.out.println();
midOrder(t);
System.out.println();
postOrder(t);
System.out.println();
doubleStackPostOrder(t);
}