本文代碼為java代碼
一、二叉樹
二叉樹(Binary Tree)是n(n>=0)個結點的有限集合,該集合或者為空集(稱為空二叉樹),或者由一個根節點和兩棵互不相交的,分別稱為根節點的左子樹和右子樹的二叉樹組成。 --《大話數據結構》
簡單的說,二叉樹是一種樹,並且最多有2個子樹。如圖1-1:
代碼表示:
public class TreeNode {
public int val;
public TreeNode left;
public TreeNode right;
public TreeNode(int x) { val = x; }
}
二、二叉樹的遍歷
1、前序遍歷
前序遍歷的順序是,根節點->左子樹->右子樹,遍歷子樹時也按照相同的順序,可以用遞歸的思想理解。遍歷順序如圖2-1:
代碼表示:
public static void prevPrintTreeNode(TreeNode root){
if(root == null){
return;
}
System.out.print(root.val+" ");
//運用了遞歸
prevPrintTreeNode(root.left);
prevPrintTreeNode(root.right);
}
所以結果是:{1,2,3,4,5,6}
。可知前序遍歷結果的第一個節點為根節點。
2、中序遍歷
中序遍歷的順序是,左子樹->根節點->右子樹。遍歷順序如圖2-2:
代碼表示,只有順序的區別:
public static void inPrintTreeNode(TreeNode root){
if(root == null){
return;
}
//運用了遞歸
inPrintTreeNode(root.left);
System.out.print(root.val+" ");
inPrintTreeNode(root.right);
}
所以結果是:{3,2,1,5,4,6}
。可知,中序遍歷根節點左側都為左子樹節點,右側都為右子樹節點。
3、后序遍歷
后序遍歷的順序是,左子樹->右子樹->根節點,遍歷順序如圖2-3:
代碼表示,依然只有順序的區別:
public static void postPrintTreeNode(TreeNode root){
if(root == null){
return;
}
//運用了遞歸
postPrintTreeNode(root.left);
postPrintTreeNode(root.right);
System.out.print(root.val+" ");
}
所以結果是:{3,2,5,6,4,1}
。可知,后序遍歷最后一個節點是根節點。
4、根據遍歷結果推導二叉樹
已知前序遍歷或后序遍歷可以得到根節點,中序遍歷在已知根節點的情況下可以得知左子樹和右子樹的遍歷結果,所以已知前序遍歷結果和中序遍歷結果、已知后序遍歷結果和中序比那里結果都可以推導出二叉樹結構。但已知前序節點和后序節點不能推導出,因為無法判斷左子樹和右子樹節點個數。比如一個二叉樹前序遍歷結果為{1,2,3}
,后序遍歷結果為{3,2,1}
,就有如圖2-4的四種可能:
三、根據前序遍歷和中序遍歷結果還原二叉樹
原理第二節講過了,再畫個圖便於理解。見圖3-1:
合並得到圖1-1的二叉樹。
代碼實現:
public class Solution {
public static TreeNode reConstructBinaryTree(int [] prev,int [] in) {
//不管什么遍歷方式,結果長度肯定是一樣的,都是總結點數
if(prev.length!= in.length || prev.length<1){
return null;
}
//只有一個節點,那就是根節點
if(prev.length == 1){
return new TreeNode(prev[0]);
}
//在中序遍歷結果中找根節點
int index = -1;
for(int i=0;i<in.length;i++){
if(in[i]==prev[0]){
index=i;
break;
}
}
//沒找到,說明數據有問題
if(index==-1){
return null;
}
//找到根節點了
TreeNode root = new TreeNode(prev[0]);
//得到左子樹的前序遍歷結果
int[] lChildPrev = new int[index];
System.arraycopy(prev,1,lChildPrev,0,index);
//得到左子樹的中序遍歷結果
int[] lChildin = new int[index];
System.arraycopy(in,0,lChildin,0,index);
//通過遞歸,得到左子樹結構
root.left=reConstructBinaryTree(lChildPrev,lChildin);
//得到右子樹的前序遍歷結果
int[] rChildPrev = new int[in.length-1-index];
System.arraycopy(prev,index+1,rChildPrev,0,in.length-1-index);
//得到右子樹的中序遍歷結果
int[] rChildin = new int[in.length-1-index];
System.arraycopy(in,index+1,rChildin,0,in.length-1-index);
//通過遞歸,得到右子樹結構
root.right=reConstructBinaryTree(rChildPrev,rChildin);
//得到完整的二叉樹結構
return root;
}
//測試
public static void main(String[] args){
int[] prev = {1,2,4,7,3,5,6,8};
int[] in = {4,7,2,1,5,3,8,6};
TreeNode root = reConstructBinaryTree(prev,in);
prevPrintTreeNode(root);
System.out.println();
inPrintTreeNode(root);
}
//測試結果
//1 2 4 7 3 5 6 8
//4 7 2 1 5 3 8 6
}
本文完。