AVLTree的节点删除
当年实现自己的共享内存模板的时候,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的节点删除的更多相关文章
- 二叉平衡查找树AvlTree(C实现)
二叉平衡查找树即是一棵树中所有节点的左右子树高度差不超过1的查找树 头文件—————————————————————————————— #ifndef _AVLTREE_H_ #define _AVL ...
- hdu 4006/AvlTree
原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=4006 这道题以前用c语言写的Avltree水过了.. 现在接触了c++重写一遍... 由于没有删除操作 ...
- Java实现平衡二叉树(AVLTree)的构建
近期在学习数据结构上关于平衡二叉树的知识,看了严老师的思路,感觉用java写出递归的构建方式有点困难,由于当中的递归须要把引用传进去,所以感觉是要实现起来比較麻烦,所以就首先想到使用非递归的方式来实现 ...
- POJ 2418 Hardwood Species( AVL-Tree )
#include <stdio.h> #include <stdlib.h> #include <math.h> #include <string.h> ...
- DOM节点删除之empty和remove
DOM节点删除之empty和remove 刚学了新知识,虽然是一个小知识点,但还是忍不住想和大家分享. .empty()是指对该节点后代的删除,结果是清空该节点(该节点里面已无元素). .remove ...
- C#平衡树(AVLTree)
参考:http://www.cnblogs.com/skywang12345/p/3577479.html using System; using System.Collections.Generic ...
- jQuery基础(DOM篇,append(),after(),prepend(),insertAfter(),节点删除,遍历方法each())
1.DOM创建节点及节点属性 创建流程比较简单,大体如下: - 创建节点(常见的:元素.属性和文本) - 添加节点的一些属性 - 加入到文档中 流程中涉及的一点方法: - 创建元素:d ...
- 数据结构——平衡二叉树(AVLTree)
3.平衡二叉树 平衡二叉树,又称AVL树,它是一种特殊的二叉排序树. 3.1 平衡二叉树的四种自旋 这个左旋.右旋,在方向上和我观念里的是相反的. 查了之后才知道: 1.外侧插入:LL.RR,都是在最 ...
- 当xml结构很深时候 可以通过父节点删除子元素
当xml结构很深时候 可以通过父节点删除子元素
随机推荐
- APP 上传之后出现"invalid binary" 问题解决汇总
背景 5.1 号开始 App 审核开始强制支持 iPhone5,并禁止使用 UDID. 问题 上传 app 后一直处于 Invalid Binary 状态,并且收到一封邮件说 Non-public A ...
- python参考手册--第8章
1.模块和import (1)首次import module会做以下3件事: a)创建新的命名空间,用作在该源文件中定义的所有对象的容器.在模块中定义的函数和方法在使用global语句时将访问该命名空 ...
- 如何将DJANGO轻量级化
看看这本书,应该有收获. 不用DJANGO-ADMIN STARTPROJECT XXX 一个文件,一样可以写出可以运行的原生DJANGO哟. import hashlib import sys im ...
- HDU1429+bfs+状态压缩
bfs+状态压缩思路:用2进制表示每个钥匙是否已经被找到.. /* bfs+状态压缩 思路:用2进制表示每个钥匙是否已经被找到. */ #include<algorithm> #inclu ...
- HDU4545+LCS
最长公共子序列. /* LCS 最长公共子序列 */ #include<stdio.h> #include<string.h> #include<stdlib.h> ...
- CKEditor在线编辑器增加一个自定义插件
CKEditor是一个非常优秀的在线编辑器,它的前身就是FCKEditor,CKEditor据官方说是重写了内核的,但功能和性能比FCKEditor更为强大和优越.记得07年的时候第一次接触FCKEd ...
- codeforces #310 div1 A
首先我们考虑最暴力的拆解拼凑 显然拆分掉所有的链需要 n-m 次 之后拼凑需要 n-1 次 然后由题目规定可知:只有从1出发且连续的链不用拆掉,其余的都必须拆掉(因为两个都套有娃娃的套娃不能组合) 我 ...
- [itint5]棋盘漫步
要注意dp[0][0]要初始化为1. int totalPath(vector<vector<bool> > &blocked) { int m = blocked.s ...
- 初始化windows窗口
LRESULT WINAPI WndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam) { PAINTSTRUCT ps; switch (msg ...
- VS下遇到未能加载文件或程序集 错误
这个的错误原因可能是在64的系统上编译32位的应用程序,遇到这个错误,可以通过下面的手段解决! 1.关闭Visual Studio. 2. 在Visual Studio Tools子目录,以管理员身份 ...