树及树的算法(3) —— 平衡二叉树
来源:互联网 发布:mac播放flash 编辑:程序博客网 时间:2024/06/03 10:47
在计算机科学中,平衡二叉树(AVL树)是最先发明的自平衡二叉查找树。在AVL树中任何节点的两个子树的高度最大差别为一,所以它也被称为高度平衡树。查找、插入和删除在平均和最坏情况下都是O(log n)。增加和删除可能需要通过一次或多次树旋转来重新平衡这个树。AVL树得名于它的发明者是前苏联数学家G.M. Adelson-Velsky和E.M. Landis,他们在1962年的论文《An algorithm for the organization of information》中发表了它。
节点的平衡因子是它的右子树的高度减去它的左子树的高度。带有平衡因子1、0或 -1的节点被认为是平衡的。带有平衡因子 -2或2的节点被认为是不平衡的,并需要重新平衡这个树。平衡因子可以直接存储在每个节点中,或从可能存储在节点中的子树高度计算出来。
class AVLTree : public BST{protected:int height;int BalanceFactor () const;void AdjustHeight ();void LLRotation ();void LRRotation ();void RRRotation ();void RLRotation ();void AttachKey (Object&);Object& DetachKey ();void Balance ();public:AVLTree ();int Height () const;AVLTree& Left () const;AVLTree& Right () const;private:int Max(int lft, int rt) const;};AVLTree::AVLTree():BST(),height(-1){}int AVLTree::Height() const{return height;}void AVLTree::AdjustHeight(){if (IsEmpty ())height = -1;elseheight = Max (left->Height (), right->Height ()) + 1;}int AVLTree::Max( int lft, int rt ) const{return (lft>rt)?lft:rt;}int AVLTree::BalanceFactor() const{if (IsEmpty ()){return 0;}else{return left->Height () - right->Height ();}}void AVLTree::LLRotation(){if (IsEmpty ())throw domain_error ("invalid rotation");BinaryTree* const tmp = right;right = left;left = Right ().left;Right ().left = Right ().right;Right ().right = tmp;Object* const tmpObj = key;key = Right ().key;Right ().key = tmpObj;Right ().AdjustHeight ();AdjustHeight ();}void AVLTree::LRRotation(){if (IsEmpty ())throw domain_error ("invalid rotation");Left ().RRRotation ();LLRotation ();}void AVLTree::RRRotation(){ if (IsEmpty ()) throw domain_error ("invalid rotation"); BinaryTree* const tmp = left; left = right; right = Left().right; Left().right = Left().left; Left().left = tmp; Object* const tmpObj = key; key = Left().key; Left().key = tmpObj; Left().AdjustHeight(); AdjustHeight();}void AVLTree::RLRotation(){ if (IsEmpty ()) throw domain_error ("invalid rotation"); Right().LLRotation(); RRRotation();}void AVLTree::Balance(){AdjustHeight ();if (abs (BalanceFactor ()) > 1){if (BalanceFactor () > 0){if (Left ().BalanceFactor () > 0)LLRotation ();elseLRRotation ();}else{if (Right ().BalanceFactor () < 0)RRRotation ();elseRLRotation ();}}}void AVLTree::AttachKey( Object& object ){if (!IsEmpty ())throw domain_error ("invalid operation");key = &object;left = new AVLTree ();right = new AVLTree ();height = 0;}Object& AVLTree::DetachKey(){height = -1;return BST::DetachKey ();}AVLTree& AVLTree::Left() const{ if (IsEmpty()) { throw domain_error("invalid operation"); } return dynamic_cast<AVLTree&>(*left);}AVLTree& AVLTree::Right() const{ if (IsEmpty()) { throw domain_error("invalid operation"); } return dynamic_cast<AVLTree&>(*right);}
解释一下实现代码,AVL树在每次完成插入或删除之后,会进行一次平衡操作。这个操作会根据平衡因子的情况对节点进行旋转,如图:
向AVL树插入可以通过如同它是未平衡的二叉查找树一样把给定的值插入树中,接着自底向上向根节点折回,于在插入期间成为不平衡的所有节点上进行旋转来完成。因为折回到根节点的路途上最多有1.5乘log n个节点,而每次AVL旋转都耗费恒定的时间,插入处理在整体上耗费O(log n)时间。
从AVL树中删除可以通过把要删除的节点向下旋转成一个叶子节点,接着直接剪除这个叶子节点来完成。因为在旋转成叶子节点期间最多有log n个节点被旋转,而每次AVL旋转耗费恒定的时间,删除处理在整体上耗费O(log n) 时间。
可以像普通二叉查找树一样的进行,所以耗费O(log n)时间,因为AVL树总是保持平衡的。不需要特殊的准备,树的结构不会由于查找而改变。(这是与伸展树查找相对立的,它会因为查找而变更树结构。)
- 树及树的算法(3) —— 平衡二叉树
- 查找算法及二叉平衡树
- 验证算法——平衡二叉树
- 算法-平衡二叉树
- 平衡二叉树的数组表示算法
- 平衡二叉树的实现算法
- 平衡二叉查找树的基本算法
- 二叉平衡树的算法复杂度笔记
- 【基础算法】:平衡二叉树的插入
- 二叉排序树及平衡二叉树的实现
- 平衡二叉树算法详解
- 平衡二叉树算法详解
- 平衡二叉树算法分析
- 平衡二叉树算法分析
- 二叉排序树、二叉平衡树算法
- 平衡二叉树算法详解
- 算法Day10-平衡二叉树
- 平衡二叉树及调整
- android USB绑定功能实现(framework)
- 位域
- Hibernate Dialect must be explicitly set 错误信息解决方法
- 破除“系统学习”的情结
- Android 读写文件的N种写法
- 树及树的算法(3) —— 平衡二叉树
- 如何用 C# 批量获取域名 IP
- Build CP2K using Intel Fortran compiler Professional Edition
- poj 1004 Java
- 如何成为优秀的技术开发人员?
- 东软第三天课
- android手机定位不准的问题
- 楼教主的ACM心路历程
- Eclipse中web项目部署至Tomcat步骤