在这篇文章里说了,AVL树平衡的两个条件是:1)首先,二叉查找树要求一个树的根节点必然大于(或小于)其左子树中的所有节点, 同时必然小于(或大于)其右子树中的所有节点,也就是说,如果按照中序遍历二叉查找树, 它必然是严格递增(或递减)的.2)AVL树的平衡条件要求任何一颗子树,其左右子树的高度差不超过1.我们要求一颗树是AVL树,必须严格符合以上的两 个条件.

可以从这两个条件着手考虑AVL树中节点的删除.

首先,采用二叉查找树的删除节点算法删除一个节点,这个算法在这里有阐述, 此时必然保证了第一个条件.

其次, 从所删除节点的父节点开始向上搜索,看看哪里出现了不平衡的地方, 出现不平衡的情况肯定是因为这条路径上一个节点的兄弟节点高度大于该节点高度,可以通过旋转将这个兄弟节点上升一层, 这样就满足了第二个条件.

以一个例子进行说明:
      10              10                18
     
/  \            / \               / \
    
5   18          5  18             10  12
   
/    / \   ==>      / \    ==>     /   / \
  
4    12 19          12  19         5   11  19
       
/              /
      
11             11

假设这里要删除的节点是4,在删除了节点4之后, 沿着4的父节点向上查询, 看看哪里出现了不平衡的情况, 发现节点5的高度比它的兄弟节点低了2, 那么这里要做的就是把这个兄弟节点,也就是18往上移一层, 采用的就是AVL树的单旋转方法,最后树重新达到了AVL树的两个条件.

本来想实验一下这个算法,但是原来这里的实现中, 节点的struct没有保存父节点的指针, 修改起来比较麻烦, 就不做实现了.
不知道这个算法是不是正确的,目前仅是我凭空的推理, 如果有其它地方提到了别的AVL树删除节点算法, 或者有地方证实了这个算法是可行的,请告诉我一声,谢谢.

补充:
如果这个算法是可行的,那么还有进一步优化的可能.
分两种情况:1)删除节点有两个子节点, 此时, 替代该节点的新结点, 其高度不会发生变化, 也就不会破坏平衡, 此时不需要进行旋转操作, 也就不需要往上走查询平衡是否被破坏了.
2)删除节点只有一个节点或者没有节点,此时平衡才有可能被破坏, 按照上面的算法进行平衡操作.

posted on 2008-09-17 12:38 那谁 阅读(1403) 评论(5)  编辑 收藏 引用 所属分类: 算法与数据结构
Comments
  • # re: AVL树删除节点算法[未登录]
    陈梓瀚(vczh)
    Posted @ 2008-09-17 12:57
    每一次插入的时候,从插入的节点开始往上找,每次遇到一个不平衡的父节点都旋转一次,一直到根节点为止。

    删除的时候,将中序右继换过来之后,进行上面的操作。  回复  更多评论   
  • # re: AVL树删除节点算法[未登录]
    季阳
    Posted @ 2008-09-17 18:08
    不一定需要父节点指针,也可以通过保存从根结点到被删除节点的路径,然后网上调整.  回复  更多评论   
  • # re: AVL树删除节点算法
    Lucifer
    Posted @ 2008-09-17 19:40
    老实说,俺从来没实现过 AVL Tree。实践中,凡是能够使用 AVL Tree 的地方都被 Red-Black Tree 代替了。  回复  更多评论   
  • # re: AVL树删除节点算法
    E剑仙
    Posted @ 2008-09-29 10:57
    呵呵什么时候能探讨一下自平衡树(无论AVL还是RB)的节点修改操作?有否除了“节点修改=删除+重新添加”外的更优算法?  回复  更多评论   
  • # re: AVL树删除节点算法
    dragon
    Posted @ 2008-10-10 10:12
    将18左旋转后到达不到平衡
    插入的时候不用插入后才往上找不平衡的结点,直接在找插入的时候就能标记好插入后会导致不平衡的点,然后直接判断如何使用旋转就可以了  回复  更多评论   

标题  
姓名  
主页
验证码 *
内容(提交失败后,可以通过“恢复上次提交”恢复刚刚提交的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
[使用Ctrl+Enter键可以直接提交]
相关链接:
网站导航: