什么是AVL树
AVL树,是最先发明的自平衡二叉树,得名于发明者Adelson-Velsky和Landis。他们在1962年的论文《An algorithm for the organization of information》中发表了它。
AVL树应满足以下条件:
1.首先它是一棵二叉搜索树(BST),即对于任意节点,左节点的值小于根结点的值,右节点的值大于根结点的值。
2.它要么是一棵空树,要么对任意一个节点,其左右子树高度差的绝对值不超过1。
3.对出现不平衡的节点根据不同情况进行旋转。
左旋、右旋balabala(全网最通俗易懂!)
关于左旋右旋已经有许多资料,但这里我力求简单,通俗易懂,讲清楚左旋右旋,在此给出旋转三部曲。
Step1:判断类型。有四种类型,RR,LL,RL,LR。它们的含义是出现问题的节点相对于根结点的位置,RR意味着出现问题的节点是根结点右子树的右子树,LR就是根结点左子树的右子树。
Step2:分而治之。对于RR和LL,RL和LR采用不同策略。
Step3:对于RR和LL,采用鸠占鹊巢的方式;对于LR和RL,采用甩锅的方式。
详细细节请见B站视频:AVL树-从入门到入土
Java代码实现
定义节点类
/**
* define Node class
*/
private static class AvlNode<T> {
T element;
int height;
AvlNode<T> left;
AvlNode<T> right;
public AvlNode(T element) {
this(element, null, null);
}
public AvlNode(T element, AvlNode<T> left, AvlNode<T> right) {
this.element = element;
this.left = left;
this.right = right;
this.height = 0;
}
}
判断旋转类型
/**
* Choose rotate type to achieve balance
*/
private AvlNode<T> balance(AvlNode<T> t) {
if (t == null) {
return t;
}
if (height(t.left) - height(t.right) > ALLOWED_IMBALANCE) {
if (height(t.left.left) >= height(t.left.right)) {
t = rotateWithLeftChild(t);
} else {
t = doubleWithLeftChild(t);
}
} else if (height(t.right) - height(t.left) > ALLOWED_IMBALANCE) {
if (height(t.right.right) >= height(t.right.left)) {
t = rotateWithRightChild(t);
} else {
t = doubleWithRightChild(t);
}
}
t.height = Math.max(height(t.left), height(t.right)) + 1;
return t;
}
完整代码
public class AvlTree<T extends Comparable<? super T>> {
/**
* define Node class
*/
private static class AvlNode<T> {
T element;
int height;
AvlNode<T> left;
AvlNode<T> right;
public AvlNode(T element) {
this(element, null, null);
}
public AvlNode(T element, AvlNode<T> left, AvlNode<T> right) {
this.element = element;
this.left = left;
this.right = right;
this.height = 0;
}
}
private static final int ALLOWED_IMBALANCE = 1;
private AvlNode<T> root;
public void insert(T x) {
root = insert(x, root);
}
public void remove(T x) {
root = remove(x, root);
}
public T findMin() {
return findMin(root).element;
}
private int height(AvlNode<T> t) {
return t == null ? -1 : t.height;
}
/**
* insert Node
*
* @param x Node for inserting
* @param t father Node
*/
private AvlNode<T> insert(T x, AvlNode<T> t) {
// if root is empty,set x as root
if (t == null) {
return new AvlNode(x);
}
int compareResult = x.compareTo(t.element);
// if x < root, put x in the left
if (compareResult < 0) {
t.left = insert(x, t.left);
} else if (compareResult > 0) {
// if x < root, put x in the right
t.right = insert(x, t.right);
} else {
// if they are equal, update
}
return balance(t);
}
/**
* remove Node
*
* @param x Node for removing
* @param t father Node
*/
private AvlNode<T> remove(T x, AvlNode<T> t) {
if (t == null) {
return t;
}
int compareResult = x.compareTo(t.element);
// x < root
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) {
// find the min in tne right tree
t.element = findMin(t.right).element;
// t的右节点为原来的右节点删去最小值
t.right = remove(t.element, t.right);
}
return balance(t);
}
/**
* find min Node
*/
private AvlNode<T> findMin(AvlNode<T> t) {
if (t == null) {
return null;
} else if (t.left == null) {
return t;
}
return findMin(t.left);
}
/**
* Choose rotate type to achieve balance
*/
private AvlNode<T> balance(AvlNode<T> t) {
if (t == null) {
return t;
}
if (height(t.left) - height(t.right) > ALLOWED_IMBALANCE) {
if (height(t.left.left) >= height(t.left.right)) {
t = rotateWithLeftChild(t);
} else {
t = doubleWithLeftChild(t);
}
} else if (height(t.right) - height(t.left) > ALLOWED_IMBALANCE) {
if (height(t.right.right) >= height(t.right.left)) {
t = rotateWithRightChild(t);
} else {
t = doubleWithRightChild(t);
}
}
t.height = Math.max(height(t.left), height(t.right)) + 1;
return t;
}
/**
* RR rotate type
*/
private AvlNode<T> rotateWithRightChild(AvlNode<T> k2) {
AvlNode<T> k1 = k2.right;
k2.right = k1.left;
k1.left = k2;
k2.height = Math.max(height(k2.right), height(k2.left)) + 1;
k1.height = Math.max(height(k1.right), k2.height) + 1;
return k1;
}
/**
* LL rotate type
*/
private AvlNode<T> rotateWithLeftChild(AvlNode<T> k2) {
AvlNode<T> k1 = k2.left;
k2.left = k1.right;
k1.right = k2;
k2.height = Math.max(height(k2.right), height(k2.left)) + 1;
k1.height = Math.max(height(k1.left), k2.height) + 1;
return k1;
}
// RL rotate type
private AvlNode<T> doubleWithRightChild(AvlNode<T> k3) {
k3.right = rotateWithLeftChild(k3.right);
return rotateWithRightChild(k3);
}
// LR rotate type
private AvlNode<T> doubleWithLeftChild(AvlNode<T> k3) {
k3.left = rotateWithRightChild(k3.left);
return rotateWithLeftChild(k3);
}
public boolean isEmpty() {
return root == null;
}
/**
* print Tree
*/
public void printTree() {
if (isEmpty()) {
System.out.println("节点为空");
} else {
printTree(root);
}
}
public void printTree(AvlNode<T> t) {
if (t != null) {
System.out.print(t.element);
if (t.left != null) {
System.out.print(" 左节点" + t.left.element);
}
if (t.right != null) {
System.out.print(" 右节点" + t.right.element);
}
System.out.println();
printTree(t.left);
printTree(t.right);
}
}
public static void main(String[] args) {
AvlTree test = new AvlTree();
test.insert(6);
test.insert(2);
test.insert(7);
test.insert(1);
test.insert(4);
test.insert(3);
test.printTree();
}
}
测试用例结果
相关面试题
待补充