数据结构与算法分析(第三篇-树,二叉树,AVL树)代码太多了,下一篇(伸展树,B+树,红黑树)

我知道看我博客的大家都已经了解了树的知识,为了简介,一些细枝末节的基础直接跳过,有问题直接私聊我

首先我们先需要记住树的基本概念:

一个数是一些节点的集合。这个节点可以是空集,若不是空集,则树由称作根(root)的节点以及0个或多个非空(子)树组成,其下级极为儿子,按辈分排下去了,连接的线即是边(edge),没有子级别的孩子,即为树叶(leaf)

从根到目标节点的边的数量,机位深度,从目标节点到当前最远树叶的边的数量为高度。

    《数据结构与算法分析(第三篇-树,二叉树,AVL树)代码太多了,下一篇(伸展树,B+树,红黑树)》

树的节点有点类似于链表的节点,用java代码实现一个最简单的二叉树节点,方便理解:

这里我给二叉树的实现跳过了,需要的私聊我,直接上AVL平衡树,因为旋转的问题让我一直很头疼,所以分享给大家

class BinaryNode{
   Object element;//当前节点数据
   
BinaryNode left;//其左儿子
BinaryNode right;//其右侧儿子}

 

关于二叉查找树大家结合链表的节点一起看,二叉树是只记录当前节点的左子和右子,那么当他查询的时候的时间理想状态为O(logN),但实际情况并不会特别理想,这里贴个图是理想状态下二叉树和不理想状态:

《数据结构与算法分析(第三篇-树,二叉树,AVL树)代码太多了,下一篇(伸展树,B+树,红黑树)》

因为插入的一直是比当前节点小的数据,二叉树变成了单枝树,这时候就出现了平衡的需求

 

平衡二叉树,Avl树

所谓平衡就是需要保证树的深度需是O(logN) ,既最优深度。

一颗AVL树是其每个节点的左子树和又子树的高度最多差1的二叉树找树(空树的高度定为-1)。

大家需要记住最多差一即可,是想尽量满足2^k-1的理想平衡树(perfectly balanced tree).

既然要平衡,那么就涉及到一个概念—旋转(rotation)。

旋转分两种:单旋转和双旋转

单旋转情况:对节点的左儿子的左子树进行一次插入      —>  向右转

                  对节点的右儿子的右子树进行一次插入      —>  向左转

双旋转情况:对节点的右儿子的左子树进行一次插入      —>  先右转   —>  再左转

                  对节点的左儿子的右子树进行一次插入      —>  先左转   —>  再右转

注:下面图片为转发图片,侵权删

《数据结构与算法分析(第三篇-树,二叉树,AVL树)代码太多了,下一篇(伸展树,B+树,红黑树)》

下面给大家贴一个AVL旋转树的基本实现代码,默认树中存储的都是数字:

 

代码下载地址:

https://github.com/shenyang312/shenyang/blob/dev/shen/src/main/java/com/shen/my_j_u/MyAVLTree.java

package com.shen.my_j_u;

import org.omg.CORBA.Any;

import java.nio.BufferUnderflowException;

public class MyAVLTree<AnyType extends Comparable<? super AnyType>> {
    /**
     * 平衡节点内部类
     * 注:与普通二叉树的区别在于,他需要记录每个节点的高度
     * @param <AnyType>
     */
    private static class AvlNode<AnyType>{
        AvlNode( AnyType theElement){
            this(theElement,null,null);
        }
        AvlNode( AnyType theElement,AvlNode<AnyType> lt, AvlNode<AnyType> rt){
            element = theElement;
            left = lt;
            right = rt;
            height = 0;
        }

        AnyType element;
        AvlNode<AnyType> left;
        AvlNode<AnyType> right;
        int height;
    }

    private AvlNode<AnyType> root;
    private static final int ALLOWED_IMBALANCE = 1;

    /**
     * 获取节点高度私有方法
     * @param t
     * @return
     */
    private int height(AvlNode<AnyType> t){
        return t ==null ?-1:t.height;
    }

    //既然大家都是了解二叉树的查找等结构的,那么我着重讲解一下平衡二叉树的---- 插入与删除的旋转

    private AvlNode<AnyType> insert(AnyType x,AvlNode<AnyType> t){
        if(t == null)
            return new AvlNode<>(x,null,null);
        int compareResult = x.compareTo(t.element);
        if(compareResult<0)
            t.left = insert(x,t.left);
        else if(compareResult > 0)
            t.right = insert(x,t.right);
        else
            ;
        return balance(t);
    }

    private  AvlNode<AnyType> balance(AvlNode<AnyType> t){
        if(t==null)
            return t;
        //如果左侧比右侧高一
        if(height(t.left) - height(t.right)>ALLOWED_IMBALANCE)
            //如果时左左情况,单侧旋转
            if(height(t.left.left)>=height(t.left.right))
                //单侧-右旋转
                t = rotateWithLeftChild(t);
            else
                t = doubleWithLeftChild(t);
        else
            //如果右侧比左侧高一
            if(height(t.right)-height(t.left)>ALLOWED_IMBALANCE)
                //如果是右右情况,单侧旋转
                if(height(t.right.right)>=height(t.right.left))
                    //单侧-左旋转
                    t = rotateWithRightChild(t);
                else
                    t = doubleWithRightChild(t);
        t.height = Math.max(height(t.left),height(t.right))+1;
        return t;
    }

    /**
     * 单侧-右旋转
     * @param k2
     * @return
     */
    private AvlNode<AnyType> rotateWithLeftChild(AvlNode<AnyType> k2){
        //先取出左侧的参数,这是想办法,把k1转到右侧
        AvlNode<AnyType> k1 = k2.left;
        //把当前节点的左侧子节点的右节点,赋值给当前节点的左节点,实现旋转节点的左侧右侧节点,右向左做旋转
        k2.left = k1.right;
        //然后把把旋转节点右移动,把之前的根节点k2变成其右侧节点,实现k2左侧移动
        k1.right = k2;
        //重新赋值k2高度
        k2.height = Math.max(height(k2.left),height(k2.right))+1;
        //重新赋值k1高度
        k1.height = Math.max(height(k1.left),k2.height) + 1;
        //旋转后,返回新的节点
        return k1;
    }

    private AvlNode<AnyType> rotateWithRightChild(AvlNode<AnyType> k2){
        AvlNode<AnyType> k1 = k2.right;
        k2.right = k1.left;
        k1.left = k2;
        k2.height = Math.max(height(k2.right),height(k2.left))+1;
        k1.height = Math.max(height(k1.right),k2.height) + 1;
        return k1;
    }

    private AvlNode<AnyType> doubleWithLeftChild(AvlNode<AnyType> k3){
        k3.left = rotateWithRightChild(k3.left);
        return rotateWithLeftChild(k3);
    }

    private AvlNode<AnyType> doubleWithRightChild(AvlNode<AnyType> k3){
        k3.right = rotateWithRightChild(k3.right);
        return rotateWithRightChild(k3);
    }

    /**
     * 传入参数是删除数据和 节点t
     * 默认节点t为root跟节点
     * @param x
     * @param t
     * @return
     */
    private AvlNode<AnyType> remove(AnyType x,AvlNode<AnyType> t){
        if(t==null)
            return t;
        //compareTo方法,相当返回0,小于返回-1,大于返回1
        //先查找当前删除参数是否属于当前节点
        int compareResult = x.compareTo(t.element);
        //未查询到即继续递归查询
        //即未折半查找法
        if(compareResult<0)
            t.left = remove(x,t.left);
        if(compareResult<0)
            t.left = remove(x,t.left);
        else if(compareResult>0)
            t.right = remove(x,t.right);
        else if(t.left != null && t.right != null){
            t.element = findMin(t.right).element;
            t.right = remove(t.element,t.right);
        }
        else
            t = (t.left != null) ? t.left :t.right;
        return balance(t);
    }

    public AvlNode<AnyType> findMin(){
        if(isEmty())
            throw new BufferUnderflowException();
        return findMin(root);
    }

    private AvlNode<AnyType> findMin(AvlNode<AnyType> t){
        if(t ==null)
            return null;
        else if(t.left == null)
            return t;
        return findMin(t.left);
    }

    public boolean isEmty(){
        return root == null;
    }
}

 

    原文作者:AVL树
    原文地址: https://blog.csdn.net/weixin_37352094/article/details/80675554
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