AVL树特点
(1)每个节点的平衡因子只可能是-1,0,1(否则失衡)。
(2)每个节点的左右子树高度差不能超过1。
(3)搜索、添加、删除的时间复杂度和高度差不多为 O(log n)。
为什么使用AVL树
二叉搜索树对节点的删除和添加都有可能让二叉树退化为链表,这样二叉搜索树的高度就变得很高,直接导致了搜索、添加、删除的时间复杂度变高。
所以我们考虑再添加删除后,使用尽量少的调整让树的高度变小,达到适度的平衡。进而提高删除,搜索,添加的效率。
重构代码
AVL树是BST(二叉搜索树)的子类,BST代码在之前的文章中
import java.util.Comparator;
public class AVLTree<E> extends BST<E>{
//构造方法
public AVLTree(){
this(null);
}
public AVLTree(Comparator<E> comparator) {
super(comparator);
}
/*
一棵树是否平衡
*/
private boolean isBalanced(Node<E> node) {
return Math.abs(((AVLNode<E>)node).balanceFactor()) <= 1;
}
/*
高度更新方法的封装
*/
private void updateHeight(Node<E> node) {
((AVLNode<E>)node).updateHeight();
}
/*
AVL数需要有高度属性
AVL特有的节点
*/
private static class AVLNode<E> extends Node<E>{
int height = 1;
public AVLNode(E element, Node<E> parent) {
super(element, parent);
// TODO 自动生成的构造函数存根
}
/*
求平衡因子
*/
public int balanceFactor() {
int leftHeight = left == null ? 0 : ((AVLNode<E>)left).height;
int rightHeight = right == null ? 0 : ((AVLNode<E>)right).height;
return leftHeight - rightHeight;
}
/*
更新高度的方法
*/
public void updateHeight() {
int leftHeight = left == null ? 0 : ((AVLNode<E>)left).height;
int rightHeight = right == null ? 0 : ((AVLNode<E>)right).height;
height = 1 + Math.max(leftHeight, rightHeight);
}
/*
* 找比较高的子节点
*/
public Node<E> tallerChild(){
int leftHeight = left == null ? 0 : ((AVLNode<E>)left).height;
int rightHeight = right == null ? 0 : ((AVLNode<E>)right).height;
if (leftHeight > rightHeight) {return left;}
if (leftHeight < rightHeight) {return right;}
//相等返回同边的
return isLeftChild() ? left : right;
}
}
/*
* 重写方法恢复平衡的逻辑
*/
@Override
protected void afterAdd(Node<E> node) {
while((node = node.parent) != null) {
if (isBalanced(node)) {
//更新高度
updateHeight(node);
}else {
//恢复平衡
rebalance(node);
break;
}
}
}
/*
删除后恢复平衡的方法
*/
@Override
protected void afterRemove(Node<E> node) {
while((node = node.parent) != null) {
if (isBalanced(node)) {
//更新高度
updateHeight(node);
}else {
//恢复平衡
rebalance(node);
}
}
}
/*
恢复树平衡的逻辑
*/
private void rebalance(Node<E> grand) {
//找高度比较高的子节点
Node<E> parent = ((AVLNode<E>)grand).tallerChild();
Node<E> node = ((AVLNode<E>)parent).tallerChild();
if (parent.isLeftChild()) {// L
if (node.isLeftChild()) {//LL
rotateRight(grand);
}else { //LR
rotateLeft(parent);
rotateRight(grand);
}
}else { //R
if (node.isRightChild()) {//RR
rotateLeft(grand);
}else {//RL
rotateRight(parent);
rotateLeft(grand);
}
}
}
/*
统一的恢复平衡的方法
*/
private void rebalance2(Node<E> grand) {
//找高度比较高的子节点
Node<E> parent = ((AVLNode<E>)grand).tallerChild();
Node<E> node = ((AVLNode<E>)parent).tallerChild();
if (parent.isLeftChild()) {// L
if (node.isLeftChild()) {//LL
rotate(grand, node.left, node, node.right, parent, parent.right, grand, grand.right);
}else { //LR
rotate(grand, parent.left, parent, node.left, node, node.right, grand, grand.right);
}
}else { //R
if (node.isRightChild()) {//RR
rotate(grand, grand.left, grand, parent, parent.left, node, node.left, node.right);
}else {//RL
rotate(grand, grand.left, grand, node.left, node, node.right, parent, parent.right);
}
}
}
/*
统一的旋转方法
*/
private void rotate(
Node<E> r, //子树根节点
Node<E> a,Node<E> b,Node<E> c,
Node<E> d,
Node<E> e,Node<E> f,Node<E> g) {
//让d成为这个子树的根节点
d.parent = r.parent;
if (r.isLeftChild()) {
r.parent.left = d;
}else if (r.isRightChild()) {
r.parent.right = d;
}else {
//根节点
root = d;
}
// a-b-c
b.left = a;
b.right = c;
if (a != null) {
a.parent = b;
}
if (c != null) {
c.parent = b;
}
updateHeight(b);
//e-f-g
f.left = e;
f.left = g;
if (e != null) {
a.parent = f;
}
if (g != null) {
g.parent = g;
}
updateHeight(f);
//b-d-f
d.left = d;
d.left = f;
b.parent = d;
f.parent = d;
updateHeight(d);
}
/*
左旋转
*/
private void rotateLeft(Node<E> grand) {
Node<E> parent = grand.right;
Node<E> child = parent.left;
//旋转
grand.right = child;
parent.left = grand;
//更新父节点
//parent
parent.parent = grand.parent;
if (grand.isLeftChild()) {
grand.parent.left = parent;
}else if (grand.isRightChild()) {
grand.parent.right = parent;
}else {
//grand为根节点
root = parent;
}
//grand
grand.parent = parent;
//node
if (child != null) {
child.parent = grand;
}
//更新高度
updateHeight(grand);
updateHeight(parent);
}
/*
右旋转
*/
private void rotateRight(Node<E> grand) {
Node<E> parent = grand.left;
Node<E> child = parent.right;
grand.left = child;
parent.right = grand;
parent.parent = grand.parent;
if (grand.isLeftChild()) {
grand.parent.left = parent;
}else if (grand.isRightChild()) {
grand.parent.right = parent;
}else {
root = parent;
}
grand.parent = parent;
if (child != null) {
child.parent = grand;
}
updateHeight(grand);
updateHeight(parent);
}
/*
重写方法 创建节点
*/
@Override
protected Node<E> createNode(E element, Node<E> parent) {
return new AVLNode<E>(element, parent);
}
}