直面弱点,不再逃避!!!
接上篇文章《二叉搜索树》了解到二叉搜索树在极端情况也不能满足我们对于查询性能的要求。
我们下面来使用 A - H字符来观察二叉搜索树在不同的插入顺序下构造的树的结果
自然顺序的平均查找长度为ASL=(1+ 2 + 3 + 4+ 5+ 6+ 7 +8) / 8 = 4.5
计算特定顺序的平均查找长度ASL=(1 + 2*2 + 3*4 + 4*1) / 8 = 2.6
当我们数据相同,但是采用不同的插入顺序,使平均查找长度不一样。所以我们要解决这个问题,先观察两个初始化方式两个树的特点,大致发现使用特定顺序初始化的树,感觉树的节点分布比较平衡。由于统计特点3和特点2,我们希望n个节点的二叉树的接近log2n + 1,那么我们就可以最大化的提升查询性能.
所以为了解决这个问题,我们引入新的二叉搜索树实现-平衡二叉树(AVL树)
原有节点的基础上增加height属性
class AVLNode<T extends Comparable<T>> {
private T data;
//左节点
private AVLNode<T> left;
//右节点
private AVLNode<T> right;
//当前节点的高度
private int height;
}
由于平衡二叉树的平衡指高度方面的平衡,我们先来计算树的高度
树的高度H指:左HL右HR子树高度的最大值 + 1
}
GDB路径(LL插入)、GDF路径(LR插入)、ADF路径(RR插入)、ADB路径(RL插入)
接下来我们将处理所有的情况
当插入节点在右子树的右节点上(ADF路径)
操作步骤:
实现代码如下:
AVLNode<T> singleRightRotation(AVLNode<T> node) {
AVLNode<T> result = node.getRight();
AVLNode<T> left = result.getLeft();
node.setRight(left);
result.setLeft(node);
return result;
}
LL插入
当插入的节点在左子树的左节点上(GDB路径)
操作步骤:
实现代码:
}
当插入的节点在右子树的左节点上(ADB路径)
操作步骤:
实现代码:
AVLNode<T> doubleRightLeftRotation(AVLNode<T> node){
AVLNode<T> right = singleLeftRotation(node.getRight());
node.setRight(right);
return singleRightRotation(node);
}
当插入的节点在右子树的左节点上(GDF路径)
操作步骤:
实现代码:
AVLNode<T> doubleLeftRightRotation(AVLNode<T> node) {
AVLNode<T> left = singleRightRotation(node.getLeft());
node.setLeft(left);
return singleLeftRotation(node);
}
我们在删除节点时,思路:
平衡调整的思路:节点被删除后,相当于在兄弟节点插入新的节点
代码如下:
AVLNode<T> delete(AVLNode<T> node, T data) {
由于AVL是一个高度严格平衡的二叉搜索树,查找效率在log2n级别。但是在维护节点高度平衡时,需要进行旋转操作(插入时最多两次旋转;删除节点时AVL树需要调整整个查询路径的高度平衡,最多需要log2n次旋转)
后面,我们将介绍另外一种平衡搜索二叉树(红黑树)!
欢迎大家关注留言分享和我交流!
本文分享自 javascript艺术 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!