假設二叉樹中序遍歷爲:
int[] inOrder = { 4, 2, 5, 1, 6, 3, 7 };
後序遍歷爲
int[] postOrder = { 4, 5, 2, 6, 7, 3, 1 };
那麼,如何構建還原出這顆二叉樹?類似問題還有:給出二叉樹的先序和中序遍歷如何還原出二叉樹
算法思想:
- 後序遍歷中的最後一個元素爲二叉樹的根節點,這裏是數字1
- 在中序遍歷集合中查找數字1,記作位置i,注意i的左邊是左子樹,右邊是右子樹
- 假設在步驟2中,有X個元素在i的左側,那麼從後序遍歷集合中取前X個元素,得到的結果子集合即爲左子樹的後序遍歷,類似的,i的右側有Y個元素,那麼,從後續遍歷集合中取接下來的Y個元素,得到的結果即爲右子樹的後序遍歷
- 通過步驟2和步驟3構建出根節點的左子樹和右子樹
算法實現:
public class InorderPostOrderToTree {
public static int pIndex = 0;
public Node makeBTree(int[] inOrder, int[] postOrder, int iStart, int iEnd,
int postStart, int postEnd) {
if (iStart > iEnd || postEnd > postEnd) {
return null;
}
int rootValue = postOrder[postEnd];
Node root = new Node(rootValue);
pIndex++;
if (iStart == iEnd) {
return root;
}
int index = getInorderIndex(inOrder, iStart, iEnd, root.data);
root.left = makeBTree(inOrder, postOrder, iStart, index - 1, postStart,
postStart + index - (iStart + 1));
root.right = makeBTree(inOrder, postOrder, index + 1, iEnd, postStart
+ index - iStart, postEnd - 1);
return root;
}
public int getInorderIndex(int[] inOrder, int start, int end, int data) {
for (int i = start; i <= end; i++) {
if (inOrder[i] == data) {
return i;
}
}
return -1;
}
public void printInorder(Node root) {
if (root != null) {
printInorder(root.left);
System.out.print(root.data + " ");
printInorder(root.right);
}
}
public static void main(String[] args) {
int[] inOrder = {4, 2, 5, 1, 6, 3, 7};
int[] postOrder = {4, 5, 2, 6, 7, 3, 1};
InorderPostOrderToTree i = new InorderPostOrderToTree();
Node x = i.makeBTree(inOrder, postOrder, 0, inOrder.length - 1, 0,
postOrder.length - 1);
System.out.println("inorder traversal of constructed tree:");
i.printInorder(x);
}
}
class Node {
int data;
Node left;
Node right;
public Node(int data) {
this.data = data;
left = null;
right = null;
}
}
輸出結果
inorder traversal of constructed tree:
4 2 5 1 6 3 7