判断二叉树是否是平衡二叉树 及二叉树各种操作汇总
一,问题描述
任意给定一棵二叉树,判断它是否是平衡二叉树。所谓平衡二叉树,是指二叉树中任意一个结点的左右子树的高度之差不超过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()); } }
四,二叉树操作汇总