|
1 | 1 | # AVL Trees
|
2 | 2 |
|
| 3 | + |
| 4 | + |
3 | 5 | An AVL tree is **self-balancing** **binary search tree**.
|
4 | 6 |
|
5 | 7 | Unlike the basic binary search tree, which can exhibit *O(n)* worst case behavior for certain inputs, the AVL tree is always balanced, so search will be *O(log n)*
|
6 | 8 | regardless of the order of the input data.
|
7 | 9 |
|
8 | 10 | ### The Binary Search Tree Invariant
|
9 | 11 |
|
10 |
| -A **binary tree (BST)** is either is either empty (`Empty`) or else it |
| 12 | +A **binary tree (BST)** is either is either empty (Empty) or else it |
11 | 13 | it has a root node and two subtrees (which are binary trees, and can also be empty).
|
12 |
| -The root node `t` has a key `t.key`. Ordinarily every node would also |
13 |
| -hold other data (`t.data`), which the user would like to find by |
14 |
| -searching for the key, `e.g.` search for Student ID Number (key) to find street address (data). |
15 |
| - |
16 |
| -Since the `data` attribute has no impact on |
| 14 | +The root node t has a key t.key. Ordinarily every node would also |
| 15 | +hold other data (t.data), which the user would like to find by |
| 16 | +searching for the key, *e.g.* search for Student ID Number (key) to find street address (data). Since the |
| 17 | +data attribute has no impact on |
17 | 18 | how insertion and search take place, we disregard it in this animation.
|
18 |
| - |
19 | 19 |
|
20 |
| -Note that a newly inserted node will always appear as a leaf |
| 20 | + |
| 21 | +Note that a newly inserted node |
| 22 | +will always appear as a leaf |
21 | 23 | in the tree.
|
| 24 | + |
22 | 25 |
|
23 |
| -In a binary search tree the **BST invariant** is always maintained:\ |
| 26 | +In any binary search tree, the **BST invariant** is always maintained; that is, |
24 | 27 | for each
|
25 |
| -subtree `t`, with root key `t.key`, the left subtree, `t.left`, |
26 |
| -contains no node with key greater than `t.key`, and the right subtree, |
27 |
| -`t.right`, contains no node with key smaller than `t.key`. |
28 |
| - |
29 |
| -### AVL tree balancing |
| 28 | +subtree t, with root key t.key, the left subtree, t.left, |
| 29 | +contains no node with key greater than t.key, and the right subtree, |
| 30 | +t.right, contains no node with key smaller than t.key. |
30 | 31 |
|
31 |
| -An AVL tree is **balanced** when the difference in heights of the left and right subtrees is no greater than `1`. |
32 | 32 |
|
33 | 33 |
|
| 34 | +### Insertion and Tree Balancing |
34 | 35 |
|
35 |
| -The AVL tree preserves the balance of the tree by (1) checking after every insertion to detect |
36 |
| -when the tree has become unbalanced |
37 |
| -and (2) performing one or more **rotation operations** to restore balance when necessary. |
38 |
| -The imbalance may be located at |
39 |
| -any node along the search path from the root of the tree to the newly inserted node, possibly the grandparent of the newly inserted node, or |
40 |
| -possibly |
41 |
| -considerably closer to the root of the tree. |
42 | 36 |
|
| 37 | +**Insertion of a new item** into any binary tree (*e.g.* a BST or an AVL tree) requires |
| 38 | +(1) first the search to find the correct place to insert, then (2) the actual insertion. |
43 | 39 |
|
| 40 | +In the **recursive implementation** of the AVL shown in *AIA*, the first stage, |
| 41 | +determining the insertion point, takes place |
| 42 | +during the recursive *calls* to the insert function, which accumulate on the machine stack. |
44 | 43 |
|
45 |
| -### Imbalance configurations |
46 | 44 |
|
47 |
| -When a new node is inserted in an AVL tree, the tree may become *temporarily* unbalanced. |
48 |
| -A temporarily unbalanced AVL tree takes on one of two **configurations**, *zig-zag* or *zig-zig*. The |
49 |
| -sequence of rotations depends on the configuration around the node where the imbalance is detected. |
| 45 | +The last recursive call *returns* when the new node has been inserted into the tree. |
50 | 46 |
|
| 47 | +In the AVL tree, the height of the subtree rooted at each node is stored in the |
| 48 | +node.During *each* successive *return* from the call to insert, |
| 49 | +the **height of the is updated** and the **tree is checked for balance**. |
| 50 | +When a new node is inserted in an AVL tree, the tree may become *temporarily* unbalanced, that is |
| 51 | +the difference in heights of the left and right subtrees of *any* node is greater than 1. |
51 | 52 |
|
52 |
| -The **zig-zig** configuration has two mirror-image cases: the child and grandchild nodes or subtrees of the unbalanced node are |
53 |
| -either (1) both left subtrees or (2) both right subtrees. The **zig-zag** configuration also has two mirror-image cases: the child and grandchild nodes or subtrees of the unbalanced node are |
54 |
| -either (1) a left subtree and a right subtree or (2) a right subtrees and a left subtree. |
55 | 53 |
|
56 | 54 |
|
| 55 | +If the tree has become unbalanced, |
| 56 | +balance will be restored using one or two **rotation** |
| 57 | +operations, which reduce the height of the unbalanced subtree, while still maintaining the BST invariant. |
57 | 58 |
|
58 |
| - |
| 59 | +### Imbalance configurations and rotations |
59 | 60 |
|
60 |
| -Balance will be restored, using one or two **rotation** |
61 |
| -operations (see below). |
| 61 | +The exact sequence of rotations depends on the configuration around the |
| 62 | +node where the imbalance has been detected. |
62 | 63 |
|
63 |
| -### Insertion and rotation |
| 64 | +There are four possible configurations at the node where an imbalance has been detected: |
| 65 | +(1) *left-left*, where the where the child and grandchild nodes or subtrees of the unbalanced node are |
| 66 | +either both left subtrees, and (2) its mirror image and *right-right*, where the child and grandchild are both right |
| 67 | +subtrees; (3) *left-right*, where there is a left child, with a right subtree as the grandchild, and (4) its mirror image |
| 68 | +*right-left*, where the the right child of the unbalanced node has a left (grand)child. |
64 | 69 |
|
| 70 | +The *left-left* imbalance is restored by a single rotation around the edge between the node |
| 71 | +where the imbalance is detected and its (left) child. Try inserting items 30, 20, then 10 into an AVL tree in *AIA*. You |
| 72 | +will see that the rotation restores balance, and at the same time maintains the binary search invariant. Similarly for |
| 73 | +the *right-right* configuration; try inserting 10, 20, then 30 into the *AIA* AVL tree. |
65 | 74 |
|
66 | 75 |
|
67 | 76 |
|
68 | 77 |
|
69 |
| -**Insertion of a new item** into any binary tree requires (1) first the search to find the correct place to insert, then (2) the actual insertion. |
| 78 | +If you try a larger tree |
| 79 | +XXX Lee -- we should come up with a sample tree here, to show imbalance up the tree from the new insert |
| 80 | +XXX Lee -- we can put URLs here, as you suggested. Should we do that for the really simple ones above? |
70 | 81 |
|
71 |
| -In the **recursive implementation** shown in *AIA*, the first stage, determining |
72 |
| -the insertion point takes place |
73 |
| -during the *"wind up"* stage of the algorithm, where successive recursive *calls to `insert`* are made and accumulate on the machine stack. Search does not |
74 |
| -affect the balance of the tree. During the second stage, however, an imbalance may be introduced into the tree when the new node is actually inserted. The imbalance may be close to the new node, or may be |
75 |
| -considerably farther up the tree toward the root, along the search path. Therefore, during each successive *return* from the call to `insert` |
76 |
| - in the "unwind" stage of the algorithm, the height of the node is updated and the tree is checked for balance. |
| 82 | +As you can see, while |
| 83 | +**rotation** is a **local operation**, involving only 6 pointer reassignments, |
| 84 | +it can affect the balance of the tree overall. |
77 | 85 |
|
78 |
| -When an imbalance is detected, `i.e.` whenever the heights of the subtrees rooted at this node vary by more than `1`, |
79 |
| -a rotation |
80 |
| -or rotations are performed in order to bring the tree back into balance. **Rotation** is a **local operation**, involving only 6 pointer reassignments, |
81 |
| -yet it affects the balance of the tree overall. |
| 86 | +The *left-right* and *right-left* configurations require a double rotation. For the *left-right* configuration, |
| 87 | +first a left rotation at the edge between the child and grandchild of the node, and then a right rotation |
| 88 | +at the edge between the node and its now left child (previously grandchild). The *right-left* configuration requires |
| 89 | +first a right rotation between the child and grandchild, then a left rotation around the node and its (new) right child. |
| 90 | +You can see how these work by inserting 30,10, then 20 into AIA (*left-right*) and 10, 30, 20 (*right-left*). |
82 | 91 |
|
83 |
| -Details of the **rotation**, **single** and **double** rotation are found in the AIA tab `More` for this algorithm. |
84 | 92 |
|
85 |
| - |
86 | 93 |
|
87 | 94 |
|
| 95 | +XXX Lee -- put these exercises here? or integrated into the text, as I've done for left-left above? |
| 96 | +Only one place, not both |
88 | 97 |
|
89 |
| -_**Suggested exercises in AIA**_ |
| 98 | +_**Suggested exercises in AIA**_ |
| 99 | +XXX Lee - I haven't reviewed these recently, waiting for us to agree on desired format first. |
| 100 | +XXX In any case, will be rewritten to obliterate zig-zag and friend |
90 | 101 |
|
91 |
| -To **zig-zig and zig-zag configurations** and **rotation corrections** in AIA: |
92 | 102 |
|
93 | 103 | -For a left-left zig-zig configuration, enter 50, 40, then with the code expanded enter 30, step by step, to see the temporary left-left zig-zig imbalance, followed by a single rotation.\
|
94 | 104 | -For right-right zig-zig and single rotation, enter 30, 40, then slowly 50.\
|
|
0 commit comments