zoukankan      html  css  js  c++  java
  • 判断二叉树是否是平衡二叉树 及二叉树各种操作汇总

    一,问题描述

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

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

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

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

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

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

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

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

    求解二叉树镜像

  • 相关阅读:
    转移阵地啦
    春之感--3月10日
    小鱼儿
    关于时间方法(date和simpledateformat)的实验
    hadoop练习处理地震数据
    出现log4j.properties问题
    远程hadoop集群方法
    小W学物理
    灵知的太阳信仰
    Blue
  • 原文地址:https://www.cnblogs.com/hapjin/p/5682704.html
Copyright © 2011-2022 走看看