AVL树简介
AVL树是被最先发明的一种较为简单的平衡二叉查找树。
它的特点是:
1.本身首先是一棵二叉查找树。
2.带有平衡条件:每个结点的左右子树的高度之差的绝对值(平衡因子LoadFactor)最多为1。
(根结点的高度最高,最底层的叶结点的高度最低且为1。由叶结点向上到树的根结点,树的高度不断增加。例如,只有一个结点的树,该结点即是根结点,高度为1;有两个结点的树,叶结点的高度为1,根结点的高度为2。一棵树总的高度与深度相同,但是树中同一个结点的高度与深度互补。)
优点:
无论是查找、插入或删除,它在最坏情况下的时间复杂度均为O(logN),空间复杂度为O(N)
缺点:引入了平衡因子的概念之后,需要封装更多的信息。其实测复杂度与理论值尚有差距。
上面的两张图片,左边的是AVL树,它的任何节点的两个子树的高度差别都小于等于1;而右边的不是AVL树,因为结点7的两颗子树的高度相差为2(以2为根节点的树的高度是3,而以8为根节点的树的高度是1)。
AVL树的查找、插入和删除在平均和最坏情况下都是O(logn)。
在对AVL树进行插入或删除一个结点之后,会可能导致树中某个结点的左右子树的高度之差超过1,从而破坏了AVL树的适度平衡。因此,为了让它重新回到平衡状态,需要采取额外的操作。
重平衡操作
在AVL树中进行插入或者删除一个结点之后,可能会导致AVL树的失衡。AVL树失衡的状态一共可以分为以下四种:
1、LL情况
如下图所示,进行一次右旋转RotateRight就可以恢复树的平衡。
//LL情况
private Node rotateRight(Node node) {
Node temp = node.left;
node.left = temp.right;
temp.right = node;
node.height = max(height(node.left), height(node.right)) + 1;
temp.height = max(height(temp.left), height(temp.right)) + 1;
return temp;
}
2、RR情况
如下图所示,进行一次左旋转RotateLeft就可以恢复树的平衡。
//RR情况
private Node rotateLeft(Node node) {
Node temp = node.right;
node.right = temp.left;
temp.left = node;
node.height = max(height(node.left), height(node.right)) + 1;
temp.height = max(height(temp.left), height(temp.right)) + 1;
return temp;
}
3、LR情况
如下图所示,先对1结点进行一次左旋转,再对3结点进行一次右旋转就可以恢复树的平衡。
//LR情况
private Node LR(Node node) {
node.left = rotateLeft(node.left);
return rotateRight(node);
}
4、RL情况
如下图所示,先对3结点进行一次右旋转,再对1结点进行一次左旋转就可以恢复树的平衡。
//RL情况
private Node RL(Node node) {
node.right = rotateRight(node.right);
return rotateLeft(node);
}
AVL树完整Java实现
public class AVLTree<Key extends Comparable<Key>, Value> {
private Node root;
private class Node {
Key key;
Value val;
int height;
Node left,right;
public Node(Key key, Value val, int height) {
this.key = key;
this.val = val;
this.height = height;
}
}
public void put(Key key, Value val) {
root = put(root, key, val);
}
private Node put(Node node, Key key, Value val) {
if(node == null)
return new Node(key, val, 1);
int cmp = key.compareTo(node.key);
if(cmp > 0) {
node.right = put(node.right, key, val);
if(height(node.right) - height(node.left) == 2) {
if(key.compareTo(node.right.key) > 0)
node = rotateLeft(node);
else
node = RL(node);
}
} else if(cmp < 0) {
node.left = put(node.left, key, val);
if(height(node.left) - height(node.right) == 2) {
if(key.compareTo(node.left.key) < 0)
node = rotateRight(node);
else
node = LR(node);
}
} else {
node.val = val;
}
node.height = max(height(node.left), height(node.right)) + 1;
return node;
}
public Value delete(Key key) {
Node node = delete(root, key);
if(node == null)
return null;
return node.val;
}
private Node delete(Node node, Key key) {
if(key == null || node == null)
return null;
return node;
}
//LL情况
private Node rotateRight(Node node) {
Node temp = node.left;
node.left = temp.right;
temp.right = node;
node.height = max(height(node.left), height(node.right)) + 1;
temp.height = max(height(temp.left), height(temp.right)) + 1;
return temp;
}
//RR情况
private Node rotateLeft(Node node) {
Node temp = node.right;
node.right = temp.left;
temp.left = node;
node.height = max(height(node.left), height(node.right)) + 1;
temp.height = max(height(temp.left), height(temp.right)) + 1;
return temp;
}
//LR情况
private Node LR(Node node) {
node.left = rotateLeft(node.left);
return rotateRight(node);
}
//RL情况
private Node RL(Node node) {
node.right = rotateRight(node.right);
return rotateLeft(node);
}
//以node为根结点的子树的高度
private int height(Node node) {
if(node == null)
return 0;
return node.height;
}
private int max(int a, int b) {
return a > b ? a : b;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
}
}