【算法导论学习-30】 二叉树专题5:二叉树类型的判断

一、完全二叉树的判断

参考:http://blog.csdn.net/lilypp/article/details/6158699/

【分析】根节点开始进行层次遍历,节点入队列,如果队列不为空,循环。遇到第一个没有左儿子或者右儿子的节点,设置标志位,如果之后再遇到有左/右儿子的节点,那么这不是一颗完全二叉树。

/*使用LinkedList实现队列,入队使用queue.offer(),出队使用queue.poll()*/
       Queue<BinaryTreeNode<T>> queue=new LinkedList<>();
        boolean flag=true;
       queue.offer(root);
        while (!queue.isEmpty()) {
           BinaryTreeNode<T> tempNode=queue.poll();
            if (tempNode.getLeftChild()!=null&&flag){
               queue.offer(tempNode.getLeftChild());
           }else if (tempNode.getLeftChild()!=null) {
                return false;
           }else {
                flag=false;
           }

            if (tempNode.getRightChild()!=null&&flag){
               queue.offer(tempNode.getRightChild());
           }else if (tempNode.getRightChild()!=null) {
                return false;
           }else {
                flag=false;
           }

           }
        /*如果遍历完成仍然没有返回false,表明是完全二叉树*/
        return true;
       }

二、平衡二叉树的判断

【分析-1】从root开始往下递归判断节点的左右子树的深度差(动态规划问题,但不容易加入备忘机制,所以比较低效) 。子树的深度被重复计算,所以比较低效。

/*递归判断左右子树的深度,如果深度差的绝对值大于1表明非平衡树*/

public  int isBalancedTree(BinaryTreeNode<T> node) {

if (node==null) {

return 1;

}

int leftDepth=getTreeDeep(node.getLeftChild());

int rightDepth=getTreeDeep(node.getRightChild());

int diff=leftDepth-rightDepth;

if (diff<-1||diff>1) {

return 0;

}else {

if (isBalancedTree(node.getLeftChild())==1&&isBalancedTree(node.getRightChild())==1){

return 1;

}else {

return 0;

}

}

}

/* 获得树的高度,递归过程 */

private int getTreeDeep(BinaryTreeNode<T> root) {

if (root == null) {

return 0;

}

if (root.getLeftChild() == null && root.getRightChild() == null) {

return 1;

}

return 1 + Math.max(getTreeDeep(root.getLeftChild()),

getTreeDeep(root.getRightChild()));

}

【分析-2】利用动态规划的方法从底向上计算每个子数的深度。从顶向下递归传递一个Integer对象,探底之后就从底向上开始计算,本质上是后续遍历。这里要注意,Depth depth需要传址调用,所以不能用int或Interger,而要新定义一个类。

/*isBalancedTree(node.getLeftChild(),leftDepth)&&isBalancedTree(node.getRightChild(),rightDepth)表明先左边探底,然后上移一个节点计算右子数,是后续遍历过程*/
        public boolean isBalancedTree(BinaryTreeNode<T> node,Depth depth){
      if (node==null) {
           depth=new Depth(0);
         return true;
         }
        Depth leftDepth=new Depth(0),rightDepth=new Depth(0);
        if (isBalancedTree(node.getLeftChild(),leftDepth)&&isBalancedTree(node.getRightChild(),rightDepth)){
            int diff=leftDepth.getDepth()-rightDepth.getDepth();
            if (diff<=1&&diff>=-1) {
               depth.setDepth(1 + Math.max(leftDepth.getDepth(),rightDepth.getDepth()));
               System.out.println(depth.getDepth());
                return true;
           }
       }
        return false;
   }
    public boolean isBalancedTree(){
        return isBalancedTree(root, new Depth(0));
   }
    class Depth{
        int depth;
        public Depth(int depth) {
            // TODO 自动生成的构造函数存根
            this.depth=depth;
       }

        public int getDepth() {
            return depth;
       }

        public void setDepth(int depth) {
            this.depth = depth;
       }

   }

三、二叉搜索树(BST)的判断

参考:http://www.2cto.com/kf/201310/250996.html

【分析】BST的中序遍历是递增数列,所以可以利用中序遍历来进行判断。这里也是递归调用,需要传址调用,所以不能用int或Interger来定义pre。

先设计一个类:

class Pre{
    int pre;

    public int getPre() {
        return pre;
    }

    public void setPre(int pre) {
        this.pre = pre;
    }

}

函数体:

public staticbooleanisBST(BinarySearchTreesNode<String> root) {
        Prepre=new Pre();
        pre.setPre(Integer.MIN_VALUE);
        return isBSTOrder(root, pre);

    }
    public static booleanisBSTOrder(BinarySearchTreesNode<String> root,Pre pre) {
        if (root==null) {
            return true;
        }
        if (isBSTOrder(root.getLeftChild(), pre)) {
            if (root.getKey()>pre.getPre()) {
                pre.setPre(root.getKey());
                return isBSTOrder(root.getRightChild(), pre);
            }else {
                return false;
            }
        }

            return false;

    }
