《劍指Offer》第二版之重建二叉樹(五)

目錄

題目:
輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重複的數字。例如,輸入前序遍歷序列{1,2,4,7,3,5,6,8}和中序遍歷序列{4,7,2,1,5,3,8,6},則重建如圖2.6所示的二叉樹並輸出它的頭節點。二叉樹節點的定義如下:
stuct BinaryTreeNode {
	int m_nValue;
	BinaryTreeNode* m_pLeft;
	BinaryTreeNode* m_right;
}

思路:
在二叉樹的前序遍歷序列中,第一個數字總是樹的根節點的值。但在中序遍歷序列中,根節點的值在序列的中間,左子樹的節點的值位於根節點的值的左邊,而右子樹的節點的值位於根節點的值的右邊。因此我們需要掃描中序遍歷序列,才能找到根節點的值。
步驟:
1.前序遍歷序列的第一個數字1就是根節點的值。掃描中序遍歷序列,就能確定根節點的值的位置。根據中序遍歷的特點,在根節點的值1前面的3個數字都是左子樹的值,位於1後面的數字都是右子樹節點的值。
2.由於在中序遍歷序列中,有3個數字是左子樹節點的值,因此左子樹共有3個左子節點。同樣,在前序遍歷序列中,根節點後面的3個數字就是3個左子樹的節點的值,再後面的所有數字都是右子樹節點的值。這樣我們就在前序遍歷和中序遍歷兩個序列中分別找到了左、右子樹對應的子序列。
3.既然我們已經分別找到了左、右子樹的前序遍歷序列和中序遍歷序列,我們可以用同樣的方法分別構建左、右子樹。也就說,接下來的事情可以用遞歸的方法去完成。
代碼:
package test;

public class BinaryTreeNode {

	public static void main(String[] args) {
		int[] pre = {1, 2, 4, 7, 3, 5, 6, 8};
		int[] in = {4, 7, 2, 1, 5, 3, 8, 6};
		TreeNode root = reConstructBinaryTree(pre, in);
		printTree(root);
	}
	
	private static void printTree(TreeNode root) {
		if(root != null) {
			printTree(root.left);
			System.out.println(root.value);
			printTree(root.right);
		}
	}
	
	public static TreeNode reConstructBinaryTree(int[] pre, int[] in) {
		//對輸入數據進行校驗
		if(pre == null || in == null || pre.length != in.length)
			return null;
		return construct(pre, 0, pre.length - 1, in, 0, in.length - 1);
	}
	
	private static TreeNode construct(int[] pre, int ps, int pe, int[] in, int is, int ie) {
		//5.遞歸結束條件
		if(ps > pe)
			return null;
		//1.獲取根節點
		int root = pre[ps];
		
		//2.掃描中序遍歷序列,確定根節點的位置
		int index = is;
		while(index <= ie && root != in[index])
			index++;
		
		//3.創建根節點
		TreeNode node = new TreeNode(root);
		
		//4.創建左右子節點
		node.left = construct(pre, ps + 1, ps + index - is, in, is, index - 1);
		node.right = construct(pre, ps + index - is + 1, pe, in, index + 1, ie);
		
		return node;
	}
	
	static class TreeNode {
		int value;
		TreeNode left;
		TreeNode right;
		
		public TreeNode(int value) {
			this.value = value;
		}
	}
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章