当年实现自己的共享内存模板的时候,map和set的没有实现,本来考虑用一个AVLTree作为底层实现的,为啥,因为我当时的数据结构知识里面我和RBTree不熟,只搞过AVLTree,但当时我一直没有看过删除如何实现。结果Scottxu跳出来,参考STLport的实现,迅速用RBTree搞掂了。搞得这个代码的头文件也就一直放在那儿,7-8年后,整理这个代码,看看Scottxu代码的底子,觉得挺不错的,觉得Copy改造一个AVLTree的实现应该很容易,就上手了。

AVL的插入无话可说,就是参考严蔚敏先生的《数据结构》上的手(仿佛回到十几年前的大学时代),迅速搞掂,但到删除,又哑火了。可以参考的代码不多。特别把AVLTree删除的代码讲明白的不多,有些明显存在错误,有些是用高度Height计算的平衡因子,但大部分实现计算Height都是用递归,但这种消耗性能方法在正式环境基本不具备可操作性。于是看了一些帖子,自己摸索了一下实现,完善了基于每个节点自己保存平衡因子的结构算法(严蔚敏先生的《数据结构》树中的插入也是基于平衡因子的,实现过程,发现小坑不少,总结出来。

(1)首先,仍然是找到这个要删除的节点。

(2)然后要如果这个节点是叶子节点,直接删除,如果不是叶子节点,需要将其交换成叶子节点。而交换方法是,选的其左子树的最大节点(左子节点的最右儿子节点,),或者右子树最小的节点(右子节点的最左儿子节点)。也就是选择这个节点最相邻的节点,和这个其交换。如果这个交换的位置还不是叶子节点,就继续前面的方法找个节点交换。

当这个节点成为叶子节点,就删除之。

示例一:10为要删除的节点。经过2次交换,将其调整为节点3的位置,成为叶子节点

交换后的树形变成:

示例二:10为要删除的节点。经过1次交换,将其调整为节点7的位置,成为叶子节点

调整后的树形变成:

(3)删除后,就要调整其父节点的平衡因子了。插入过程的时候,调整到平衡因子不等于0的节点就可以了。而删除过程恰恰相反,调整到一个平衡因子为0的时候(高度变化对平衡的影响只到此为止),就可以停止。发现一个节点存在不平衡,平衡因子是2或者-2,那么就需要做旋转调整。而旋转调整后,可能要继续向上调整(这个和插入不太一样),也可能停止调整(后面重点说明这个问题)。

如果是传统意义的的LL,LR,RR,RL旋转4种旋转,那么树的高度会减少,所以还是要继续向上调整平衡因子。

但有意思的是,由于删除的特点,你会发现可能出现的情况,不全是传统LL,LR,RR,RL 4种旋转。比如,下面这个示例。

节点内部的()内为平衡因子,12为要删除的节点,删除后,节点7的平衡因子是2,但其左子节点5的平衡因子是0,这和LL(左子树平衡因子为1)和LR旋转(左子树要平衡因子是-1)的情况都有一定的区别。

而这个树形还是可以通过LL旋转让其平衡,但平衡之后,各个节点的平衡因子和插入后的平衡因子不一样,根节点平衡因子没有调整为0,而且发生这种情况下,树的高度没有发生变化,所以在删除的情况下也不用继续向上调整了。

同样展示一下类似RR旋转的一种情况:

其调整后的树形变成

好了,基本情况如上所诉,参考代码放在GIT,是基于模板的,类似STLPort。

算法这个东西,没有看到明确明确说明前,碰还是谨慎一点,这次的测试过程画了一堆的树形图。最后怀旧一下,当年在话单过滤的时候也写过AVLTree(那时也没有实现删除),至今看看当年幼稚的代码,而当年的大学时代的《数据结构》课程的代码已经不知道在那张发霉的3吋软盘上了,有些唏嘘。好吧过两天要去听李宗盛的演唱会《既然青春留不住》了。

【本文作者是雁渡寒潭,本着自由的精神,你可以在无盈利的情况完整转载此文档,转载时请附上BLOG链接:http://www.cnblogs.com/fullsail/,否则每字一元,每图一百不讲价。对Baidu文库和360doc加价一倍】

AVLTree的节点删除的更多相关文章

  1. 二叉平衡查找树AvlTree(C实现)

    二叉平衡查找树即是一棵树中所有节点的左右子树高度差不超过1的查找树 头文件—————————————————————————————— #ifndef _AVLTREE_H_ #define _AVL ...

  2. hdu 4006/AvlTree

    原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=4006 这道题以前用c语言写的Avltree水过了.. 现在接触了c++重写一遍... 由于没有删除操作 ...

  3. Java实现平衡二叉树(AVLTree)的构建

    近期在学习数据结构上关于平衡二叉树的知识,看了严老师的思路,感觉用java写出递归的构建方式有点困难,由于当中的递归须要把引用传进去,所以感觉是要实现起来比較麻烦,所以就首先想到使用非递归的方式来实现 ...

  4. POJ 2418 Hardwood Species( AVL-Tree )

    #include <stdio.h> #include <stdlib.h> #include <math.h> #include <string.h> ...

  5. DOM节点删除之empty和remove

    DOM节点删除之empty和remove 刚学了新知识,虽然是一个小知识点,但还是忍不住想和大家分享. .empty()是指对该节点后代的删除,结果是清空该节点(该节点里面已无元素). .remove ...

  6. C#平衡树(AVLTree)

    参考:http://www.cnblogs.com/skywang12345/p/3577479.html using System; using System.Collections.Generic ...

  7. jQuery基础(DOM篇,append(),after(),prepend(),insertAfter(),节点删除,遍历方法each())

    1.DOM创建节点及节点属性   创建流程比较简单,大体如下:   - 创建节点(常见的:元素.属性和文本) - 添加节点的一些属性 - 加入到文档中   流程中涉及的一点方法:   - 创建元素:d ...

  8. 数据结构——平衡二叉树(AVLTree)

    3.平衡二叉树 平衡二叉树,又称AVL树,它是一种特殊的二叉排序树. 3.1 平衡二叉树的四种自旋 这个左旋.右旋,在方向上和我观念里的是相反的. 查了之后才知道: 1.外侧插入:LL.RR,都是在最 ...

  9. 当xml结构很深时候 可以通过父节点删除子元素

    当xml结构很深时候 可以通过父节点删除子元素

随机推荐

  1. JSP中脚本、声明和表达式的本质区别

     JSP脚本元素 使用JSP脚本元素可以将Java代码嵌入到JSP页面里,这些Java代码将出现在由当前JSP页面生成的Servlet中,使JSP将静态内容与动态内容分离出来.脚本元素包含:  1. ...

  2. nginx静态资源分离部署

    修改nginx.conf文件,用于nginx处理静态资源. 主要配置如下(在server配置中加入location配置即可): server { listen 80; server_name 123. ...

  3. SQLite入门与分析(三)---内核概述(2)

    写在前面:本节是前一节内容的后续部分,这两节都是从全局的角度SQLite内核各个模块的设计和功能.只有从全局上把握SQLite,才会更容易的理解SQLite的实现.SQLite采用了层次化,模块化的设 ...

  4. SQLite入门与分析(三)---内核概述(1)

    写在前面:从本章开始,我们开始进入SQLite的内核.为了能更好的理解SQLite,我先从总的结构上讨论一下内核,从全局把握SQLite很重要.SQLite的内核实现不是很难,但是也不是很简单.总的来 ...

  5. 关于C的一些理解

    关于字符数组和字符指针 关于相互赋值问题一只有疑问,其实是自己搞不清指针和地址的关系.地址可以指向一块内存但是不一定存在于内存,比如字符数组名,数组名是地址,但是不实际存在于内存中,无法修改,而字符指 ...

  6. 函数buf_page_get

    /**************************************************************//** NOTE! The following macros shoul ...

  7. poj2823

    这是一道题意简单,数据较大的题(喜闻乐见): 一开始可能会想到RMQ问题,ST,线段树都是O(nlogn),应该勉强能过(没试过): 由于这道题区间是滚动连续的,所以,可以使用单调队列! 以最小值为例 ...

  8. bzoj1196:[Hnoi2010]chorus 合唱队

    这数据范围明显的区间dp啊...然而据说二维会wa...那就写三维把... #include<cstdio> #include<cstring> #include<cct ...

  9. [LOJ 1038] Race to 1 Again

    C - Race to 1 Again Time Limit:2000MS     Memory Limit:32768KB     64bit IO Format:%lld & %llu D ...

  10. (转)solr排序OOM解决方法

    转自 http://topcat.iteye.com/blog/1293650 问题 lucene使用排序时会将被排序字段全部加入内存再进行排序,当多次使用不同字段进行排序时会造成OOM问题 解决方案 ...