其他分享
首页 > 其他分享> > Github搬运(本人的)平衡二叉树概念与设计

Github搬运(本人的)平衡二叉树概念与设计

作者:互联网

AVL树学习笔记

 

 

AVL树是带有平衡条件的二叉查找树。

续上文,如果向一棵树输入预先排好序的数据,那么一连串insert操作将花费二次的时间,而链表实现的代价会非常巨大,因为此时的树只由那些没有左儿子的节点组成,一种解决办法,就是要有一颗称为平衡的附加结构条件,任何节点的深度均不得过深。

于是我开始学习一种最古老的平衡查找树,即AVL树。

另外一种较新的方法是放弃平衡条件,允许树有任意的深度,但是在每次操作之后要使用一个调整规则进行调整,使得后面的效率要高,这种类型的数据结构一般属于自调整类型,在二叉查找树的情况下,对于任意的单个操作我们将不再保证o(logN)的时间界,但是可以证明任意连续M次的操作在最坏的情形下花费时间O(M logN)

AVL树的定义

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

AVL高度探讨

粗略地说,一个AVL树的高度最多为1.44log(N+2)-1.328,但是实际的高度只略大于logN

由插入节点以后AVL树的平衡性可能会遭到破坏,所以我们因此通过对树的操作来维持其平衡性,这就是我们所说的单旋转和双旋转。

我们把必须重新平衡的节点叫做a,由于任意节点最多有两个儿子,因此出现高度不平衡就需要a点的两棵子树的高度差2.

这种不平衡可能出现在下面四种情况中

1 对a的左儿子的左子树进行一次插入

 

 

2 对a的左儿子的右子树进行一次插入

 

 

3 对a的右儿子的左子树进行一次插入

 

 

4 对a的右儿子的右子树进行一次插入

 

 

 

情况1和4是关于a点的镜像对称(轴对称),而2和3是关于a点的镜像对称,因此理论上只有两种情况,当然从编程的角度来看还是四种情形。

第一种情况是插入发生在外边的情况,即左左  右右 的情况,该情况通过对树的一次单旋转而完成调整,第二次情况是插入发生在内部的情形,即左右 右左的情况,该情况需要双旋转来处理。

AVL树实现代码如下

 

package com.qyx.Tree;
/**
 * 平衡二叉树实现与设计
 * @author QYX
 *
 */
public class AVLTree {
    private static final int ALLOWED_INBALANCE=1;
    private static class AvlNode<AnyType>
    {
        AvlNode left;//左子节点
        AvlNode right;//右子结点
        AnyType element;//元素数据
        int height;//高度
        public AvlNode(AnyType elemet) {
            this(elemet,null,null);
        }
        public AvlNode(AnyType elemet,AvlNode<AnyType> left,AvlNode<AnyType> right) {
            this.element=elemet;
            this.right=right;
            this.left=left;
            this.height=0;
        }
    }
    /*高度计算方法*/
    private int height(AvlNode<Integer> node)
    {
        return node==null?-1:node.height+1;
    }
    /*插入方法*/
    private AvlNode<Integer> insert(Integer x,AvlNode<Integer> node)
    {
        if(node==null)
        {
            return new AvlNode<Integer>(x);
        }
        int compareResult=x.compareTo(node.element);//与其节点的元素值进行比较
        if(compareResult<0)
        {
            node.left=insert(x, node.left);
        }else if(compareResult>0)
        {
            node.right=insert(x,node.right);
        }else{
            ;
        }
        return balance(node);
    }
    /*删除方法*/
    private AvlNode<Integer> remove(Integer x,AvlNode<Integer> node)
    {
        if(node==null)
        {
            return node;
        }
        int compareResult=x.compareTo(node.element);
        if(compareResult<0)
        {
            node.left=remove(x,node.left);
        }else if(compareResult>0)
        {
            node.right=remove(x,node.right);
        }else if(node.left!=null&&node.right!=null)
        {
            //如果要删除的节点左右儿子节点都不为空,则将当前节点的值转换为其右儿子最小节点的值(因为其不能有左儿子),然后递归删除即可
            node.element=findMin(node.right).element;
            node.right=remove(node.element,node.right);
        }else{
            node=(node.left!=null)?node.left:node.right;
        }
        return null;
    }
    /*寻找最小节点(递归)*/
    private AvlNode<Integer> findMin(AvlNode<Integer> node) {
        if(node==null)
        {
            return null;
        }else if(node.left==null)
        {
            return node;
        }
        return findMin(node.left);
    }
    /*寻找最大节点(非递归)*/
    private AvlNode<Integer> findMax(AvlNode<Integer> node)
    {
        if(node==null)
        {
            return null;
        }
        while(node.right!=null)
        {
            node=node.right;
        }
        return node;
    }
    /*查找该树是否包含某节点*/
    private boolean contains(Integer x,AvlNode<Integer> node)
    {
        if(node==null)
        {
            return false;
        }
        int compareResult=x.compareTo(node.element);
        if(compareResult<0)
        {
            return contains(x, node.left);
        }else if(compareResult>0)
        {
            return contains(x, node.right);
        }else{
            return true;
        }
    }
    /*平衡方法*/
    private AvlNode<Integer> balance(AvlNode<Integer> node) {
        if(node==null)
        {
            return node;
        }
        if(height(node.left)-height(node.right)>ALLOWED_INBALANCE)
        {
            if(height(node.left.left)>=height(node.left.right))
            {
                node=rotateWithLeftChild(node);
            }else{
                node=doubleWithLeftChild(node);
            }
        }else{
            if(height(node.right.right)>=height(node.right.right))
            {
                node=rotateWithRightChild(node);
            }else{
                node=doubleWithRightChild(node);
            }
        }
        node.height=Math.max(height(node.left), height(node.right))+1;
        return node;
    }
    private AvlNode<Integer> doubleWithRightChild(AvlNode<Integer> node) {
        
        node.right=rotateWithLeftChild(node.right);
        return rotateWithRightChild(node);
    }
    private AvlNode<Integer> rotateWithRightChild(AvlNode<Integer> node) {
        AvlNode<Integer> k1=node.right;
        node.right=k1.left;
        k1.left=node;
        node.height=Math.max(height(node.left), height(node.right))+1;
        k1.height=Math.max(height(k1.left), height(k1.right))+1;
        return k1;
    }
    private AvlNode<Integer> doubleWithLeftChild(AvlNode<Integer> node) {
        node.left=rotateWithRightChild(node.left);
        return rotateWithLeftChild(node);
    }
    private AvlNode<Integer> rotateWithLeftChild(AvlNode<Integer> node) {
        AvlNode<Integer> k1=node.left;
        node.left=k1.right;
        k1.right=node;
        node.height=Math.max(height(node.left), height(node.right))+1;
        k1.height=Math.max(height(k1.left), height(k1.right))+1;
        return k1;
    }
    
}

标签:node,Github,return,AvlNode,height,right,二叉树,搬运,left
来源: https://www.cnblogs.com/qyx66/p/12173046.html