算法与数据结构 其六 Avl平衡树
2017-08-15 09:28
260 查看
Avl平衡树
接下来要介绍的树都是从二叉树演变而来的,Avl平衡树当然不例外。何谓平衡?
原目标是树的所有左右子数的高度都相等,但是实际操作起来不现实,所以给的平衡条件是树的每个节点的左子树和右子树的高度最多差1
那么Avl平衡树就是树的每个节点的左子树和右子树的高度最多差1 的二叉查找树。由于一科满二叉树的高度是O(logN),平衡二叉树的高度仅仅稍微大于 O(logN),所以对于我们 CRUD速度是很快的。但是在操作中有一点需要注意:
为了保持树的平衡,每次增删时判断树时对树的平衡加以控制
所以Avl树比普通二叉查找树多了一部,就是保持平衡,我们称它为旋转
旋转分为两种类型:单旋转(左旋转,单右旋转);双旋转(先左旋后右旋,先右旋后左旋)。后者是建立在前者之上。下面讲讲旋转
单旋转(右旋转)
当树的左右子树高度相差2的时候,我们将 K1的左子树挂在K2的左子树,而K1称为这个子树的根节点,保持了平衡
实际例子
这样,非常简单明了。(左旋转和这里类似,所以不做介绍)
双旋转(先右后左)
由于会出现单旋转不能解决的类型,例如下面那么我们需要使用双旋转进行修复
实际例子
只要理解了这个概念就可以了,因为其他的是和查找二叉树
使用java代码实现AVL树
因为无论插入还是删除都可能对平衡造成影响,所以我们要记录下树的高度,用来判断是否需要旋转//这是树的节点,height是节点下树的高度 private static class AvlNode<E>{ public AvlNode(E theElement){ this(theElement,null,null); } public AvlNode(E theElement, AvlNode<E> lt, AvlNode<E> rt) { this.theElement = theElement; this.lt = lt; this.rt = rt; height=0; } E theElement; AvlNode<E> lt; AvlNode<E> rt; int height; @Override public String toString() { return theElement+""; } }
单旋转代码
private AvlNode<E> rotateWidthLeftChild(AvlNode<E> a1) { //这里进行旋转 AvlNode<E> a2 = a1.lt; a1.lt=a2.rt; a2.rt = a1; //计算旋转后两个子树的高度 a1.height = Math.max(height(a1.rt),height(a1.lt))+1; a2.height = Math.max(height(a2.lt),a1.height)+1; return a2; }
双旋转代码(先右后左)
private AvlNode<E> doubleRotateWidthLeftChild(AvlNode<E> avlNode) { //右旋转 avlNode.lt = rotateWidthRightChild(avlNode.lt); //左旋转 AvlNode<E> node = rotateWidthLeftChild(avlNode); return node; }
插入元素的代码
public boolean insert(E theElement){ root = insert(theElement,root); return true; } private AvlNode<E> insert(E theElement,AvlNode<E> avlNode){ if(avlNode==null||theElement==null) return new AvlNode<E>(theElement); int compareResult = theElement.compareTo(avlNode.theElement); if(compareResult<0){ avlNode.lt = insert(theElement,avlNode.lt); if(height(avlNode.lt)-height(avlNode.rt)==2){ if(theElement.compareTo(avlNode.lt.theElement)<0){ avlNode = rotateWidthLeftChild(avlNode); }else{ avlNode = doubleRotateWidthLeftChild(avlNode); } } }else if(compareResult>0){ avlNode.rt = insert(theElement,avlNode.rt); if(height(avlNode.rt)-height(avlNode.lt)==2){ if(theElement.compareTo(avlNode.rt.theElement)>0){ avlNode = rotateWidthRightChild(avlNode); }else{ avlNode = doubleRotateWidthRightChild(avlNode); } } }else; avlNode.height = Math.max(height(avlNode.lt),height(avlNode.rt))+1; return avlNode; }
删除元素代码
private AvlNode<E> remove(E theElement, AvlNode<E> avlNode) { if(avlNode==null||theElement==null) return null; int compateTo = theElement.compareTo(avlNode.theElement); if(compateTo<0){ avlNode.lt = remove(theElement,avlNode.lt); //删除之后进行旋转 if(height(avlNode.lt)-height(avlNode.rt)==2){ if(theElement.compareTo(avlNode.lt.theElement)<0){ avlNode = rotateWidthLeftChild(avlNode); }else{ avlNode = doubleRotateWidthLeftChild(avlNode); } } }else if(compateTo>0){ avlNode.rt = remove(theElement,avlNode.rt); //删除之后进行旋转 if(height(avlNode.rt)-height(avlNode.lt)==2){ if(theElement.compareTo(avlNode.rt.theElement)>0){ avlNode = rotateWidthRightChild(avlNode); }else{ avlNode = doubleRotateWidthRightChild(avlNode); } } }else if(compateTo==0){ if(avlNode.lt!=null && avlNode.rt!=null){ //如果左子树的高度 大于右子树 if(height(avlNode.lt)>height(avlNode.rt)){ //找左子树最大的点 AvlNode<E> avl =findMax(avlNode.lt); avlNode.theElement = avl.theElement; //该保持还是要保持 avlNode.lt = remove(avl.theElement,avlNode.lt); }else{ //如果左子树的高度 小于右子树 //找右子树最小的点 AvlNode<E> avl = findMin(avlNode.rt); avlNode.theElement = avl.theElement; // avlNode.rt = remove(avl.theElement,avlNode.rt); } }else{ AvlNode<E> avl = avlNode; if(avlNode.lt!=null){ //整个左子树向上移了 avlNode = avlNode.lt; }else if(avlNode.rt!=null){ //整个右子树向上移了 avlNode = avlNode.rt; } avl=null; } } return avlNode; }
注意这里,因为删除和插入也是需要一定的开销,所以建议如果在数据量大,插入和删除操作很少的情况下,可以使用惰性删除(删除元素而不删除节点)
相关文章推荐
- 数据结构和算法之数组奇数、偶数分离
- MySQL索引背后的数据结构及算法原理
- 数据结构和算法[精选]----说明一下这个分类之后的作用
- 算法与数据结构-动态规划 讲解与java代码实现
- 数据结构第七周项目(二)——建立连队算法库
- 微软等数据结构+算法面试100题全部答案集锦
- 数据结构-算法效率的度量-时间复杂度和空间复杂度
- 斐波那契查找(黄金分割法查找)- 数据结构和算法71
- 每天一个数据结构——三种简单排序算法及Java实现
- Java数据结构和算法的数组
- 头疼的算法与数据结构——红黑树
- 线性表15|魔术师发牌问题和拉丁方阵 - 数据结构和算法20
- 【源代码】C++实现严蔚敏数据结构所有算法(一)线性表-顺序表
- 数据结构—基于广度优先遍历算法的应用
- 【算法与数据结构】B-树学习笔记
- php算法和数据结构
- 大数据学习之BigData常用算法和数据结构
- [数据结构和算法]算法基本概念
- 算法与数据结构-Hash表的理解
- 张小五学算法与数据结构第二天:数据结构和线性表概述