查找算法总结(4)--平衡二叉树

原创 2017年05月30日 17:34:26

一、简介

二叉查找树在构建时,当数组是有序时,树的高度达到n,查找效率也为O(n)。平衡二叉树(AVL树)是二叉查找树的改进,不仅有二叉查找树的性质,而且每个节点的左右子树的高度相差不超过1。
平衡二叉树具有以下的性质:
1、是二叉查找树
2、每个节点的左右子树的高度差不超过1

平衡二叉树的查找和二叉查找树一样,找最大值、最小值、指定值、前驱和后继等。

平衡二叉树的插入不仅需要比较插入值和根节点的大小,在插入之后,由于会破坏平衡二叉树的性质,需要旋转来维护。
根据插入节点与最小不平衡子树的根节点(设为A)的位置关系,分为4种情况:
(最小不平衡子树是离插入节点最近,且以平衡因子绝对值大于1的节点为根的子树)
1、LL型:在A的左孩子(L)的左子树(L)上插入节点,使得A的左子树较高而失去平衡。LL型的调整规则为带着左子树向右旋转,选择A的左孩子(设为B)作为新的根节点,B的左子树不变(带着左子树),A作为B的右子树,而B原来的右子树作为A的左子树。
2、RR型:在A的右孩子(R)的右子树(R)上插入节点,使得A的右子树较高而失去平衡。RR的调整规则为带着右子树向左旋转,选择A的右孩子(设为B)作为新的根节点,B的右子树不变(带着右子树),A作为B的左子树。而B原来的左子树作为A的右子树。
3、LR型:在A的左孩子(L)的右子树(R)上插入节点,使得A的左子树较高而失去平衡。LR向的调整规则为先RR调整,再LL调整。首先对A的左子树进行RR型调整,然后再对以A为根节点的树进行LL型调整。
4、RL型:在A的右孩子(R)的左子树(L)上插入节点,使得A的右子树较高而失去平衡。RL型的调整规则为先LL型调整,在RR型调整。首先对A的右子树进行LL型调整,再对以A为根节点的树进行RR型调整。

二、代码实现

/*
 * 平衡二叉树的实现
 * 1、创建二叉平衡树
 * 2、二叉平衡树的操作,查找,最大值,最小值,插入
 * 3、判断一个树是不是二叉平衡树,是否空
 * 4、按顺序打印平衡二叉树
 * */

public class AvlTree<T extends Comparable<? super T>>{
    private AvlNode<T> root;

    //构造函数
    public AvlTree(){
        this.root=null;
    }
    public AvlTree(T[] array){
        for(T x:array){
            insert(x);
        }
    }

    //在Avl树中查找数据,和查找二叉树一样
    public boolean search(T value){
        return search(root,value);
    }

    public boolean search(AvlNode<T> node,T value){
        while(node!=null){
            int c=value.compareTo(node.element);
            if(c<0) node=node.left;
            else if (c>0) node=node.right;
            else return true;
        }
        return false;
    }

    //在Avl树中找到最大值,和查找二叉树一样
    public T findMax(){
        if(root==null) System.out.println("数空");
        return findMax(root).element;
    }

    public AvlNode<T> findMax(AvlNode<T> node){
        if(node==null) return node;
        while(node.left!=null){
            node=node.left;
        }
        return node;
    }

    //在Avl树中找到最小值,和查找二叉树一样
    public T findMin(){
        if(root==null) System.out.println("数空");
        return findMin(root).element;
    }

    public AvlNode<T> findMin(AvlNode<T> node){
        if(node==null) return node;
        while(node.right!=null){
            node=node.right;
        }
        return node;
    }


    //在Avl树中插入数据,重复数据替换
    public void insert(T value){
        root=insert(root,value);
    }

    public AvlNode<T> insert(AvlNode<T> node,T value){
        //如果树空,生成一个节点
        if(node==null) return new AvlNode<T>(value,null,null);

        int c=value.compareTo(node.element);

        if(c<0){
            //如果插入的值小于节点的值,插入左子树中
            node.left=insert(node.left,value);
            if(hight(node.left)-hight(node.right)==2){//失去平衡
                if(value.compareTo(node.left.element)<0){//LL型
                     node= rotateWithLeftChild(node);   
                }else node=doubleWithLeftChild(node);  //LR型
            }
        }
        else if(c>0){
            //如果插入的值大于节点的值,插入右子树中
            node.right=insert(node.right,value);
            if(hight(node.left)-hight(node.right)==-2){
                if(value.compareTo(node.right.element)>0){//RR
                    node=rotateWithRightChild(node);
                }else node=doubleWithRightChild(node); //RL
            }
        } 
        //如果相等,替换
        else if(c==0) node.element=value;


        //更新节点高度
        node.height=Math.max(hight(node.left), hight(node.right))+1;
        return node;
    }

    //LL,带左子树旋转,向右旋转
     private AvlNode< T> rotateWithLeftChild( AvlNode< T> node ) {
         AvlNode<T> reNode=node.left;
         node.left=reNode.right;
         reNode.right=node;
         node.height=Math.max(hight(node.left),hight(node.right))+1;
         reNode.height=Math.max(hight(reNode.left), hight(reNode.right))+1;
         return reNode;
     }

