Avl Tree
对于二叉搜索树,如果预先输入一堆排好序的序列,其会退化成单链表。为了解决这个问题,规定一个平衡的附加条件:任何节点的深度都不的过深。但是标准的二叉平衡树实现起来复杂性过高,因此介绍一种较为经典的平衡术—avl(adelson-velskii and landis) 树
它的特点是:
- 每个节点的左子树和右子树相差高度不超过1的二叉搜索树
Insert
对于 avl 树最主要的问题应该在于插入后,如何保证其平衡的要求即: 每个节点的左子树和右子树相差高度不超过1
对于一节待平衡节点,破坏其平衡由四种可能
- 对其左儿子的左子树一次插入
- 对其左儿子的右子树一次插入
- 对其右儿子的右子树一次插入
- 对其右儿子的左子树一次插入
对于每一种情况进行分析
left - left 结构(即第一种)
此时 k2
节点是不平衡的,
此时以k1
为节点,顺时针旋转,k2
,然后将k1
的右孩子置为k2
,k2
的左孩子置为y
1 | Position single_rotate_with_left(Position k2) |
right - right 结构(第三种)
此时与第一种对称
1 | Position single_retate_with_right(Position k1) |
left-right 结构[第二种结构]
此时可以观察,k1
,k2
,k3
布局,使用两次旋转。第一次对于k1,k2
进行一次右单旋(第三种结构)。再对调整后的布局(k2
,k3
)再进行一次左单旋。
1 |
|
right-left 结构[第四种结构]
此时可以观察,k1
,k2
,k3
布局,使用两次旋转。第一次对于k2,k3
进行一次左单旋(第一种结构)。再对调整后的布局(k1
,k2
)再进行一次右单旋。
1 | Position rotate_with_left_right(Position k1) |
插入
接下来的插入就比较清晰了,插入流程与二叉搜索树一样,但是每次插入之后,要对其平衡性进行判断,根据不同的情形,进行不同的调整:
1 |
|
find
查找过程与二叉搜索树一样
delete
删除采用哑节点的模式,因为删除后的调整更为繁杂。
1 | AvlTree remove(Element e, AvlTree t, compare_func cmp) |
// TODO
更多删除方法,请见
…
Implement
- 本文标题: Avl Tree
- 本文作者:codeflysafe
- 创建时间:2020-03-12 16:26:46
- 本文链接:https://codeflysafe.github.io/2020/03/12/2020-03-12-Avl-Tree/
- 版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
评论