13、自平衡二叉查找树AVL

  1 package ren.laughing.datastructure.baseImpl;
  2
  3 /**
  4  * 自平衡二叉查找树AVL 继承二叉查找树
  5  *
  6  * @author Laughing_Lz
  7  * @time 2016年4月20日
  8  */
  9 public class AVLTree extends BSTree {
 10     /**
 11      * 统一平衡方法 旋转操作
 12      *
 13      * @param z
 14      *            z是失衡的结点
 15      * @return 返回平衡后子树的根结点
 16      */
 17     private BinTreeNode rotate(BinTreeNode z) {
 18         BinTreeNode y = heightSubT(z);// 取y为z更高的孩子
 19         BinTreeNode x = heightSubT(y);// 取x为y更高的孩子
 20         boolean isLeft =z.isLChild();//标记z是否是左孩子
 21         BinTreeNode p = z.getParent();//取z的父结点
 22         BinTreeNode a,b,c;
 23         BinTreeNode t0,t1,t2,t3;
 24         //以下分四种情况重命名
 25         if(y.isLChild()){//1如果y是左孩子
 26             c = z;
 27             t3 = z.getRChild();
 28             if(x.isLChild()){//1.1如果x是左孩子(左左失衡)
 29                 a = x;
 30                 b = y;
 31                 t0 = x.getLChild();
 32                 t1 = x.getRChild();
 33                 t2 = y.getRChild();
 34             }else{//1.2如果x是右孩子(左右失衡)
 35                 b = x;
 36                 a = y;
 37                 t1 = x.getLChild();
 38                 t2 = x.getRChild();
 39                 t0 = y.getLChild();
 40             }
 41         }else{//2如果y是右孩子
 42             a = z;
 43             t0 = z.getLChild();
 44             if(x.isRChild()){//2.1如果x是右孩子(右右失衡)
 45                 c = x;
 46                 b = y;
 47                 t2 = x.getLChild();
 48                 t3 = x.getRChild();
 49                 t1 = y.getLChild();
 50             }else{//2.2如果x是左孩子(右左失衡)
 51                 b = x;
 52                 c = y;
 53                 t1 = x.getLChild();
 54                 t2 =x.getRChild();
 55                 t3 = y.getRChild();
 56             }
 57         }
 58 //        x.server();//疑问,已经赋值给a b c 还有何用?★
 59 //        y.server();
 60 //        z.server();
 61         a.server();//断开与父结点的连接
 62         b.server();
 63         c.server();
 64         if(t0 != null){
 65             t0.server();
 66         }
 67         if(t1 != null){
 68             t1.server();
 69         }
 70         if(t2 != null){
 71             t2.server();
 72         }
 73         if(t3 != null){
 74             t3.server();
 75         }
 76         b.setLChild(a);//重新设置左右孩子,平衡
 77         b.setRChild(c);
 78         a.setLChild(t0);
 79         a.setRChild(t1);
 80         c.setLChild(t2);
 81         c.setRChild(t3);
 82         if(isLeft){
 83             p.setLChild(b);
 84         }else{
 85             p.setRChild(b);
 86         }
 87         return b;//返回平衡后子树的根
 88     }
 89
 90     /**
 91      * 获取结点v较高的子树
 92      *
 93      * @param v
 94      * @return
 95      */
 96     private BinTreeNode heightSubT(BinTreeNode v) {
 97         if (v == null) {
 98             return null;
 99         }
100         int lH = -1;// 若没有左子树,默认左子树高度为-1
101         if (v.hasLChild()) {
102             lH = v.getLChild().getHeight();
103         }
104         int rH = -1;// 若没有右子树,默认右子树高度为-1
105         if (v.hasRChild()) {
106             rH = v.getRChild().getHeight();
107         }
108         if (lH > rH) {
109             return v.getLChild();
110         } else if (lH < rH) {
111             return v.getRChild();
112         } else {// 若两边子树等高
113             if (v.isLChild()) {
114                 return v.getLChild();
115             } else {
116                 return v.getRChild();
117             }
118         }
119     }
120     /**
121      * 重写BSTree的insert方法
122      * insert之后要重新平衡
123      */
124     @Override
125     public void insert(Object obj) {
126         super.insert(obj);
127         root = reBalance(startBN);//重新平衡树
128     }
129     /**
130      * 重新平衡AVL树
131      * @param startBN
132      * @return 返回平衡后的AVL树根结点
133      */
134     private BinTreeNode reBalance(BinTreeNode startBN) {
135         if(startBN == null){
136             return root;
137         }
138         BinTreeNode c = startBN;
139         while(startBN != null){//从startBN开始,向上逐一检查 z 的祖先★
140             if(!isBalance(startBN)){//若startBN失衡,则旋转使之重新平衡★
141                 startBN = rotate(startBN);
142             }
143             c = startBN;
144             startBN = startBN.getParent();//继续检查其父亲
145         }
146         return c;
147     }
148     /**
149      * 判断该结点是否平衡
150      * @param startBN
151      * @return
152      */
153     private boolean isBalance(BinTreeNode startBN) {
154         if(startBN == null){
155             return true;
156         }
157         int lH = startBN.hasLChild()?startBN.getLChild().getHeight():-1;
158         int rH = startBN.hasRChild()?startBN.getRChild().getHeight():-1;
159         return (Math.abs(lH-rH) <= 1);
160     }
161     /**
162      * 重写BSTree的remove方法
163      */
164     @Override
165     public Object remove(Object ele) {
166         Object obj = super.remove(ele);
167         root = reBalance(startBN);//重新平衡AVL树
168         return obj;
169     }
170 }
时间: 2024-10-31 15:12:52

