判断二叉树是否是平衡二叉树

一,问题描述

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

View Code

 

 

四,二叉树操作汇总

按层打印二叉树–每行打印一层

二叉树的前序、中序、后序的非递归遍历实现

二叉树的层序遍历算法实现求二叉树中第K层结点的个数

比较两棵二叉–(比较两棵二叉是否相同/判断一棵二叉是否是另一棵二叉的子树)

给定一个序列,判断该序列是否为二叉查找的后序遍历序列

二叉的操作之统计二叉中节点的个数

二叉中的和为某一值的路径

求解二叉中两个结点的最低公共父结点

二叉的先序遍历和后序遍历的应用–输出文件和统计目录大小

二叉查找的递归实现及递归分析

求解二叉树镜像

    原文作者:hapjin
    原文地址: http://www.cnblogs.com/hapjin/p/5682704.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