AVL树
定义
每个结点的左子树和右子树的高度最多差1的二叉查找树(空树的高度定义为-1)。
最大高度
AVL树的最大高度为1.44log(N+2)-1.328,但是实际上的高度只略大于logN。在高度为h的AVL树中,最少结点数S(h)由S(h)=S(h-1)+S(h-2)+1给出。对于h=0,S(h)=1;h=1,S(h)=2。函数S(h)与斐波那契数密切相关,由此推出高度的界。
插入
在插入以后,只有那些从插入点到根结点的路径上的结点的平衡可能被改变,因为只有这些结点的子树可能发生变化。只需在第一个 这样的结点(即最深的结点)重新平衡这棵树,就能保证整棵树的平衡。
不平衡性分析
我们将必须平衡的结点成为a。由于任意结点最多有两个子结点,因此出现 高度不平衡时只需要a的两颗子树的高度差为 2。主要包含四种情况:
1、对a的左儿子的左子树进行一次插入
2、对a的左儿子的右子树进行一次插入
3、对a的右儿子的左子树进行一次插入
4、对a的右儿子的右子树进行一次插入
调整情形1的单旋转

分析
结点k2不满足 AVL平衡的性质,因为它的左子树比右子树深2层(图中间的几条虚线表示树的各层)。该图所描述的情况只是情形1的一种可能,在插入之前k2满足AVL性质,但在插入之后这种性质被破坏了。子树X已经生长出一层,这使得它比子树Z深出2层。Y不可能与新X在同一水平上,因为那样 k2在插入前就已经失去了平衡了,Y不可能与Z在同一层上,因为那样k1就会是在通向根的路径上破坏AVL平衡条件的第一个结点 。
调整操作
对根结点k2执行右旋转,使得k1子树高度+1,k2子树高度-1
X向上移动了一层,Y停在原来的水平上,而Z下移一层。不仅如此,整个树的新高度恰恰与插入前原树的高度相同,而插入操作却使得子树Z长高了。因此,通向根结点的路径的高度不需要进一步的修正,因而也不需要进一步的旋转。
调整情形2的双旋转

分析
如图k1的右子结点必然非空,可以将它假设为一个根和两颗子树。于是可以将整棵树看成是4棵子树由3个结点链接。如图所示恰好树B和树C中有一棵比D深2层,但是无法 确定哪一棵。可以将B、C子树的高度画成3/2层。
调整操作
为了调整树的高度可以先左旋转树的左子结点k1,再右旋转根结点k3。这样子树B、D的高度-1,子树D的高度+1。整棵树的高度恢复到新增前。
删除
删除操作的分析与插入操作类似,因为可能存在两个子树高度比被删除的子树高度高的场景。调整后树的高度比删除前树的高度变低。因此需要一直往上平衡到根结点。
public class AVLBST<Key extends Comparable<Key>, Value> {
private static final int ALLOWED_IMBALANCE = 1;
private Node root;
public void put(Key key, Value val) {
root = put(key, val, root);
}
private Node put(Key key, Value val, Node x) {
if(x == null) return new Node(key, val, 0);
int cmp = key.compareTo(x.key);
if(cmp < 0) x.left = put(key, val, x.left);
else if(cmp > 0) x.right = put(key, val, x.right);
else x.val = val;
return balance(x);
}
public void delete(Key key) {
root = delete(key, root);
}
private Node delete(Key key, Node x) {
if(x == null) return null;
int cmp = key.compareTo(x.key);
if(cmp < 0) x.left = delete(key, x.left);
else if(cmp > 0) x.right = delete(key, x.right);
else if(x.left != null && x.right != null) {
Node min = min(x.right);
x.right = delete(min.key, x.right);
x.key = min.key;
x.val = min.val;
} else
x = (x.left != null) ? x.left : x.right;
return balance(x);
}
private Node balance(Node x) {
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.right) >= height(t.right.left))
t = rotateWithRightChild(t);
else
t = doubleWithRightChild(t);
}
t.h = Math.max(height(t.left), height(t.right)) + 1;
return t;
}
private Node doubleWithLeftChild(Node x) {
x.left = rotateWithRightChild(x.left);
x = rotateWithLeftChild(x);
return x;
}
private Node doubleWithRightChild(Node x) {
x.right = rotateWithLeftChild(x.right);
x = rotateWithRightChild(x);
return x;
}
private Node rotateWithLeftChild(Node x) {
Node l = x.left;
x.left = l.right;
l.right = x;
x.h = Math.max(height(x.left), height(x.right)) + 1;
l.h = Math.max(height(l.left), height(l.right)) + 1;
return l;
}
private Node rotateWithRightChild(Node x) {
Node r = x.right;
x.right = r.left;
r.left = x;
x.h = Math.max(height(x.left), height(x.right)) + 1;
r.h = Math.max(height(r.left), height(h.right)) + 1;
return r;
}
private int height(Node x) {
if(x == null) return -1;
return x.h;
}
class Node {
Key key;
Value val;
Node left, right;
int h;
public Node(Key key, Value val, int h) {
this.key = key;
this.val = val;
this.h = h;
}
}
}

浙公网安备 33010602011771号