題目:輸入某二叉樹的前序遍歷和中序遍歷的結果,請從新構造出該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中不包含重複的數字。例如輸入的前序遍歷序列爲{1,2,4,7,3,5,6,8}和中序遍歷爲{4,7,2,1,5,3,6,8},則重建出二叉樹並輸出它的頭結點。ui
前序遍歷:根節點--》左節點--》右節點this
中序遍歷:左節點--》根節點--》右節點spa
後序遍歷:左節點--》右節點--》根節點3d
在二叉樹的前序遍歷序列中,第一個數字老是樹的根節點的值。但在中序遍歷中,根節點的值在序列的中間,左子樹的結點的值位於根節點的值的左邊,而右子樹的結點的值位於根節點的右邊。所以咱們須要掃描中序遍歷序列,才能找到根節點的值。code
如圖所示,前序遍歷序列的第一個數字1就是根節點的值。掃描中序遍歷序列,就能肯定根節點的值的位置。根據中序遍歷的特色,在根節點的值1前面3個數字都是左子樹結點的值,位於1後面的數字都是右子樹結點的值。blog
因爲中序遍歷序列中,有3個數字是左子樹結點的值,所以左子樹總共有3個左子結點。一樣,在前序遍歷的序列中,根節點後面的3個數字就是3個左子樹結點的值,再後面的全部數字都是右子樹結點的值。這樣咱們就在前序遍歷和中序遍歷兩個序列中,分別找到了左右子樹對應的子序列。遞歸
而後再根據左子樹的前序遍歷和中序遍歷找出根節點和左右子樹,能夠使用遞歸來完成,每次獲得根節點get
用左子樹來舉例:class
第二次:二叉樹
前序:247
中序:472
根節點2,由中序可知沒有右節點
第三次:
前序:47
中序:47
根節點:4
沒有了左子樹,7爲4的右節點
代碼以下:
/** * 樹節點 */ class BinaryTreeNode { int value; BinaryTreeNode leftNode; BinaryTreeNode rightNode; public BinaryTreeNode(int value){ this.value=value; } public int getValue() { return value; } public void setValue(int value) { this.value = value; } public BinaryTreeNode getLeftNode() { return leftNode; } public void setLeftNode(BinaryTreeNode leftNode) { this.leftNode = leftNode; } public BinaryTreeNode getRightNode() { return rightNode; } public void setRightNode(BinaryTreeNode rightNode) { this.rightNode = rightNode; } } public class RebuildTree { /** * 根據前序遍歷和中序遍歷重建二叉樹 * */ public static BinaryTreeNode rebuildTree(int[] preOrder, int[] inOrder){ if (preOrder == null || inOrder == null || preOrder.length == 0 || inOrder.length == 0 || preOrder.length != inOrder.length) { return null; } //根節點 BinaryTreeNode root=new BinaryTreeNode(preOrder[0]); root.setLeftNode(null); root.setRightNode(null); //左子樹節點的個數 int leftNum=0; for(int i=0;i<inOrder.length;i++){ if(inOrder[i]==root.getValue()){ break; }else{ leftNum++; } } //右子樹節點的個數 int rightNum=inOrder.length-1-leftNum; //重建左子樹 while(leftNum>0){ //用來存放左子樹的前序遍歷 int leftPreOrder[]=new int[leftNum]; //用來存放左子樹的中序遍歷 int leftInOrder[]=new int[leftNum]; //賦值給左子樹每一個節點值,把左子樹再獨立成一棵樹 for(int i=0;i<leftNum;i++){ leftPreOrder[i]=preOrder[i+1]; leftInOrder[i]=inOrder[i]; } BinaryTreeNode leftRoot=rebuildTree(leftPreOrder, leftInOrder); root.setLeftNode(leftRoot); } //重建右子樹 while(rightNum>0){ //右子樹的前序遍歷 int rightPreOrder[]=new int[rightNum]; //右子樹的中序遍歷 int rightInOrder[]=new int[rightNum]; //賦值 for(int i=0;i<rightNum;i++){ rightPreOrder[i]=preOrder[i+1+leftNum]; rightInOrder[i]=preOrder[i+1+leftNum]; } BinaryTreeNode rightNode=rebuildTree(rightPreOrder, rightInOrder); root.setRightNode(rightNode); } return root; } public static void main(String[] args) { // 二叉樹的先序序列 int[] preOrder = { 1, 2, 4, 7, 3, 5, 6, 8 }; // 二叉樹的中序序列 int[] inOrder = { 4, 7, 2, 1, 5, 3, 8, 6 }; BinaryTreeNode root = rebuildTree(preOrder, inOrder); } }