public class AVLBinaryTree<E extends Comparable<E>> {
Node<E> root;
int size = 0;
private static final int LH = 1;
private static final int RH = -1;
private static final int EH = 0;
/*
* x y
* / \ / \
* a y <-----> x c
* / \ / \
* b c a b
*/
public void left_rotate(Node<E> x) {
if (x != null) {
Node<E> y = x.right;
//1,b作为x的右孩子
x.right = y.left;
if (y.left != null) {
y.left.parent = x;
}
//2,把y移到x的位置
y.parent = x.parent;
if (x.parent == null) {
root = y;
} else {
if (x.parent.left == x) {
x.parent.left = y;
} else if (x.parent.right == x) {
x.parent.right = y;
}
}
//3,x作为y的左孩子
y.left = x;
x.parent = y;
}
}
public void right_rotate(Node<E> y) {
if (y != null) {
Node<E> x = y.left;
//1,b作为y的左孩子
y.left = x.right;
if (y.left != null) {
y.left.parent = x;
}
//2,把x移到y的位置
x.parent = y.parent;
if (y.parent == null) {
root = x;
} else {
if (y.parent.left == y) {
y.parent.left = x;
} else if (y.parent.right == y) {
y.parent.right = x;
}
}
//3,y作为x的右孩子
x.right = y;
y.parent = x;
}
}
/**
* 右平衡操作,即结点t的不平衡是因为右子树过深
*
* 1、如果新的结点插入到t的右孩子的右子树中,则直接进行左旋操作即可
*
* t tr
* / \ / \
* l tr 左旋操作 t rr
* / \ -----------> / \ / \
* rl rr l rl rrl rrr
* / \
* rrl rrr
* 2、如果新的结点插入到t的右孩子的左子树中,则需要进行分情况讨论
* 情况a:当t的右孩子的左子树根节点的balance = LEFT_HIGH
*
* t t trl
* / \ / \ / \
* 2 tr tr右旋 2 trl t左旋 t tr
* / \ -------> / \ -------> / \ \
* trl 5 6 tr 2 6 5
* / \
* 6 5
* 情况b:当t的右孩子的左子树根节点的balance = RIGHT_HIGH
*
* t t trl
* / \ / \ / \
* 2 tr tr右旋 2 trl t左旋 t tr
* / \ -------> \ -------> / / \
* trl 5 tr 2 6 5
* \ / \
* 6 6 5
* 情况C:当t的右孩子的左子树根节点的balance = EQUAL_HIGH
* t t trl
* / \ / \ / \
* 2 tr 右旋 2 trl 左旋 t tr
* / \ -------> / \ -------> / \ / \
* trl 5 6 tr 2 6 7 5
* / \ / \
* 6 7 7 5
* */
public void rightBalance(Node<E> t) {
Node<E> tr = t.right;
switch (tr.balance) {
case RH://新的结点插入到t的右孩子的右子树中
left_rotate(t);
t.balance = EH;
tr.balance = EH;
break;
case LH://新的结点插入到t的右孩子的左子树中
Node<E> trl = tr.left;
switch (trl.balance) {
case RH:
t.balance = LH;
tr.balance = EH;
trl.balance = EH;
break;
case LH:
t.balance = EH;
tr.balance = RH;
trl.balance = EH;
break;
case EH:
tr.balance = EH;
trl.balance = EH;
t.balance = EH;
break;
}
right_rotate(t.right);
left_rotate(t);
break;
}
}
/**
* 左平衡操作,即结点t的不平衡是因为左子树过深
*
* 1、如果新的结点插入到t的左孩子的左子树中,则直接进行右旋操作即可
* t tl
* / \ 右旋操作 / \
* tl tr -------------> tll t
* / \ / \ / \
* tll tlr lcll lclr tlr tr
* / \
* lcll lclr
*
* 2、如果新的结点插入到t的左孩子的右子树中,则需要进行分情况讨论
*
* 情况a:当t的左孩子的右子树根节点的balance = RIGHT_HIGH
* t t tlr
* / \ / \ / \
* tl 6 左旋 tlr 6 右旋 tl t
* / \ -------> / \ --------> / / \
* 3 tlr tl 5 3 5 6
* \ /
* 5 3
* 情况b:当t的左孩子的右子树根节点的balance = LEFT_HIGH
*
* t t tlr
* / \ / \ / \
* tl 6 左旋 tlr 6 右旋 tl t
* / \ -------> / --------> / \ \
* 3 tlr tl 3 5 6
* / / \
* 5 3 5
*
* 情况c:当t的左孩子的右子树根节点的balance = EQUAL_HIGH
*
* t t tlr
* / \ / \ / \
* tl 7 左旋 tlr 7 右旋 tl t
* / \ -------> / \ --------> / \ / \
* 3 tlr tl 6 3 5 6 7
* / \ / \
* 5 6 3 5
* */
public void leftBalance(Node<E> t) {
Node<E> tl = t.left;
switch (tl.balance) {
case LH:
right_rotate(t);
tl.balance = EH;
t.balance = EH;
break;
case RH:
Node<E> tlr = tl.right;
switch (tlr.balance) {
case LH:
t.balance = RH;
tl.balance = EH;
tlr.balance = EH;
break;
case RH:
t.balance = EH;
tl.balance = LH;
tlr.balance = EH;
break;
case EH:
t.balance = EH;
tl.balance = EH;
tlr.balance = EH;
break;
default:
break;
}
left_rotate(t.left);
right_rotate(t);
break;
}
}
public boolean insertElement(E element) {
Node<E> t = root;
if (t == null) {
root = new Node<E>(element, null);
size = 1;
root.balance = 0;
return true;
} else {
//开始找到要插入的位置
int cmp = 0;
Node<E> parent;
Comparable<? super E> e = (Comparable<? super E>) element;
do {
parent = t;
cmp = e.compareTo(t.element);
if (cmp < 0) {
t = t.left;
} else if (cmp > 0) {
t = t.right;
} else {
return false;
}
} while (t != null);
//开始插入数据
Node<E> child = new Node<E>(element, parent);
if (cmp < 0) {
parent.left = child;
} else {
parent.right = child;
}
//节点已经放到了树上
//检查平衡,回溯查找
while (parent != null) {
cmp = e.compareTo(parent.element);
if (cmp < 0) {
parent.balance++;
} else {
parent.balance--;
}
if (parent.balance == 0) {//如果插入后还是平衡树,不用调整
break;
}
if (parent.balance == 2 || parent.balance == -2) {
//出现了平衡的问题,需要修正
fixAfterInsertion(parent);
break;
} else {
parent = parent.parent;
}
}
}
size++;
return true;
}
private void fixAfterInsertion(Node<E> parent) {
if (parent.balance == 2) {
leftBalance(parent);
}
if (parent.balance == -2) {
rightBalance(parent);
}
}
public class Node<E extends Comparable<E>> {
E element;
int balance = 0;//平衡因子
Node<E> left;
Node<E> right;
Node<E> parent;
public Node(E element, Node<E> parent) {
this.element = element;
this.parent = parent;
}
}
}