时间: 2024-11-07 09:34:32

【算法导论学习-30】 二叉树专题5:二叉树类型的判断的相关文章

算法导论学习---红黑树具体解释之插入(C语言实现)

前面我们学习二叉搜索树的时候发如今一些情况下其高度不是非常均匀,甚至有时候会退化成一条长链,所以我们引用一些"平衡"的二叉搜索树.红黑树就是一种"平衡"的二叉搜索树,它通过在每一个结点附加颜色位和路径上的一些约束条件能够保证在最坏的情况下基本动态集合操作的时间复杂度为O(nlgn).以下会总结红黑树的性质,然后分析红黑树的插入操作,并给出一份完整代码. 先给出红黑树的结点定义: #define RED 1 #define BLACK 0 ///红黑树结点定义,与普通

算法导论学习---红黑树详解之插入(C语言实现)

前面我们学习二叉搜索树的时候发现在一些情况下其高度不是很均匀,甚至有时候会退化成一条长链,所以我们引用一些"平衡"的二叉搜索树.红黑树就是一种"平衡"的二叉搜索树,它通过在每个结点附加颜色位和路径上的一些约束条件可以保证在最坏的情况下基本动态集合操作的时间复杂度为O(nlgn).下面会总结红黑树的性质,然后分析红黑树的插入操作,并给出一份完整代码. 先给出红黑树的结点定义: #define RED 1 #define BLACK 0 ///红黑树结点定义,与普通的二

【算法导论学习-015】数组中选择第i小元素(Selection in expected linear time)

1.算法思想 问题描述:从数组array中找出第i小的元素(要求array中没有重复元素的情况),这是个经典的"线性时间选择(Selection in expected linear time)"问题. 思路:算法导论215页9.2 Selection in expect linear time 2.java实现 思路:算法导论216页伪代码 /*期望为线性时间的选择算法,输入要求,array中没有重复的元素*/ public static int randomizedSelect(i

算法导论 学习资源

学习的过程会遇到些问题,发现了一些比较好的资源,每章都会看下别人写的总结,自己太懒了,先记录下别人写的吧,呵呵. 1  Tanky Woo的,每次差不多都看他的 <算法导论>学习总结 - 1.前言 <算法导论>学习总结 - 2.第一章 && 第二章 && 第三章 <算法导论>学习总结 - 3.第四章 && 第五章 <算法导论>学习总结 - 4.第六章(1) 堆排序 <算法导论>学习总结 - 5.第六

【算法导论学习-014】计数排序(CountingSortTest)

参考:<算法导论>P194页 8.2节 Counting sort 1.Counting sort的条件 待排序数全部分布在0~k之间,且k是已知数:或者分布在min~max之间,等价于分布在0~max-min之间,max和min是已知数. 2.java 实现 /** * 创建时间:2014年8月17日 下午3:22:14 项目名称:Test * * @author Cao Yanfeng * @since JDK 1.6.0_21 类说明: 计数排序法,复杂度O(n), 条件:所有数分布在0

【算法导论学习-015】基数排序(Radix sort)

1.<算法导论>P197页 8.3节Radix sort 2.java实现 这里仅仅对[算法导论学习-014]计数排序 的参数进行了修改,同时仅仅修改了一行代码. /** * 创建时间:2014年8月17日 下午4:05:48 * 项目名称:Test * @author Cao Yanfeng * @since JDK 1.6.0_21 * 类说明: 利用计数排序实现基数排序 * 条件:待排序的所有数位数相同,注意,即便不相同,也可以认为是最多那个位数,如下面的例子可以认为都是3位数 */ p

【算法导论学习-016】两个已排过序的等长数组的中位数(median of two sorted arrays)

问题来源 <算法导论>P223 9.3-8: Let X[1..n] and Y[1..n] be two arrays, each containing nnumbers already in sorted order. Give an O(lgn)-time algorithm to find themedian of all 2n elements in arrays X and Y. 翻译过来即:求两个等长(n个元素)的已排序数组A和B的中位数 方案1:对两个数组进行归并直到统计到第n

【算法导论学习-012】n个数随机等概率的抽样m个

算法法导论>P129页课后题5.3-7 suppose we want to create a random sample of the set {1,2,3,-,n}, thatis, an m-element subset S, where0≤m≤n, such that each m-subset is equally likely to be created. One waywould be to set A[i]=i for i=1,2,3,-,n, call RANDOMIZE-IN

【算法导论学习笔记】第3章:函数的增长

????原创博客,转载请注明:http://www.cnblogs.com/wuwenyan/ ? 当算法的输入n非常大的时候,对于算法复杂度的分析就显得尤为重要,虽然有时我们能通过一定的方法得到较为精确的运行时间,但是很多时候,或者说绝大多数时候,我们并不值得去花精力求得多余的精度,因为精确运行时间中的倍增常量和低阶项已经被输入规模本身的影响所支配.我们需要关心的是输入规模无限增加,在极限中,运行时间是如何随着输入规模增大而增加的,通常来说,在极限情况下渐进地更优的算法在除很小的输入外的所有情