download

AVL TREES
AVL Tree
• AVL trees are balanced.
• AVL Trees
• An AVL Tree is a binary search tree such that for
every internal node v of T, the heights of the children
of v can differ by at most 1.
• An example of an AVL tree where the heights are
shown next to the nodes:
4
44
2
3
17
78
1
2
32
1
88
50
1
48
AVL Trees
9.1
1
AVL Trees
Height of an AVL Tree
9.2
Insertion
• Proposition: The height of an AVL tree T storing n
keys is O(log n).
• Justification: The easiest way to approach this
problem is to try to find the minimum number of
internal nodes of an AVL tree of height h: n(h).
• A binary search tree T is called balanced if for every
node v, the height of v’s children differ by at most
one.
• Inserting a node into an AVL tree involves
performing an expandExternal(w) on T, which
changes the heights of some of the nodes in T.
• We see that n(1) = 1 and n(2) = 2
• for n 3, an AVL tree of height h with n(h) minimal
contains the root node, one AVL subtree of height n1 and the other AVL subtree of height n-2.
• i.e. n(h) = 1 + n(h-1) + n(h-2)
• If an insertion causes T to become unbalanced, we
travel up the tree from the newly created node until
we find the first node x such that its grandparent z is
unbalanced node.
• Since z became unbalanced by an insertion in the
subtree rooted at its child y,
height(y) = height(sibling(y)) + 2
• Knowing n(h-1) > n(h-2), we get n(h) > 2n(h-2)
- n(h) > 2n(h-2)
- n(h) > 4n(h-4)
...
- n(h) > 2in(h-2i)
• To rebalance the subtree rooted at z, we must
perform a restructuring
- we rename x, y, and z to a, b, and c based on the
order of the nodes in an in-order traversal.
- z is replaced by b, whose children are now a and c
whose children, in turn, consist of the four other
subtrees formerly children of x, y, and z.
• Solving the base case we get: n(h) 2h/2-1
• Taking logarithms: h < 2log n(h) +2
• Thus the height of an AVL tree is O(log n)
AVL Trees
62
9.3
AVL Trees
9.4
Insertion (contd.)
Restructuring
• Example of insertion into an AVL tree.
Oh no, unbalanced!
5
44
• The four ways to rotate nodes in an AVL tree,
graphically represented:
z
2
17
3
1
32
1
4
2
1
3
1
48
7
78
2y
50
1
- Single Rotations:
64
62
88
x
a=z
a=z
T3
T0
T1
44
17
2
1
32
1
1
48
62
2y
50
3
c=z
78
54
b=y
c=z
a=x
T2
T0
7
T2
a=x
T3
2
T1
single rotation
b=y
z6
5
1
T0
T2
Whew, balanced now.
4 x
3
2
T3
T3
T2
4
c=x
c=x
5
54
T0
b=y
single rotation
b=y
T1
1
T3
T2
T1
T0
88
T2
T0
T1
T3
AVL Trees
9.5
AVL Trees
Restructuring (contd.)
Restructure Algorithm
- double rotations:
Algorithm restructure(x):
Input: A node x of a binary search tree T that has both
a parent y and a grandparent z
Output: Tree T restructured by a rotation (either
single or double) involving nodes x, y, and z.
double rotation
a=z
b=x
a=z
c=y
1: Let (a, b, c) be an inorder listing of the nodes x, y,
and z, and let (T0, T1, T2, T3) be an inorder listing
of the the four subtrees of x, y, and z not rooted at x,
y, or z
2. Replace the subtree rooted at z with a new subtree
rooted at b
3. Let a be the left child of b and let T0, T1 be the left
and right subtrees of a, respectively.
4. Let c be the right child of b and let T2, T3 be the left
and right subtrees of c, respectively.
c=y
b=x
T0
T3
T2
T0
T2
T1
T3
T1
double rotation
c=z
9.6
b=x
c=z
a=y
a=y
b=x
T3
T0
T2
T3
T2
T1
T0
T1
AVL Trees
9.7
AVL Trees
9.8
Cut/Link Restructure Algorithm
• Let’s go into a little more detail on this algorithm...
• Any tree that needs to be balanced can be grouped
into 7 parts: x, y, z, and the 4 trees anchored at the
children of those nodes (T0-3)
Cut/Link Restructure Algorithm
• Number the 7 parts by doing an in-order-traversal.
(note that x,y, and z are now renamed based upon
their order within the traversal)
z
44
y
17
62
T0
1
x
50
44
y (b) 4
17
78
54
48
2z (a)
62
3
T2
T0
78
5
54
48
88
7
T2
T3
T1
x (c)6
50
88
T3
T1
• Make a new tree which is balanced and put the 7
parts from the old tree into the new tree so that the
numbering is still correct when we do an in-ordertraversal of the new tree.
• This works regardless of how the tree is originally
unbalanced.
• Let’s see how it works!
AVL Trees
9.9
Cut/Link Restructure Algorithm
• Now create an Array, numbered 1 to 7 (the 0th
element can be ignored with minimal waste of
space)
AVL Trees
9.10
Cut/Link Restructure Algorithm
• Now cut x,y, and z in that order
(child,parent,grandparent) and place them in their
inorder rank in the array.
T0
1
2
3
4
5
6
7
1
• Cut() the 4 T trees and place them in their inorder
rank in the array.
T0
1
AVL Trees
T1
2
3
T2
4
5
T1
62
2
3
4
b T2
5
78
6
c T
3
7
• Now we can re-link these subtrees to the main tree.
• Link in rank 4 (b) where the subtree’s root formerly
was
T3
6
a
44
4b
7
62
9.11
AVL Trees
9.12
Cut/Link Restructure Algorithm
Link in ranks 2 (a) and 6 (c) as 4’s children.
Cut/Link Restructure Algorithm
• Finally, link in ranks 1,3,5, and 7 as the children of 2
and 6.
4b
4y
62
a
2 44
c
78
62
6
z
x
2 44
1
17
3
78
5
50
54
48
6
88
7
T2
T3
T0
T1
• Now you have a balanced tree!
AVL Trees
9.13
AVL Trees
Cut/Link Restructure algorithm
9.14
Removal
• This algorithm for restructuring has the exact same
effect as using the four rotation cases discussed
earlier.
• We can easily see that performing a
removeAboveExternal(w) can cause T to become
unbalanced.
• Advantages: no case analysis, more elegant
• Let z be the first unbalanced node encountered while
travelling up the tree from w. Also, let y be the child
of z with the larger height, and let x be the child of y
with the larger height.
• Disadvantage: can be more code to write
• Same time complexity
• We can perform operation restructure(x) to restore
balance at the subtree rooted at z.
• As this restructuring may upset the balance of
another node higher in the tree, we must continue
checking for balance until the root of T is reached.
AVL Trees
9.15
AVL Trees
9.16
Removal (contd.)
Removal (contd.)
• example of deletion from an AVL tree:
z
Oh no, unbalanced!
4
44
y
1
17
x
T0
0
1
y
78
17
50
1
T0
T2
3
T1
4
17
x
78
Whew, balanced now.
z
y
17
1
48
88
3
62
1
1
1
54
x
44
1
50
48
2
2
0
1
T3
50
44
2
1
88
T2
4
62
1
2
32
Whew, balanced now.
z
78
0
54
48
T3
T1
y
3
1
1
88
32
62
x
2
2
54
48
4
1
2
1
44
3
62
50
• example of deletion from an AVL tree
Oh no, unbalanced!
z
54
0
78
1
88
T2
T0
2
T0
T3
T1
T2
T3
T1
AVL Trees
9.17
AVL Trees
Implementation
9.18
Implementation (contd.)
public class SimpleAVLTree
extends SimpleBinarySearchTree
implements Dictionary {
• A Java-based implementation of an AVL tree
requires the following node class:
public class AVLItem extends Item {
int height;
public SimpleAVLTree(Comparator c) {
super(c);
T = new RestructurableNodeBinaryTree();
}
private int height(Position p) {
if (T.isExternal(p))
return 0;
else
return ((AVLItem) p.element()).height();
}
private void setHeight(Position p) { // called only
AVLItem(Object k, Object e, int h) {
super(k, e);
height = h;
}
public int height() {
return height;
}
// if p is internal
public int setHeight(int h) {
int oldHeight = height;
height = h;
return oldHeight;
}
((AVLItem) p.element()).setHeight
(1 + Math.max(height(T.leftChild(p)),
height(T.rightChild(p))));
}
}
AVL Trees
9.19
AVL Trees
9.20
Implementation (contd.)
Implementation (contd.)
private void rebalance(Position zPos) {
private boolean isBalanced(Position p) {
// test whether node p has balance factor
// between -1 and 1
//traverse the path of T from zPos to the root;
//for each node encountered recompute its
//height and perform a rotation if it is
//unbalanced
int bf = height(T.leftChild(p)) - height(T.rightChild(p));
return ((-1 <= bf) && (bf <= 1));
while (!T.isRoot(zPos)) {
zPos = T.parent(zPos);
setHeight(zPos);
if (!isBalanced(zPos)) { // perform a rotation
Position xPos = tallerChild(tallerChild(zPos));
zPos = ((RestructurableNodeBinaryTree)
T).restructure(xPos);
setHeight(T.leftChild(zPos));
setHeight(T.rightChild(zPos));
setHeight(zPos);
}
private Position tallerChild(Position p) {
// return a child of p with height no
// smaller than that of the other child
if(height(T.leftChild(p)) >= height(T.rightChild(p)))
return T.leftChild(p);
else
return T.rightChild(p);
}
}
}
}
AVL Trees
9.21
Implementation (contd.)
public void insertItem(Object key, Object element)
throws InvalidKeyException {
super.insertItem(key, element);// may throw an
// InvalidKeyException
Position zPos = actionPos; // start at the
// insertion position
T.replace(zPos, new AVLItem(key, element, 1));
rebalance(zPos);
}
public Object remove(Object key)
throws InvalidKeyException {
Object toReturn = super.remove(key); // may throw
// an InvalidKeyException
if (toReturn != NO_SUCH_KEY) {
Position zPos = actionPos; // start at the
// removal position
rebalance(zPos);
}
return toReturn;
}
}
AVL Trees
9.23
AVL Trees
9.22