     //带右子树旋转,适用于RR型  ,向左旋转
     private AvlNode< T> rotateWithRightChild( AvlNode< T> node ) {
         AvlNode<T> reNode=node.right;
         node.right=reNode.left;
         reNode.left=node;
         node.height=Math.max(hight(node.left), hight(node.right))+1;
         reNode.height=Math.max(hight(reNode.left), hight(reNode.right))+1;
         return reNode;
     }

    //双旋转,适用于LR型  
     private AvlNode< T> doubleWithLeftChild( AvlNode< T> node ) {
         node.left = rotateWithRightChild( node.left );  
         return rotateWithLeftChild( node );  
     } 

    //双旋转,适用于RL型  
     private AvlNode< T> doubleWithRightChild( AvlNode< T> node ) {
         node.right = rotateWithLeftChild( node.right );  
         return rotateWithRightChild(node);  
     }

    public int hight(AvlNode<T> node){
        return node==null ? -1:node.height;
    }
    //判断一个树是不是平衡二叉树
    public boolean isTree(){
        if(root==null) System.out.println("数空");
        return isTree(root);
    }

    public boolean isTree(AvlNode<T> node){
        if(node==null) return true;
        return(Math.abs(node.height)<=1 &&
                node.left==null || node.left!=null && node.left.element.compareTo(node.element)<0  
                && node.right==null || node.right!=null && node.right.element.compareTo(node.element)>0); 
    }

    //判断一个二叉树是不是空
    public boolean isEmpty(){
        return root==null;
    }

    //打印
    public void printTree(){
        if(root==null) System.out.println("数空");
        else printTree(root);
    }

    public void printTree(AvlNode<T> node){
        if(node!=null){
            printTree(node.left);
            System.out.println(node.element);
            printTree(node.right);
        }
    }
}

数据结构中常见的树(BST二叉搜索树、AVL平衡二叉树、RBT红黑树、B-树、B+树、B*树)

BST树        即二叉搜索树:        1.所有非叶子结点至多拥有两个儿子(Left和Right);        2.所有结点存储一个关键字;        3...
  • Sup_Heaven
  • Sup_Heaven
  • 2014年09月16日 12:07
  • 33047

数据结构课程设计平衡二叉排序树的三种基本功能:查找、插入、删除。

  • 2010年06月12日 12:46
  • 326KB
  • 下载

数据结构实验之查找二:平衡二叉树【OJ--3374】

题目描述 根据给定的输入序列建立一棵平衡二叉树,求出建立的平衡二叉树的树根。 输入 输入一组测试数据。数据的第1行给出一个正整数N(n 数,按数据给定顺序建立平衡二叉树。 输出 输...
  • zhang_di233
  • zhang_di233
  • 2015年12月17日 20:54
  • 1374

二叉查找树、平衡二叉树、红黑树、B-/B+树性能对比

原文链接:http://blog.csdn.net/z702143700/article/details/49079107 前言:BST、AVL、RBT、B-tree都是动态结构,查找时间基本都在O...
  • xamhaha
  • xamhaha
  • 2017年09月11日 22:18
  • 102

数据结构实验之查找二:平衡二叉树

创建平衡二叉树,我们采用依次插入节点的方式进行。而平衡二叉树上插入节点采用递归的方式进行。递归算法如下:(1)      若该树为一空树,那么插入一个数据元素为e的新节点作为平衡二叉树的根节点,树的高...
  • guoqingshuang
  • guoqingshuang
  • 2015年12月05日 22:50
  • 1928

数据结构实验之查找二:平衡二叉树

平衡二叉树 对于二叉查找树,尽管查找、插入及删除操作的平均运行时间为O(logn),但是它们的最差运行时间都是O(n),原因在于对树的形状没有限制。 平衡二叉树又称为AVL树,它或者是一棵...
  • FightingEveryDay365
  • FightingEveryDay365
  • 2017年08月23日 14:34
  • 162

查找、检索 算法-总结3 平衡二叉查找树 [AVL]

 源地址: http://hxraid.javaeye.com/blog/609949 在上一个专题中,我们在谈论二叉查找树的效率的时候。不同结构的二叉查找树,查找效率有很大的不同(单支树结构的查找效...
  • caisini_vc
  • caisini_vc
  • 2010年06月17日 09:49
  • 1125

平衡二叉查找树算法代码

  • 2014年12月17日 21:59
  • 4KB
  • 下载

平衡二叉树各种算法详解一:红黑树

平衡二叉树(Balanced Binary Tree)具有以下性质:它是一 棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。平衡二叉树的常用算法有红黑树、AVL、...
  • qq_29407877
  • qq_29407877
  • 2015年11月01日 09:46
  • 2264

二叉树 平衡二叉树 平均查找长度

  • 2014年06月13日 09:48
  • 229KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:查找算法总结(4)--平衡二叉树
举报原因:
原因补充:

(最多只允许输入30个字)