package tree;
/**
* 2017-3-15
* 劍指offer-P55
* @author victorlee
*
*/
public class ConstructTree{
public Tree construct(int[] pre,int[] in){
if(pre.length ==0 || in.length == 0)
return null;
Tree head = buildTree(pre,0,pre.length-1,in,0,in.length-1);
return head;
}
/**
* 通過 前序遍歷和中序遍歷重建二叉樹
* @param preOrder
* @param begin1
* @param end1
* @param inOrder
* @param begin2
* @param end2
* @return
*/
public Tree buildTree(int[] preOrder, int begin1, int end1, int[] inOrder, int begin2, int end2) {
if(begin1>end1||begin2>end2){
return null;
}
int rootData = preOrder[begin1];
Tree head = new Tree(rootData);
int divider = findIndexInArray(inOrder,rootData,begin2,end2);
int offSet = divider -begin2 -1;
Tree left = buildTree(preOrder,begin1+1,begin1+1+offSet,inOrder,begin2,begin2+offSet);
Tree right = buildTree(preOrder,begin1+offSet+2,end1,inOrder,divider+1,end2);
head.left_child = left;
head.right_child = right;
return head;
}
private int findIndexInArray(int[] a, int x, int begin, int end) {
for(int i = begin;i<=end;i++){
if(a[i]==x)
return i;
}
return -1;
}
public void inOrder(Tree n){
if(n!=null){
inOrder(n.left_child);
System.out.print(n.val+" ");
inOrder(n.right_child);
}
}
public void preOrder(Tree n){
if(n!=null){
System.out.print(n.val+" ");
preOrder(n.left_child);
preOrder(n.right_child);
}
}
public void behindOrder(Tree n){
if(n!= null){
behindOrder(n.left_child);
behindOrder(n.right_child);
System.out.print(n.val+" ");
}
}
/**
* 遞迴求得樹的深度
* @param head
* @return
*/
public int treeDepth(Tree head){
if(head == null)
return 0;
int nLeft = treeDepth(head.left_child);
int nRight = treeDepth(head.right_child);
return (nLeft > nRight)?(nLeft +1):(nRight +1);
}
/**
* 2017-3-17
* 使用遞迴的方法判斷一棵樹是不是平衡二叉樹
* 缺點:一個結點會被多次遍歷。
* @param args
*/
public boolean isBanlanced(Tree root){
if(root == null){
return true;
}
int left = treeDepth(root.left_child);
int right = treeDepth(root.right_child);
int diff = left -right;
if(diff>1||diff<-1){
return false;
}
return isBanlanced(root.left_child)&&isBanlanced(root.right_child);
}
/**
* 2017-3-17
* 一個結點只需要遍歷一次就可以求得該二叉樹是不是平衡二叉樹
* @param root
* @param depth
* @return
*/
public boolean isBalanced(Tree root,int depth){
if(root == null){
depth = 0;
return true;
}
int left=0,right=0;
if(isBalanced(root.left_child,left)&&isBalanced(root.right_child,right)){
int diff = left-right;
if(diff<=1 &&diff>=-1){
depth = 1+(left>right?left:right);
return true;
}
}
return false;
}
public boolean isBalanced3(Tree root){
return getHeight(root)!=-1;
}
private int getHeight(Tree root){
if(root==null) return 0;
int nLeft=getHeight(root.left_child);
if(nLeft==-1) return -1;
int nRight=getHeight(root.right_child);
if(nRight==-1) return -1;
if(nLeft-nRight<-1||nLeft-nRight>1)
return -1;
return 1+(nLeft>nRight?nLeft:nRight);
}
public static void main(String[] args){
ConstructTree build =new ConstructTree();
int[] preOrder = {1,2,4,7,3,5,6,8};
int[] inOrder = {4,7,2,1,5,3,8,6};
Tree root = build.construct(preOrder, inOrder);
System.out.print("前序遍歷為:");
build.preOrder(root);
System.out.println();
System.out.print("中序遍歷為:");
build.inOrder(root);
System.out.println();
System.out.print("後序遍歷為:");
build.behindOrder(root);
System.out.print("樹的深度為:");
int treeDepth = build.treeDepth(root);
System.out.println(treeDepth);
}
}