判斷二叉樹是否是平衡二叉樹 及二叉樹各種操作匯總


一,問題描述

任意給定一棵二叉樹,判斷它是否是平衡二叉樹。所謂平衡二叉樹,是指二叉樹中任意一個結點的左右子樹的高度之差不超過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層結點的個數

比較兩棵二叉--(比較兩棵二叉是否相同/判斷一棵二叉是否是另一棵二叉的子樹)

給定一個序列,判斷該序列是否為二叉查找的后序遍歷序列

二叉的操作之統計二叉中節點的個數

二叉中的和為某一值的路徑

求解二叉中兩個結點的最低公共父結點

二叉的先序遍歷和后序遍歷的應用--輸出文件和統計目錄大小

二叉查找的遞歸實現及遞歸分析

求解二叉樹鏡像


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM