平衡二叉树(AVL)
简介
二叉查找树虽然能够进行快速查找,但是查找速度是不稳定的,在最坏情况下,二叉树的查找相当于单向链表查找。
那么如何解决这个问题呢?此时就需要保证二叉树的层数尽可能的少,叶子结点与根结点之间的距离尽可能平均,这就涉及一个概念 -- 平衡因子(左子树和右子树的高度差值)。平衡二叉树在插入结点时,会判断平衡因子是否符合要求,如果不符合,则会进行相应处理(旋转),保证左右子树高度平衡。下面将介绍一下四种旋转平衡的方法。
结点为左左
javascript
rotateLeftLeft(rootNode) {
// 1. 断开左结点与父结点的联系
const leftNode = rootNode.left;
rootNode.setLeft(null);
// 2. 将左结点作为接下来的父结点
if (rootNode.parent) {
rootNode.parent.setLeft(leftNode);
} else if (rootNode === this.root) {
// If root node is root then make left node to be a new root.
this.root = leftNode;
}
// 3. 如果左结点有右结点,那么将右结点设置为父结点的左结点(因为右结点比父结点小)
if (leftNode.right) {
rootNode.setLeft(leftNode.right);
}
// 4. 将父结点设置为左结点的右结点
leftNode.setRight(rootNode);
}
结点为左右
javascript
rotateLeftRight(rootNode) {
// 1. 父结点和子结点断开联系
const leftNode = rootNode.left;
rootNode.setLeft(null);
// 2. 将左结点与其右结点断开联系
const leftRightNode = leftNode.right;
leftNode.setRight(null);
// 3. 如果左右结点有左结点,将其添加到左结点的右结点上
if (leftRightNode.left) {
leftNode.setRight(leftRightNode.left);
leftRightNode.setLeft(null);
}
// 4. 将左右结点设为父结点的左结点
rootNode.setLeft(leftRightNode);
// 5. 将左结点设置为左右结点的左结点
leftRightNode.setLeft(leftNode);
// 6. 以上步骤实质上将结点转换成了左左的情况
this.rotateLeftLeft(rootNode);
}
结点为右左
与节点为左右的时候,情况对称。
结点为右右
与节点为左左的时候,情况对称。