一,問題描述
任意給定一棵二叉樹,判斷它是否是平衡二叉樹。所謂平衡二叉樹,是指二叉樹中任意一個結點的左右子樹的高度之差不超過1
二,思路分析
可以分兩步實現。第一步先實現求解 二叉樹中每個結點的高度的函數height(BinaryNode );然后先序遍歷二叉樹中的每一個結點node,調用height()求出該結點的左子樹高度height(node.left) 和 右子樹高度 height(node.right)。根據左右子樹的高度判斷是否為平衡二叉樹。
求解二叉樹高度代碼如下:
1 private int height(BinaryNode root){ 2 if(root == null) 3 return 0; 4 int left_height = height(root.left); 5 int right_height = height(root.right); 6 return 1 + (left_height > right_height ? left_height : right_height); 7 }
判斷二叉樹是否平衡代碼如下:
1 private boolean isBalance(BinaryNode root){ 2 if(root == null) 3 return true; 4 int left_height = height(root.left); 5 int right_height = height(root.right); 6 if(Math.abs(left_height - right_height) > 1) 7 return false; 8 else 9 return isBalance(root.left) && isBalance(root.right); 10 }
可以看出,這是一個典型的“先序遍歷”算法。第4、5、6行相當於先“訪問”結點,第9行相當於 再“訪問”該結點的左子樹,然后再“訪問”結點的右子樹。
但是,上面的“先序遍歷”判斷二叉樹平衡的方法,時間復雜度比較大。因為,二叉樹中的很多結點遍歷了多次。
比如,求解根的的高度時,需要先求解根的左子樹高度和右子樹高度,這就遍歷了整棵左子樹中的結點和右子樹中的結點。而求解以根的左孩子為根的子樹的高度時,又需要遍歷它(根的左孩子)的左子樹和右子樹。這樣,相當於很多結點的高度重復計算了。
根本原因是采用了“先序遍歷”,求根的高度,需要先知道根的左右孩子的高度。
如果采用后序遍歷,先知道某結點左右子樹的高度,如果左右子樹的高度都不滿足平衡二叉樹(二者高度相減大於1),那么都不需要再去求解該結點的高度了。
因為,平衡二叉樹要求二叉樹中任意結點的左右子樹高度相差不超過1
至於具體代碼實現,先不貼了。
三,完整代碼實現

import java.util.LinkedList; import java.util.Queue; import java.util.Random; public class MyBinaryTree2 { private static final Random rand = new Random();//insert left or right private static class BinaryNode{ int ele; BinaryNode left; BinaryNode right; public BinaryNode(int ele) { this.ele = ele; this.left = this.right = null; } } private BinaryNode root; public void buildTree(){ int[] ndoes = {3,0,7,4,8}; for (int i : ndoes) { insert(i); } } public BinaryNode insert(int ele){ return root = insert(root, ele); } private BinaryNode insert(BinaryNode root, int ele){ if(root == null) return root = new BinaryNode(ele); if(rand.nextInt() %2 == 0) root.left = insert(root.left, ele); else root.right = insert(root.right, ele); return root; } //求解二叉樹的高度 public int height(){ return height(root); } private int height(BinaryNode root){ if(root == null) return 0; int left_height = height(root.left); int right_height = height(root.right); return 1 + (left_height > right_height ? left_height : right_height); } //判斷二叉樹是否為平衡二叉樹 public boolean isBalance(){ return isBalance(root); } private boolean isBalance(BinaryNode root){ if(root == null) return true; int left_height = height(root.left); int right_height = height(root.right); if(Math.abs(left_height - right_height) > 1) return false; else return isBalance(root.left) && isBalance(root.right); } //print binary tree in level public void printTree(){ if(root == null) return; printTree(root); } //按層打印二叉樹,每行打印一層 private void printTree(BinaryNode root){ assert root != null; Queue<BinaryNode> queue = new LinkedList<MyBinaryTree2.BinaryNode>(); BinaryNode currentNode = root; int current, next; current = 1; next = 0; queue.offer(root); while(!queue.isEmpty()) { currentNode = queue.poll(); System.out.printf("%-4d" ,currentNode.ele); current--; if(currentNode.left != null) { queue.offer(currentNode.left); next++; } if(currentNode.right != null) { queue.offer(currentNode.right); next++; } if(current == 0) { System.out.println(); current = next; next = 0; } } } //test public static void main(String[] args) { MyBinaryTree2 mbt2 = new MyBinaryTree2(); mbt2.buildTree(); mbt2.printTree(); System.out.println("height:" + mbt2.height()); System.out.println("balace? " + mbt2.isBalance()); } }
四,二叉樹操作匯總