-AVL树

一、AVL树的概念

AVL树是最先发明的自平衡二叉查找树。在AVL树中任何节点的两个子树的高度最大差别为1,所以它也被称为高度平衡树。增加和删除可能需要通过一次或多次树旋转来重新平衡这个树。

二、AVL树相关算法

1.AVL树的结点定义

class AVLNode{
        AVLNode leftchild;//左孩子
        AVLNode rightchild;//右孩子
        AVLNode parent;//双亲结点
        int balance;//右孩子-左孩子
        int key;
        public AVLNode(){
            key=0;
            leftchild=rightchild=parent=null;
        }
        public AVLNode(int x){
            key=x;
            leftchild=rightchild=parent=null;
        }
        public AVLNode(int x, AVLNode left, AVLNode pa, AVLNode right){
            key=x;
            leftchild=left;
            parent=pa;
            rightchild=right;

        }
    }

2.AVL树左旋

如果在子树E中插入一个新结点,该子树高度增1导致结点A的平衡因子变成+2,出现不平衡。
为使树恢复平衡,从A沿插入路径连续取3个结点A、C和E。它们处于一条方向为“1”的直线上,需要做左单旋转。
以结点C为旋转轴,让结点A反时针旋转。
在这里插入图片描述
解题思路:
在这里插入图片描述

    private void RotateLeft(AVLNode ptr){
      AVLNode newroot=ptr.rightchild;//对应第一步
      newroot.parent=ptr.parent;//1维护双亲
      ptr.rightchild=newroot.leftchild;//对应第二步
      //2维护双亲
      if(newroot.leftchild!=null) {
          newroot.leftchild.parent = ptr;
      }
      newroot.leftchild=ptr;//对应第三步
      //新根
      AVLNode pa=ptr.parent;
      if(pa==null){
          root=newroot;
      }else {
          if(pa.leftchild==ptr){
              pa.leftchild=newroot;
          }else {
              pa.rightchild=newroot;
          }
      }
      ptr.parent=newroot;//3维护双亲
    }

主要完成三步代码后,对应为其添加维护双亲结点,以及根节点。

3.AVL树的右旋

在左子树D上插入新结点使其高度增1,导致结点A的平衡因子增到-2,造成了不平衡。
为使树恢复平衡,从A沿插入路径连续取3个结点A、B和D,它们处于一条方向为“/”的直线上,需要做右单旋转。
以结点B为旋转轴,将结点A顺时针旋转。
在这里插入图片描述
解题思路:
在这里插入图片描述

private void RotateRight(AVLNode ptr){
     AVLNode newroot=ptr.leftchild;
     newroot.parent=ptr.parent;
     ptr.leftchild=newroot.rightchild;
     if(newroot.rightchild!=null){
         newroot.rightchild.parent=ptr;
     }
     newroot.parent=ptr;
     AVLNode pa=ptr.parent;
     if(pa==null){
         root=newroot;
     }else {
         if(pa.leftchild==ptr){
             pa.leftchild=newroot;
         }else {
             pa.rightchild=newroot;
         }
         ptr.parent=newroot;
     }
    }

4.AVL树的双旋

1)左单旋–》右单旋

在这里插入图片描述
在子树F或G中插入新结点,该子树的高度增1。结点A的平衡因子变为-2,发生了不平衡。
从结点A起沿插入路径选取3个结点A、B和E,它们位于一条形如“<”的折线上,因此需要进行先左后右的双旋转。

旋转思路:
在这里插入图片描述

private void LeftBalance(AVLNode ptr){
        AVLNode leftsub=ptr.leftchild,rightsub=null;
        switch (leftsub.balance){
            case 0://平衡因子为0时说明是平衡的
                System.out.println("left is balance \n"); break;
            //平衡因子为-1时,说明处于的时一条斜线,因此进行右旋
            case -1:
                ptr.balance=0;
                leftsub.balance=0;
                RotateRight(ptr);
                break;
                //当平衡因子为1时,则说明是一条折线
            case 1:
               //指向这个不平衡的因子
                rightsub=leftsub.rightchild;
                //根据不同情况重置它们的平衡因子
                switch (rightsub.balance){
                    case 1:
                        ptr.balance=0;
                        leftsub.balance=-1;
                        break;
                    case 0:
                        ptr.balance=0;
                        leftsub.balance=0;
                        break;
                    case -1:
                        ptr.balance=1;
                        leftsub.balance=0;
                        break;
                }
                rightsub.balance=0;
                //进行左旋、右旋
                RotateLeft(leftsub);
                RotateRight(ptr);
                break;
        }
    }

2)右单旋–》左单旋

在这里插入图片描述
此次双旋则是上一个双旋的镜像操作

private void RightBalance(AVLNode ptr){
        AVLNode rightsub=ptr.rightchild,leftsub=null;
        switch (rightsub.balance){
            case 0:
                System.out.println("right is balance \n"); break;
            case 1:
                ptr.balance=0;
                rightsub.balance=0;
                RotateLeft(ptr);
                break;
            case -1:
                leftsub=rightsub.leftchild;
                switch (leftsub.balance){
                    case 1:
                        ptr.balance=-1;
                        rightsub.balance=0;
                        break;
                    case 0:
                        ptr.balance=0;
                        leftsub.balance=0;
                        break;
                    case -1:
                        ptr.balance=0;
                        rightsub.balance=1;
                        break;
                }
                leftsub.balance=0;
                RotateRight(rightsub);
                RotateLeft(ptr);
                break;
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值