gb_tree平衡树源码
1.平衡树简称AVL,出名的有红黑树,这里介绍一下gb_tree的实现
gb_tree的原理比红黑树简单,没有过多的旋转跳跃闭着眼,是一种叫AA树的结构(Arne Andersson's General Balanced Trees),有兴趣看这篇论文:传送门
2.结构
{Size, Tree} 是整个结构体,Tree的定义又是 {Key, Value, Smaller, Bigger} | nil
初始化直接返回{0, nil}
3.插入
insert(Key, Val, {S, T}) when is_integer(S) ->
S1 = S+1,
{S1, insert_1(Key, Val, T, ?pow(S1, ?p))}. % 给size+1,insert_1返回新的结构
insert_1又是如何找到要插入的位置,且做平衡的?
% 由于对称性,这里讲插入左子树的情况就行
insert_1(Key, Value, {Key1, V, Smaller, Bigger}, S) when Key < Key1 -> % 要插入的key比目前节点的key小
case insert_1(Key, Value, Smaller, ?div2(S)) of
% 递归,在目前节点的左子树继续查找,当Smaller为nil的时候返回下面两种情况
% T1 就是已经更新好的左子树
{T1, H1, S1} ->
T = {Key1, V, T1, Bigger},
{H2, S2} = count(Bigger),
H = ?mul2(erlang:max(H1, H2)), %% 每层都会被调用一次
SS = S1 + S2 + 1,
P = ?pow(SS, ?p),
if
H > P -> % 满足这个条件就重新平衡
balance(T, SS);
true ->
{T, H, SS}
end;
T1 ->
{Key1, V, T1, Bigger} % 结果--节点和右子树均没改变,T1改变
end;
4.平衡
也就是上面的balance(T, SS),这里什么时候会被执行呢?看一下下面代码
%% 是的insert_1的{T1,H1, S1}分支被执行
insert_1(Key, Value, nil, S) when S =:= 0 ->
{{Key, Value, nil, nil}, 1, 1};
看看官方的说明

也就是说 13行的H>P就是重新进行平衡的时候了,而平衡的操作也很简单,看下代码,就是按顺序填满一棵树
balance_list_1(L, S) when S > 1 ->
Sm = S - 1,
S2 = Sm div 2,
S1 = Sm - S2,
{T1, [{K, V} | L1]} = balance_list_1(L, S1),
{T2, L2} = balance_list_1(L1, S2),
T = {K, V, T1, T2},
{T, L2};
balance_list_1([{Key, Val} | L], 1) ->
{{Key, Val, nil, nil}, L};
balance_list_1(L, 0) ->
{nil, L}.
5.删除
删除比插入是更简单了,找到对应的结点,然后从结点的右子树里找到一个最小的代替当前的点
delete_1(Key, {Key1, Value, Smaller, Larger}) when Key < Key1 ->
Smaller1 = delete_1(Key, Smaller),
{Key1, Value, Smaller1, Larger};
delete_1(Key, {Key1, Value, Smaller, Bigger}) when Key > Key1 ->
Bigger1 = delete_1(Key, Bigger),
{Key1, Value, Smaller, Bigger1};
delete_1(_, {_, _, Smaller, Larger}) ->
merge(Smaller, Larger).
merge(Smaller, nil) ->
Smaller;
merge(nil, Larger) ->
Larger;
merge(Smaller, Larger) ->
{Key, Value, Larger1} = take_smallest1(Larger),
{Key, Value, Smaller, Larger1}.
可以看到整棵树没有旋转等复杂操作,但是仍是一个效率比lists高的二叉树
gb_tree平衡树源码的更多相关文章
- LevelDB源码剖析
LevelDB的公共部件并不复杂,但为了更好的理解其各个核心模块的实现,此处挑几个关键的部件先行备忘. Arena(内存领地) Arena类用于内存管理,其存在的价值在于: 提高程序性能,减少Heap ...
- 死磕 java集合之TreeMap源码分析(二)- 内含红黑树分析全过程
欢迎关注我的公众号"彤哥读源码",查看更多源码系列文章, 与彤哥一起畅游源码的海洋. 插入元素 插入元素,如果元素在树中存在,则替换value:如果元素不存在,则插入到对应的位置, ...
- Java - TreeMap源码解析 + 红黑树
Java提高篇(二七)-----TreeMap TreeMap的实现是红黑树算法的实现,所以要了解TreeMap就必须对红黑树有一定的了解,其实这篇博文的名字叫做:根据红黑树的算法来分析TreeMap ...
- 源码速读及点睛:HashMap
Java 8 HashMap的分离链表 从Java 2到Java 1.7,HashMap在分离链表上的改变并不多,他们的算法基本上是相同的.如果我们假设对象的Hash值服从平均分布,那么获取一个对象需 ...
- 【转】【java源码分析】Map中的hash算法分析
全网把Map中的hash()分析的最透彻的文章,别无二家. 2018年05月09日 09:08:08 阅读数:957 你知道HashMap中hash方法的具体实现吗?你知道HashTable.Conc ...
- JDK部分源码阅读与理解
本文为博主原创,允许转载,但请声明原文地址:http://www.coselding.cn/article/2016/05/31/JDK部分源码阅读与理解/ 不喜欢重复造轮子,不喜欢贴各种东西.JDK ...
- 跟着大彬读源码 - Redis 9 - 对象编码之 三种list
目录 1 ziplist 2 skiplist 3 quicklist 总结 Redis 底层使用了 ziplist.skiplist 和 quicklist 三种 list 结构来实现相关对象.顾名 ...
- Java源码解析|HashMap的前世今生
HashMap的前世今生 Java8在Java7的基础上,做了一些改进和优化. 底层数据结构和实现方法上,HashMap几乎重写了一套 所有的集合都新增了函数式的方法,比如说forEach,也新增了很 ...
- Redis学习之zskiplist跳跃表源码分析
跳跃表的定义 跳跃表是一种有序数据结构,它通过在每个结点中维持多个指向其他结点的指针,从而达到快速访问其他结点的目的 跳跃表的结构 关于跳跃表的学习请参考:https://www.jianshu.co ...
随机推荐
- Effective Java 第三版—— 20. 接口优于抽象类
Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...
- python os 模块
os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径os.chdir("dirname") 改变当前脚本工作目录:相当于shell下cdos.curdir ...
- vim中的批量替换
VI中的批量替换 1) 文件内全部替换: :%s#abc#123#g (如文件内有#,可用/替换,:%s/abc/123/g) --注:把abc替换成123 (或者: %s/str ...
- Machine Learning - week 3
Classification 使用线性回归来分类,会很不准确.并且,它的范围也会超出 {0, 1}.所以使用下面的逻辑回归模型. Hypothesis representation 线性回归中 hθ( ...
- 运用C语言将图片转换成16进制的字符串(base64)
最近在写手机端的性能测试脚本的时候,发现手机在上传图片数据时,先将图片转换成一堆16进制的字符,将字符传输过去,服务器再将字符解码成图片 我们在loadrunner中测试时,就需要用C语言将图片编码. ...
- CTF---密码学入门第七题 杯酒人生
杯酒人生分值:10 来源: Veneno 难度:易 参与人数:2633人 Get Flag:790人 答题人数:963人 解题通过率:82% 使用古典密码 一喵星人要想喵星发送一段不知道干什么用的密码 ...
- [bzoj2638] 黑白染色
比较蛋疼的是我们可以先染个底色,再在底色上染别的东西. 由ccz大爷的题解可得..将目标状态里相同颜色的联通块缩点后,枚举起点,生成树里的最大节点深度就是需要的次数了, 如果最大深度是白色的话记得-1 ...
- 并查集-HDU1232-畅通工程
转的其他人的.不知道谁的. 来看一个实例,杭电1232畅通工程 首先在地图上给你若干个城镇,这些城镇都可以看作点,然后告诉你哪些对城镇之间是有道路直接相连的.最后要解决的是整幅图的连通性问题.比如随意 ...
- UR11 A.元旦老人与汉诺塔
题目:http://uoj.ac/contest/23/problem/167 如果我们拿个map来存状态的话.设当前状态是v,下一个状态是s.有f[i+1][s]+=f[i][v]. 初始f[0][ ...
- Android扫码二维码、美女瀑布流、知乎网易音乐、动画源码等
Android精选源码 QRCode 扫描二维码.扫描条形码.相册获取图片后识别.生... 一个简洁好看的loading弹窗 Android用瀑布流展示美女图片源码 Android知乎阅读 ...