AVL树是自平衡二叉查找树,其实现自平衡原理为旋转。
代码中对应情形如下:
java实现代码如下:
/** * Created by Administrator on 2017/4/11. */
//AVL树的节点类
class AVLNode<T> {
T element;
AVLNode<T> left;
AVLNode<T> right;
int height;//记录高度
//构造器
public AVLNode(T theElement) {
this(theElement, null, null);
element = theElement;
}
public AVLNode(T theElement, AVLNode<T> left, AVLNode<T> right) {
this.element = theElement;
this.left = left;
this.right = right;
this.height = 0;
}
}
//AVL树
public class AVLTree<T extends Comparable> {
//私有属性
private AVLNode<T> root;//根节点
private int height(AVLNode<T> t) {
return t == null ? -1 : t.height;
}
//构造方法
AVLTree() {
this.root = null;
}
//插入操作
public void insert(T x) {
this.root = insert(x, root);
}
//删除操作
public void remove(T x) {
this.root = remove(x, root);
}
//中序打印操作
public void infPrintTree() {
infPrintTree(root);
System.out.println();
}
//判断是否是AVL树
public boolean isAVL() {
return Math.abs(maxDeep(root.right) - maxDeep(root.left)) < 2;
}
public AVLNode<T> findMax(AVLNode<T> t) {
if (t == null)
throw new RuntimeException("this AVLNode is Empty");
if (t.right == null)
return t;
return findMax(t.right);
}
public AVLNode<T> insert(T x, AVLNode<T> t) {
if (t == null)//传入节点为空,则将该节点作为根节点返回
return new AVLNode<>(x, null, null);
int compareResult = x.compareTo(t.element);
if (compareResult < 0)//传入元素x小于t
t.left = insert(x, t.left);
else if (compareResult > 0)//传入元素x大于t
t.right = insert(x, t.right);
return balance(t);
}
//重新进行平衡
public AVLNode<T> balance(AVLNode<T> t) {
if (t == null)
return t;
if (height(t.left) - height(t.right) > 1) {//左插入
if (height(t.left.left) >= height(t.left.right)) //左左插入 情形1
t = singleRightRotate(t);//右旋
else //左右插入 情形2
t = doubleLeftRightRotate(t);//左右双旋
}
if (height(t.right) - height(t.left) > 1) {//右插入
if (height(t.right.right) >= height(t.right.left)) //右右插入 情形3
t = singleLeftRotate(t);//左旋
else //右左插入 情形4
t = doubleRightLeftRotate(t);//右左双旋
}
t.height = height(t.right) > height(t.left) ? height(t.right) + 1 : height(t.left) + 1;
return t;
}
//右单旋
private AVLNode<T> singleRightRotate(AVLNode<T> t) {
System.out.println("进行右旋转==============>>>");
AVLNode<T> r = t.left;
t.left = r.right;
r.right = t;
t.height = height(t.left) > height(t.right) ? height(t.left) + 1 : height(t.right) + 1;
r.height = height(t.right) > height(r) ? height(t.right) + 1 : height(r) + 1;
return r;
}
//左单旋
private AVLNode<T> singleLeftRotate(AVLNode<T> t) {
System.out.println("进行左旋转==============>>>");
AVLNode<T> r = t.right;
t.right = r.left;
r.left = t;
t.height = height(t.left) > height(t.right) ? height(t.left) + 1 : height(t.right) + 1;
r.height = height(t.left) > height(r) ? height(t.left) + 1 : height(r) + 1;
return r;
}
//右左双旋
private AVLNode<T> doubleRightLeftRotate(AVLNode<T> t) {
System.out.println("进行右左双旋==============>>>");
t.right = singleRightRotate(t.right);
return singleLeftRotate(t);
}
//左右双旋
private AVLNode<T> doubleLeftRightRotate(AVLNode<T> t) {
System.out.println("进行左右双旋==============>>>");
t.left = singleLeftRotate(t.left);
return singleRightRotate(t);
}
public AVLNode<T> remove(T x, AVLNode<T> t) {
if (t == null)//传入节点为空
return t;
int compareResult = x.compareTo(t.element);
if (compareResult < 0)
t.left = remove(x, t.left);
else if (compareResult > 0)
t.right = remove(x, t.right);
else if (t.left != null && t.right != null) { //有两个儿子
t.element = findMax(t.left).element;
remove(t.element, t.left);
} else //单儿子情形
t = t.left == null ? t.right : t.left;
if (t != null)
t.height = height(t.right) > height(t.left) ? height(t.right) + 1 : height(t.left) + 1;
return balance(t);
}
public int maxDeep(AVLNode<T> t) {
int dl, dr;//记录左右树的深度
if (t == null)
return 0;
else {
dl = maxDeep(t.left);
dr = maxDeep(t.right);
}
return dl > dr ? dl + 1 : dr + 1;
}
public void infPrintTree(AVLNode<T> t) {
if (t == null)
return;
infPrintTree(t.left);
System.out.print(t.element + " ");
infPrintTree(t.right);
}
public static void main(String[] args) {
AVLTree avlT = createAVLTree();
System.out.println("是否是AVL树:" + avlT.isAVL());
System.out.println("中序打印出该树===>>>");
avlT.infPrintTree();
avlT.remove(60);
avlT.insert(35);
}
/** * 50 * / \ * 30 60 * / \ * 20 40 * * @return */
private static AVLTree createAVLTree() {
AVLTree<Integer> avlT = new AVLTree();
avlT.insert(50);
avlT.insert(60);
avlT.insert(30);
avlT.insert(40);
avlT.insert(20);
return avlT;
}
}
下图更详细解释左旋和右旋,本图片为转载:
http://blog.csdn.net/collonn/article/details/20128205
原创博文,转载请注明出处。