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) {
// TODO Auto-generated method stub
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) {
// TODO Auto-generated method stub
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);
}
}
[java]二叉树构建、遍历、深度、平衡性
最新推荐文章于 2024-04-18 14:10:46 发布