还真是第一次用Java来实现一棵AVL树 要考虑方方面面啊 好累 写了2天 顺便复习一下AVL树 废话不多说 :
import java.nio.file.attribute.AclEntryType;
import java.util.Iterator;
import java.util.NoSuchElementException;
/**
* Created by albert.bai on 2014/11/6.
* AVL树是一个带有平衡条件的平衡二叉树,他的左右子树都是平衡二叉树
* 左右子树的高度差绝对值小于1;
* 平衡因子:左子树高度减去右子树高度
* 平衡二叉树是对二叉排序树的优化,防止二叉排序树在最坏情况下平均查找时间为n,
* 二叉排序树最坏情况下形如一个单链表
* 平衡二叉树查找元素的次数不超过树的深度,时间复杂度为logN;
*/
public class AVLTree<E> {
private static final int LH = 1;
private static final int EH = 0;
private static final int RH = -1;
static class Entry<E> {
E element;
Entry<E> parent;
Entry<E> left;
Entry<E> right;
int balance = EH; //平衡因子,只能为1或0或-1
public Entry(E element, Entry<E> parent) {
this.element = element;
this.parent = parent;
}
public Entry() {
}
@Override
public String toString() {
return element + "BF=" + balance;
}
}
/**
* 根节点
*/
private Entry<E> root = null;
/**
* 树中元素个数
*/
private int size = 0;
public AVLTree() {
}
public int size() {
return size;
}
/**
* @param p 最小旋转树的根节点
* 左旋后p移到p的左子树处,p的右子树B现在为根节点
* B的左子变为P的右子树
*/
private void rotateLeft(Entry<E> p) {
System.out.println("绕" + p + "左旋");
if (p != null) {
Entry<E> R = p.right;
p.right = R.left; //把p的右子树R 的左节点嫁接过来 不管是否为null
if (R.left != null) {//如果R的左节点不为空 那么将其parent设置为P
R.left.parent = p;
}
R.parent = p.parent; //R现在是根节点了 所以得将原来的根节点p的parent 嫁接给R
if (p.parent == null) { //如果P的parent为null 那么R就是root了
root = R;
} else if (p.parent.left == p) {//如果p是p的parent的左子树 那么将p的parent的左子树嫁接给R
p.parent.left = R;
} else if (p.parent.right == p) {//同上
p.parent.right = R;
}
R.left = p;//将p嫁接在R的左子树上
p.parent = R;//当然现在p的parent变成了R了 狸猫换太子
}
}
/**
* @param p 最小旋转树的根节点
* 右旋后p移到p的右子树上,p的左子树L现在为根节点
* L的右子树变为p的左子树
*/
private void rotateRight(Entry<E> p) {
System.out.println("绕" + p.element + "右旋");
if (p != null) {
Entry<E> L = p.left;
p.left = L.right;
if (L.right != null) { //如果L的右节点不是空的,那么将其parent设置为parent
L.right.parent = p;
}
L.parent = p.parent;
if (p.parent == null) {
root = L;
} else if (p.parent.left == p) {
p.parent.left = L;
} else
p.parent.right = L;
L.right = p;
p.parent = L;
}
}
/**
* @param element 传入的节点
* @return true/false
* 1 像二叉搜索树那样,找到要插入的位置,并插入
* 2 从下向上回溯:
* a 修改平衡因子,当插入一个节点后只有root到插入节点的路径上的节点的平衡因子会发生改变
* 当插入的节点在某节点A的左子树时,A的平衡因子为BF+1,右节点是为BF-1
* 判断是在左右子树时只要通过比较其与A的大小比较
* b 在改变平衡因子的同时,找到最近一个平衡因子>2或<2的节点,从这个节点开始调整祖先节点
*/
public boolean add(E element) {
Entry<E> t = root;
if (t == null) {
root = new Entry<E>(element, null);
size = 1;
return true;
}
int cmp;
Entry<E> parent;//保存t的父节点
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);
Entry<E> child = new Entry(element, parent);
if (cmp < 0) {
parent.left = child;
} else {
parent.right = child;
}
//自下向上回溯,查找最近不平衡节点
while (parent != null) {
if (cmp < 0) {
parent.balance++;
} else {
parent.balance--;
}
if (parent.balance == 0) {//此时balence为0 说明左右子树为等高 不需要调整
break;
}
if ((Math.abs(parent.balance) == 2)) {
fixAfterInsertion(parent);
break;
}
parent = parent.parent;
}
size++;
return true;
}
/**
* 调整方法:
* 1 当最小不平衡树的根R的balence为2是说明左子树高于右子树
* 如果R的左子树的根节点BF为1时 右旋;
* 如果R的左子树的根节点BF为-1时 先左旋在右旋;
* 2 反正 亦然
*/
private void fixAfterInsertion(Entry<E> p) {
if (p.balance == 2) {
leftBalence(p);
}
if (p.balance == -2) {
rightBalence(p);
}
}
private boolean leftBalence(Entry<E> t) {//左平衡
boolean heightLower = true;
Entry<E> l = t.left;
switch (l.balance) {
case LH://左高 ,右旋调整,旋转后树的高度减少
t.balance = l.balance = EH;
rotateRight(t);
break;
case RH://右高,分情况调整
Entry<E> rd = l.right;
switch (rd.balance) {
case LH:
t.balance = RH;
l.balance = EH;
break;
case EH:
t.balance = l.balance = EH;
break;
case RH:
t.balance = EH;
l.balance = LH;
break;
}
rd.balance = EH;
rotateLeft(t.left);
rotateRight(t);
break;
case EH://特殊情况 这种情况在添加时不可能发生,但在移除时可能发生
l.balance = RH;
t.balance = LH;
rotateRight(t);
heightLower = false;
break;
}
return heightLower;
}
//反之亦然
private boolean rightBalence(Entry<E> t) {
boolean heightLower = true;
Entry<E> r = t.right;
switch (r.balance) {
case LH:
Entry<E> ld = r.left;
switch (ld.balance) {
case LH:
t.balance = EH;
r.balance = RH;
break;
case EH:
t.balance = r.balance = EH;
break;
case RH:
t.balance = LH;
r.balance = EH;
break;
}
ld.balance = EH;
rotateRight(t.right);
rotateLeft(t);
break;
case RH:
t.balance = r.balance = EH;
rotateLeft(t);
break;
case EH:
r.balance = LH;
t.balance = RH;
rotateLeft(t);
heightLower = false;
break;
}
return heightLower;
}
private Entry<E> getEntry(Object element) {
Entry<E> temp = root;
Comparable<? super E> e = (Comparable<? super E>) element;
int cmp;
while (temp != null) {
cmp = e.compareTo(temp.element);
if (cmp == 0) {
return temp;
} else if (cmp < 0) {
temp = temp.left;
} else {
temp = temp.right;
}
}
return null;
}
public boolean remove(Object o) {
Entry<E> e = getEntry(o);
if (e != null) {
deleteEntry(e);
return true;
}
return false;
}
private void deleteEntry(Entry<E> p) {
size--;
//如果p左右子树都不为空,找到其直接后继,替换p,之后p指向s,删除p就是删除s;
if (p.left != null && p.right != null) {
Entry<E> s = successor(p);
p.element = s.element;
p = s;
}
Entry<E> replacement = (p.left != null ? p.left : p.right);
if (replacement != null) {//左右空其一
replacement.parent = p.parent;
if (p.parent == null) {
root = replacement;
} else if (p == p.parent.left) {
p.parent.left = replacement;
} else
p.parent.right = replacement;
p.left = p.right = p.parent = null;
fixAfterDeletion(replacement);
} else if (p.parent == null) {
root = null;
} else {//左右子树都是空的
fixAfterDeletion(p);
if (p.parent != null) {
if (p == p.parent.left) {
p.parent.left = null;
} else if (p == p.parent.right) {
p.parent.right = null;
}
p.parent = null;
}
}
}
/**
* 中序遍历方式,找到t的直接后继
*
* @param t
* @param <E>
* @return
*/
static <E> Entry<E> successor(Entry<E> t) {
if (t == null) {
return null;
} else if (t.right != null) {
Entry<E> p = t.right;
while (p.left != null) {
p = p.left;
}
return p;
} else {
Entry<E> p = t.parent;
Entry<E> ch = t;
while (p != null && ch == p.right) {
ch = p;
p = p.parent;
}
return p;
}
}
private void fixAfterDeletion(Entry<E> p) {
boolean heightLower = true;
Entry<E> t = p.parent;
Comparable<? super E> e = (Comparable<? super E>) p.element;
int cmp;
while (t != null && heightLower) {
cmp = e.compareTo(t.element);
if (cmp >= 0) {
t.balance++;
} else
t.balance--;
if (Math.abs(t.balance) == 1) {
break;
}
Entry<E> r = t;
if (t.balance == 2) {
heightLower = leftBalence(r);
} else if (t.balance == -2) {
heightLower = rightBalence(r);
}
t = t.parent;
}
}
private class BinarySortIterator implements Iterator<E> {
Entry<E> next;
Entry<E> lastReturned;
public BinarySortIterator() {
Entry<E> s = root;
if (s != null) {
while (s.left != null) {
s = s.left;
}
next = s;//中序遍历的第一个元素
}
}
/**
* Returns {@code true} if the iteration has more elements.
* (In other words, returns {@code true} if {@link #next} would
* return an element rather than throwing an exception.)
*
* @return {@code true} if the iteration has more elements
*/
@Override
public boolean hasNext() {
return next != null;
}
/**
* Returns the next element in the iteration.
*
* @return the next element in the iteration
* @throws NoSuchElementException if the iteration has no more elements
*/
@Override
public E next() {
Entry<E> e = next;
if (e == null) {
throw new NoSuchElementException();
}
next = successor(e);
lastReturned = e;
return e.element;
}
/**
* Removes from the underlying collection the last element returned
* by this iterator (optional operation). This method can be called
* only once per call to {@link #next}. The behavior of an iterator
* is unspecified if the underlying collection is modified while the
* iteration is in progress in any way other than by calling this
* method.
*
* @throws UnsupportedOperationException if the {@code remove}
* operation is not supported by this iterator
* @throws IllegalStateException if the {@code next} method has not
* yet been called, or the {@code remove} method has already
* been called after the last call to the {@code next}
* method
*/
@Override
public void remove() {
if (lastReturned == null) {
throw new IllegalStateException();
}
if (lastReturned.left != null && lastReturned.right != null) {
next = lastReturned;
deleteEntry(lastReturned);
lastReturned = null;
}
}
}
public Iterator<E> iterator() {
return new BinarySortIterator();
}
private int treeHeight(Entry<E> p) {
if (p == null) {
return -1;
}
return 1 + Math.max(treeHeight(p.left), treeHeight(p.right));
}
public static void main(String[] args) {
AVLTree<Integer> avlTree = new AVLTree<Integer>();
avlTree.add(23);
avlTree.add(34);
avlTree.add(56);
avlTree.add(12);
avlTree.add(87);
Iterator<Integer> it = avlTree.iterator();
while (it.hasNext()) {
// it.remove();
System.out.println(it.next());
}
avlTree.remove(23);
Iterator<Integer> it2 = avlTree.iterator();
while (it2.hasNext()) {
System.out.println(it2.next());
}
}
}