08.判断一棵树是否为完全二叉树

118 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第29天,点击查看活动详情

  • 📝 个人主页:程序员阿红🔥
  • 🎉 支持我:点赞👍收藏⭐️留言📝
  • 🍓欢迎大家关注哦,互相学习🍓
  • 🍋欢迎大家访问哦,互相学习🍋
  • 🍑欢迎大家收藏哦,互相学习🍑

一、判断一棵树是否为完全二叉树

  • 判断条件:

    • 如果树为空,返回false
    • 如果树不为空,开始层序遍历二叉树(用队列)
    • 如果node.left != null && node.right != null 将其node.left和node.right入队。
    • 如果node.left == null && node.right != null 返回false
    • 如果node.left != null && node.right == null或者node.left == null && node.left == null
      • 那么后面遍历的节点应该都为叶子节点,才是完全二叉树
      • 否则返回false
     public boolean completeBinaryTree(){
            if ( root == null ) return false;
            Queue<Node<E>> queue = new LinkedList<>();
            queue.offer(root);
            boolean flag = false;
            while(!queue.isEmpty()){
                Node<E> node =  queue.poll();
                if (flag && !node.isLeaf()){
                    return  false;
                }
                if (node.left != null){
                    queue.offer(node.left);
                }else if(node.right != null){
                    return false;//这说明node.left == null && node.right != null
                }
                if (node.right != null){
                   queue.offer(node.right);
                }else{
                    //2种情况
                    // node.left != null && node.right == null
                    // node.left == null && node.right == null
                    //总结:后面遍历的节点必须是叶子节点
                    flag = true;
                }
    
            }
    
    
     		/**
             * 判断是否为叶子节点
             * @return
             */
            public boolean isLeaf(){
                return left == null && right == null;
            }
    
       
    

    验证: 在这里插入图片描述

二、二叉搜索树的前驱节点和后继节点

二叉搜索树的前驱节点

  • 先了解一下前驱节点
    • 前驱节点:中序遍历时的前一个节点
    • 但如果是二叉搜索树,前驱节点就是前一个比它小的节点

image-20220119144149156

  • 找前驱节点两种情况:

    1. 当前节点的左子树不为空。则一直遍历左子树的右节点,直至为null。

    2. 当前节点的左子树为空,则从父节点开始寻找前驱节点:

      1. 如果当前节点为父节点的右子树,则父节点即为前驱节点。例:7的前驱节点为6。
      2. 如果当前节点为父节点的左子树,则依次遍历父节点,直至遍历的节点为父节点的右子树为止。因为属于父节点的左子树都是比该节点大的,循环遍历到节点为父节点的右子树时,该节点的父子树才比该节点小。例如:9的前驱节点为8。
      3. 如果父节点为空,返回当前节点的父节点,即==null。

    上代码:

    public Node<E> predecessor(Node<E> node){
            if ( node == null ) return null;
            Node<E> p =node.left;
            if ( p != null ){
                //1.当前节点的左子树不为空
                while(p.right != null){
                    p = p.right;
                }
                return p;
            }
            //2.当前节点的左子树为空
            // 从父节点、祖父节点中寻找前驱节点
            while(node.parent != null && node == node.parent.left){
                node = node.parent;
            }
            //3.循环到这有两种情况
            //3.1 node.parent == null;-->即前驱节点为null(也可以是node.parent)
            //3.2 node = node.parent.right;-->即前驱节点为node.parent
            return node.parent;
        }
    

    二叉搜索树的后继节点

  • 后继节点:中序遍历时的后一个节点

  • 如果是二叉搜索树,后继节点就是一个比它大的节点

    image-20220119154219467

  • 找后继节点有两种情况:

  1. 当前节点的右子树不为空。则一直遍历右子树的左节点,直至为null。
  2. 当前节点的右子树为空,则从父节点开始寻找后继节点:
    1. 如果当前节点为父节点的左子树,则后继节点即为父节点。例:9的后继节点为10。
    2. 如果当前节点为父节点的右子树,则依次遍历父节点,直至遍历节点的父节点为左子树为止,因为如果遍历的父节点一直为右节点,肯定是比该节点小的,只有找到节点的父节点为左子树时,找到节点的父节点才比它大,即为后继节点。
    3. 如果父节点为空,返回当前节点的父节点,即==null。
  • 上代码:
public Node<E> successor(Node<E> node){
        if (node == null ) return null;
        Node<E> p = node.right;
        if (p != null ){
            // 1.前驱节点在左子树当中(right.left.left.left....)
            while( p.left != null){
                p = p.left;
            }
            return  p;
        }
        //2.从父节点,祖父节点寻找前驱节点
        while(node.parent != null && node == node.parent.right){
            node = node.parent;
        }

        return node.parent;
    }

💖💖💖 完结撒花

💖💖💖 路漫漫其修远兮,吾将上下而求索

💖💖💖 写作不易,如果您觉得写的不错,欢迎给博主点赞、收藏、评论来一波~让博主更有动力吧