13、自平衡二叉查找树AVL的相关文章

二叉查找树(BST),平衡二叉查找树(AVL),红黑树(RBT),B~/B+树(B-tree)的比较

http://www.iteye.com/topic/614070 此少侠总结的特棒,直接收藏了. 我们这个专题介绍的动态查找树主要有: 二叉查找树(BST),平衡二叉查找树(AVL),红黑树(RBT),B~/B+树(B-tree).这四种树都具备下面几个优势: (1) 都是动态结构.在删除,插入操作的时候,都不需要彻底重建原始的索引树.最多就是执行一定量的旋转,变色操作来有限的改变树的形态.而这些操作所付出的代价都远远小于重建一棵树.这一优势在<查找结构专题(1):静态查找结构概论 >中讲到

【查找结构3】平衡二叉查找树 [AVL]

在上一个专题中,我们在谈论二叉查找树的效率的时候.不同结构的二叉查找树,查找效率有很大的不同(单支树结构的查找效率退化成了顺序查找).如何解决这个问题呢?关键在于如何最大限度的减小树的深度.正是基于这个想法,平衡二叉树出现了. 平衡二叉树的定义 (AVL—— 发明者为Adel'son-Vel'skii 和 Landis) 平衡二叉查找树,又称 AVL树. 它除了具备二叉查找树的基本特征之外,还具有一个非常重要的特点:它 的左子树和右子树都是平衡二叉树,且左子树和右子树的深度之差的绝对值(平衡因子

[重温数据结构]一种自平衡二叉查找树avl树的实现方法

最近重温<数据结构>,发现其中的东西我上学的时候几乎都没写过... 惭愧啊.于是打算一一写点.算是对我逝去青春的纪念... avl树的代码网上有很多, 这个在平衡二叉树里面算是比较简单的. 需要注意的就是树的平衡因子和其子树的平衡因子符号相反的旋转情况.这个在函数avl_rotate_right等中有处理. 目前只做了插入,删除等哪天想做了再做吧. avl.h 1 #define INSERT_ERROR -1 2 #define INSERT_OK 1 3 4 #define LEFT_LE

平衡二叉查找树——AVL树

二叉查找树在最坏情况下高度可能为N-1,即插入元素时后插入的元素总比以前插入的元素大或者小.为了解决这种不平衡的情况,引入了平衡条件来限制树中节点的深度不能过深,其中最老的一种平衡树称为AVL树.这种树限制树中每个节点的左右子树的高度相差不能超过一.(另一种更严格的树限制节点的左右子树高度必须相等,但这样的树要求树中的节点数目为2的k次幂减1,是一种理想平衡树,但是要求太严格,无法实际使用.) AVL树平衡条件分析 AVL树是一棵特殊的二叉查找树,对AVL树的操作中,除了插入操作与普通二叉查找树

平衡二叉查找树AVL

1.AVL简介 这篇文章我们要介绍的是能够在key插入时一直保持平衡的二叉查找树(AVL树,AVL是发明者的名字缩写) 利用AVL实现ADT MAP,基本上与BST的实现相同.不同之处在于二叉树的生成与维护过程. 2.AVL中的概念 AVL树的实现中,需要对每个节点跟踪"平衡因子balance factor"参数. 平衡因子是根据节点的左右子树的高度来定义的.确切的来说,是左右子树的高度差.balanceFactor = height(leftSubTree) - height(rig

平衡树初阶——AVL平衡二叉查找树+三大平衡树(Treap + Splay + SBT)模板【超详解】

平衡树初阶——AVL平衡二叉查找树 一.什么是二叉树 1. 什么是树. 计算机科学里面的树本质是一个树状图.树首先是一个有向无环图,由根节点指向子结点.但是不严格的说,我们也研究无向树.所谓无向树就是将有向树的所有边看成无向边形成的树状图.树是一种递归的数据结构,所以我们研究树也是按照递归的方式去研究的. 2.什么是二叉树. 我们给出二叉树的递归定义如下: (1)空树是一个二叉树. (2)单个节点是一个二叉树. (3)如果一棵树中,以它的左右子节点为根形成的子树都是二叉树,那么这棵树本身也是二叉

AVL树(平衡二叉查找树)

首先要说AVL树,我们就必须先说二叉查找树,先介绍二叉查找树的一些特性,然后我们再来说平衡树的一些特性,结合这些特性,然后来介绍AVL树. 一.二叉查找树 1.二叉树查找树的相关特征定义 二叉树查找树,又叫二叉搜索树,是一种有顺序有规律的树结构.它可以有以下几个特征来定义它: (1)首先它是一个二叉树,具备二叉树的所有特性,他可以有左右子节点(左右孩子),可以进行插入,删除,遍历等操作: (2)如果根节点有左子树,则左子树上的所有节点的值均小于根节点上的值,如果根节点有右子树,则有字数上的所有节

算法学习 - 平衡二叉查找树实现(AVL树)

平衡二叉查找树 平衡二叉查找树是很早出现的平衡树,因为所有子树的高度差不超过1,所以操作平均为O(logN). 平衡二叉查找树和BS树很像,插入和删除操作也基本一样,但是每个节点多了一个高度的信息,在每次插入之后都要更新树的每个节点的高度,发现不平衡之后就要进行旋转. 单旋转 单旋转是碰到左左或者右右的情况下所使用的方法. 例如: 3 2 1 这种情况就需要旋转,因为3是根节点,它的左子树高度为0,右子树高度为2,相差超过1了,所以要进行旋转,而这是右右的情况,所以是单旋转. 2 / 1 3 这

数据结构-自平衡二叉查找树(AVL)详解

介绍: 在计算机科学中,AVL树是最先发明的自平衡二叉查找树. 在AVL树中任何节点的两个子树的高度最大差别为一,所以它也被称为高度平衡树. 查找.插入和删除在平均和最坏情况下都是O(log n).增加和删除可能需要通过一次或多次树旋转来重新平衡这个树.AVL树得名于它的发明者 G.M. Adelson-Velsky 和 E.M. Landis,他们在 1962 年的论文 "An algorithm for the organization of information" 中发表了它.