恋上数据结构与算法第一季笔记—— 平衡搜索二叉树

Posted Johnny*

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了恋上数据结构与算法第一季笔记—— 平衡搜索二叉树相关的知识,希望对你有一定的参考价值。

平衡

在这里插入图片描述

理想平衡

在这里插入图片描述

改进

在这里插入图片描述

平衡二叉搜索树

在这里插入图片描述

AVL 树

在这里插入图片描述

平衡对比

在这里插入图片描述

AVLTree

继承结构

在这里插入图片描述

添加导致的失衡

在这里插入图片描述

右旋转

在这里插入图片描述

左旋转

在这里插入图片描述

LR —— RR左旋,LL右旋

在这里插入图片描述

AVLTree

package trees;

public class AVLTree<E> extends  BST<E> {


}

  //默认只有无参的构造方法
        AVLTree<Integer> avl = new AVLTree<>();

添加了以下构造方法才能使用

    public AVLTree(){
        this(null);
    }
    public AVLTree(Comparator comparator){
        //调用父类的构造方法
        super(comparator);
    }
        //
        AVLTree<Integer> avl2 = new AVLTree<>(new Comparator() {
            @Override
            public int compare(Object o1, Object o2) {
                return 0;
            }
        });

由于Node中没有无参构造方法,所以AVLNode必须

    class AVLNode extends Node{

    }

删除

删除导致的失衡

在这里插入图片描述

LL

在这里插入图片描述

RR 右旋

在这里插入图片描述

LR

注意高度变化对祖先的节点的影响
在这里插入图片描述

RL

在这里插入图片描述

实现

BinaryTree

package trees;

import printer.BinaryTreeInfo;

import java.util.LinkedList;
import java.util.Queue;

@SuppressWarnings("unchecked")
public class BinaryTree<E>  implements BinaryTreeInfo{
    //元素数量
    protected int size;
    //二叉树根节点
    protected Node<E> root;

    /**
     * 清空所有元素
     */
    public void clear (){
        root = null;
        size = 0;

    }
    public void preOrder(Visitor visitor){
        if(visitor == null ) return;
        if( root != null) preOrderTraverse(root, visitor);
    }
    /**
     * 前序遍历(根左右)
     * @param root
     */
    private void preOrderTraverse(Node<E> root, Visitor<E> visitor){

        if( root == null || visitor.stop) return ;
        visitor.stop = visitor.visit(root.element);
        preOrderTraverse(root.left, visitor);
        preOrderTraverse(root.right, visitor);

    }


    public void inOrder(Visitor<E> visitor){
        if(visitor == null ) return;
        if( root != null) inOrderTraverse(root, visitor);
    }
    /**
     * 中序遍历(左根右)
     * @param root
     */
    private void inOrderTraverse(Node<E> root, Visitor<E> visitor){

        if( root == null || visitor.stop) return ;
        inOrderTraverse(root.left, visitor);
        if( visitor.stop ) return;
        visitor.stop = visitor.visit(root.element);
        inOrderTraverse(root.right, visitor);

    }

    public void postOrder(Visitor<E> visitor){
        if(visitor == null ) return;
        if( root != null) postOrderTraverse(root, visitor);
    }

    /**
     * 后序遍历(左右根)
     * @param root
     */
    private void postOrderTraverse(Node<E> root, Visitor<E> visitor){

        if( root == null || visitor.stop) return ;
        postOrderTraverse(root.left, visitor);
        postOrderTraverse(root.right, visitor);
        if (visitor.stop) return;
        visitor.stop = visitor.visit( root.element); //将节点通过visit接口传递给外面处理

    }

    public void levelOrderTraverse(Visitor<E> visitor){

        if( visitor == null ||root == null ) return;

        Queue<Node<E> > q = new LinkedList<>();
        q.offer( root );  //根节点入队

        while( ! q.isEmpty() ){

            //取出队首 并访问
            Node<E> node = q.poll();
            //将node的element元素通过Visitor接口的visit方法传递到外面出去
            //同时visit方法有返回值返回
            if ( visitor.visit(node.element) ) return;

            //将node左右孩子入队
            if( node.left != null ) q.offer(node.left);
            if( node.right != null ) q.offer(node.right);

        }

    }

    public static abstract class Visitor<E>{

        boolean stop;
        /**
         * 如果返回true 则代表停止遍历
         * @param element
         * @return
         */
        protected abstract boolean visit(E element);
    }

    public int height(){
        if( root == null) return 0;
//        return heightReverse(root);
        return  heightLevelOrder();
    }
    protected Node<E> createNode(Node<E> parent,E element) {
        return new Node<E>( parent,element);
    }
    /**
     * 判断一颗树是否是完全二叉树
     * @return
     */
    public boolean isCompelete(){
        if( root == null ) return false; // 空树不是完全二叉树
        //层次遍历
        Queue<Node<E>> q = new LinkedList<>();
        q.offer( root );
        boolean leaf = false;
        while( !q.isEmpty() ){
            Node<E> node = q.poll();

            if( leaf && ! node.isLeaf() ) return false;
            if( node.hashTwoChildren() ){//度为2的节点
                q.offer(node.left);
                q.offer(node.right);

            }else if(node.left == null && node.right != null ){//到这:则节点度可能为0 也可能为1
                return false;
            }else{//此后所有的节点都必须是叶子节点
                leaf = true;
            }
        }
        return true;
    }


