数据结构: AVL树
来源:互联网 发布:爱果园团购 淘宝 编辑:程序博客网 时间:2024/06/06 00:25
二叉查找树的主要缺点:
很多时候输入得序列都是有序或基本有序的,二叉查找树(BST)在最坏的情况下会退化成链表。树的高度会变成N, 而BST的性能又依赖于树的高度。插入、删除、查找等操作的时间复杂度都变成了O(N)。所以我们需要通过一定的方式来降低树的高度。
AVL树是一种自平衡的二叉查找树,AVL树要求它的每个节点的左右子树的高度差不超过1. 它保证了树的深度是O(logN), 所以它不会出现上述BST的缺点。 不管输入序列是什么样的,都能保持良好的性能。树的高度都为O(logN)。
AVL树的缺点是频繁的旋转、需要维护树的节点的平衡以及总体的复杂性,尤其是删除操作。这些缺点使得AVL树没有成为实现字典的标准结构。
AVL树解决了BST在最坏情况下效率低下的问题。换句话说,BST不能保证查询和插入操作花费log时间,而AVL树提供了这种保证。
具体的原理就不再重复了,书上和网上有非常详细的解释。
这里仅提供我自己实现AVL树的代码和注释。
package trees;/** * AVL树,重构~ * @author earayu * @param <K> * @param <V> */public class AVL <K extends Comparable<? super K>, V> { private class AVLNode{ K key; V val; int height; AVLNode leftChild; AVLNode rightChild; AVLNode(K key, V val, AVLNode leftChild, AVLNode rightChild){ this.key = key; this.val = val; this.height = 0;//height为该节点到叶子节点的最大距离 this.leftChild = leftChild; this.rightChild = rightChild; } } private AVLNode root; public AVL(){ root = null; } /** * 返回AVL树是否为空 * @return */ public boolean isEmpty(){ return root == null; } /** * 用键值对创建一个节点插入AVL树,将自动平衡 * @param key * @param val */ public void insert(K key, V val){ root = insert(root, key, val); } /** * 删除键为key的元素 * @param key */ public void remove(K key){ root = remove(root, key); } /** * 先序遍历AVL树 */ public void prePrint(){ prePrint(root); } /**************************************************************************************************/ /** * 返回该节点的高度,空节点返回-1. * @param t * @return */ private int height(AVLNode t){ return t == null ? -1 : t.height; } /** * 将key,val插入树t中,然后返回树t。除了最后要平衡一下,代码跟BST完全相同。 * @param t * @param key * @param val * @return */ private AVLNode insert(AVLNode t, K key, V val){ if(t == null) return new AVLNode(key, val, null, null); int cmp = key.compareTo(t.key); if(cmp < 0) t.leftChild = insert(t.leftChild,key,val); else if(cmp > 0) t.rightChild = insert(t.rightChild,key,val); else t.val = val; return balance(t); } /** * AVL树的四种旋转,这里只提供代码。 * @param t * @return */ private AVLNode balance( AVLNode t ) { if( t == null ) return t; if( height( t.leftChild ) - height( t.rightChild ) > 1 ) if( height( t.leftChild.leftChild ) >= height( t.leftChild.rightChild ) ) t = rotateLL( t ); else t = rotateLR( t ); else if( height( t.rightChild ) - height( t.leftChild ) > 1 ) if( height( t.rightChild.rightChild ) >= height( t.rightChild.leftChild ) ) t = rotateRR( t ); else t = rotateRL( t ); t.height = Math.max( height( t.leftChild ), height( t.rightChild ) ) + 1; return t; } /** * 删除t中键为key的元素,返回t。除了balance,跟BST的代码也几乎相同 * @param t * @param key * @return */ private AVLNode remove(AVLNode t, K key){ if(t == null) return t; int cmp = key.compareTo(t.key); if( cmp < 0 ) t.leftChild = remove(t.leftChild, key); else if( cmp > 0 ) t.rightChild = remove(t.rightChild, key ); else if(t.leftChild == null || t.rightChild == null) t = t.leftChild==null?t.rightChild:t.leftChild; else{ AVLNode minNode = findMin(t.rightChild); t.key = minNode.key; t.val = minNode.val; t.rightChild = remove(t.rightChild, minNode.key); } return balance(t); } /** * 返回AVL树t中的键最小的节点 * @param t * @return */ private AVLNode findMin(AVLNode t) { if (t == null) { return null; } while (t.leftChild != null) { t = t.leftChild; } return t; } private AVLNode rotateLL(AVLNode k1){ AVLNode k2 = k1.leftChild; k1.leftChild = k2.rightChild; k2.rightChild = k1; k1.height = Math.max(height(k1.leftChild), height(k1.rightChild) ) + 1; k2.height = Math.max(height(k2.leftChild), k1.height) + 1; return k2; } private AVLNode rotateRR(AVLNode k1){ AVLNode k2 = k1.rightChild; k1.rightChild = k2.leftChild; k2.leftChild = k1; k1.height = Math.max(height(k1.leftChild), height(k1.rightChild)) + 1; k2.height = Math.max(k1.height, height(k2.rightChild)) + 1; return k2; } private AVLNode rotateLR(AVLNode k1){ AVLNode k2 = k1.leftChild; k1.leftChild = rotateRR(k2); return rotateLL(k1); } private AVLNode rotateRL(AVLNode k1){ AVLNode k2 = k1.rightChild; k1.rightChild = rotateLL(k2); return rotateRR(k1); } private void prePrint(AVLNode t){ if(t != null){ System.out.println(t.val +": " + t.height ); prePrint(t.leftChild); prePrint(t.rightChild); } } public static void main(String[] args) { AVL<Integer,Integer> a = new AVL<>(); //for(int i=0;i<11;i++) // a.insert(i, i); a.insert(4, 4); a.insert(1, 1); a.insert(5, 5); a.insert(0, 0); a.insert(3, 3); a.insert(2, 2); a.remove(4); a.remove(5); a.prePrint(); }}
0 0
- AVL 树数据结构
- 数据结构之AVL树
- 数据结构之AVL树
- 数据结构之AVL树
- 数据结构之AVL树
- 数据结构之AVL树
- 数据结构之AVL树
- 数据结构之AVL树
- 数据结构之AVL树
- 数据结构之AVL树
- 数据结构 - AVL树
- 数据结构:avl树
- 数据结构之AVL树
- 数据结构之AVL树
- 数据结构之AVL树
- 数据结构: AVL树
- 数据结构之AVL树
- 数据结构之AVL树
- 手把手教你用VS2005打包问题,如何打包FramkWork2.0.
- WAMPSERVER 启动图标是黄色的
- ocp-301
- java密码的加密
- 堆和堆排序
- 数据结构: AVL树
- 01-咖喱土豆鸡肉饭
- 组合优化问题求解方法GA-交叉算子的总结
- 一起talk C栗子吧(第五十六回:C语言实例--图的最短路径四)
- Linux使用dd命令备份大文件显示进度
- mysql报 2003-Can't connect to MySql server on 'localhost'10061错误
- 【Python】Learn Python the hard way, ex29 if语句
- checked exception 和 unchecked exception区别
- 堆排序算法剖析(基于Java)