    /**
     * 递归方式计算树的高度
     * @param node
     * @return
     */
    private int heightReverse(Node node){
        if( node == null ) return 0;
        return 1 + Math.max( heightReverse(node.left),  heightReverse(node.right) );
    }

    /**
     *  层次遍历计算树的高度
     * @return
     */
    private int heightLevelOrder(){
        Queue<Node<E>> q = new LinkedList<>();
        q.offer(root);
        int levelSize = 1; //当前层的节点个数
        int height = 0;
        while( ! q.isEmpty() ){
            Node<E> node = q.poll();
            levelSize --; //每从队列中取出节点 当前层节点数就减一

            if( node.left != null ) q.offer(node.left);
            if( node.right != null ) q.offer(node.right);
            if( levelSize == 0){//当前层访问完 下一层的节点数为队列元素个数
                levelSize = q.size();
                height ++;
            }

        }
        return height;
    }

    /**
     * 返回一个节点的前驱
     * @param node
     * @return
     */
    protected Node<E> predecessor(Node node){

        if( node == null ) return null;
        Node<E> p = node.left;
        //node.left != null
        // 寻找node.left.right.right…… 一直到
        if( p != null){
            while( p.right != null ) p = p.right;
            return p;
        }
        //node.left == null && node.parent!=null
        //一直找到 node = node.parent.right
        while( node.parent != null && node != node.parent.right ){
            node = node.parent;
        }
        //node.parent == null   ||  node == node.parent.right
        return node.parent;

    }

    /**
     * 返回一个节点的后继节点
     * @param node
     * @return
     */
    protected Node<E> successor(Node node){
        if( node == null ) return null;
        Node<E> p = node.right;

        //node.left != null
        // 寻找node.right.left.left…… 一直到
        if( p != null){
            while( p.left != null ) p = p.left;
            return p;
        }
        //node.left == null && node.parent!=null
        //一直找到 node = node.parent.left
        while( node.parent != null && node != node.parent.left ){
            node = node.parent;
        }
        //node.parent == null   ||  node == node.parent.left
        return node.parent;

    }



    @Override
    public Object root() {
        return this.root;
    }

    @Override
    public Object left(Object node) {
        return ((Node<E>) node).left;
    }

    @Override
    public Object right(Object node) {
        return ((Node<E>) node).right;
    }

    @Override
    public Object string(Object node) {
        return null;
    }

    //内部类且修饰符protected
    // protected:该包下及其子类都可以访问
    protected static class Node<E> {

        E element;
        Node<E> left;
        Node<E> right;
        Node<E> parent;

        public Node(Node<E> parent, E element) {
            this.parent = parent;
            this.element = element;
        }
        public Node(){}

        public boolean hashTwoChildren() {
            return this.left != null && this.right != null;
        }

        public boolean isLeaf() {
            return this.left == null && this.right == null;
        }

        public boolean isLeftChild(){ return parent != null && parent.left == this; }
        public boolean isRightChild(){ return parent != null && parent.right == this; }

    }
}

BST

package trees;

import java.util.Comparator;

public class BST<E> extends BinaryTree<E> {


    //比较器:由外部定义比较规则,并将比较器传进来使用
    private Comparator<E> comparator;

    //带比较器的构造方法
    public BST(Comparator<E> comparator){
        this.comparator = comparator;
    }

    //不带比较器则默认使用comparable的比较方法
    public BST(){
        this(null);
    }

    @Override
    public Object string(Object node) {
        Node<E> newNode = ((Node<E>) node);
        E parentElement = newNode.parent == null ? null: newNode.parent.element;
        return newNode.element+"_("+parentElement+")";
    }



    @Override
    public String toString() {
        if( root == null ) return null;
        StringBuilder sb = new StringBuilder();
        toString(root, sb,"");
        return sb.toString();
    }

    /**
     * 前序遍历展示树形结构
     * @param node
     * @param sb       整个树遍历的记录
     * @param prefix 记录当前节点的前缀
     */
    private void toString(Node<E> node, StringBuilder sb,String prefix){

        if( node == null ) return;
        sb.append(prefix).append(node.element).append("\\n");
        toString(node.left, sb, prefix+"【L】");
        toString(node.right, sb, prefix +"【R】");


    }

    /**
     * 元素数量
     * @return
     */
    public int size(){
        return size;
    }

    /**
     * 二叉搜索树是否为空
     * @return
     */
    public boolean isEmpty(){
        return size == 0;
    }



    public void add( E element){
        //二叉树树不允许节点为空 插入前先判断
        elementNotNullChck(element);

        //添加第一个节点
        if( root == null){
            root = createNode(null, element);
            size ++;
            //添加节点后调整为AVL二叉树
            afterAdd(root);
            return ;
        }
        int cmp = 0;
        Node<E> node = root;
        Node<E> parent 恋上数据结构与算法第一季笔记——红黑树

算法笔记-6:平衡二叉树(理论篇)

数据结构笔记

算法笔记-7:平衡二叉树(代码篇)

数据结构学习笔记04树(二叉树二叉搜索树平衡二叉树)

数据结构笔记