|
1 | 1 | # AVL Trees
|
2 | 2 |
|
3 |
| -An AVL tree is **self-balancing** binary search tree. |
| 3 | +An AVL tree is **self-balancing** **binary search tree**. |
4 | 4 |
|
5 |
| -Because the AVL tree is always balanced, search will be *O(log n)*, |
6 |
| -no matter what the order of the input data. |
| 5 | +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 | +regardless of the order of the input data. |
7 | 7 |
|
8 |
| -### Binary Search Trees |
| 8 | +### The Binary Search Tree Invariant |
9 | 9 |
|
10 |
| -A **binary tree** is either is either empty (`Empty`) or else it |
11 |
| - it has a root node and two subtrees (which are binary trees). |
12 |
| - The root node `t` has a key `t.key`. Ordinarily it would also |
13 |
| - hold other data (`t.data`), which the user would like to find by |
14 |
| - searching for the key. Since this attribute has no impact on |
15 |
| - how insertion and search take place, we disregard it here. |
16 |
| - Note that a newly inserted node will always appear as a leaf |
17 |
| - in the tree. |
| 10 | +A **binary tree (BST)** is either is either empty (`Empty`) or else it |
| 11 | +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 |
| 17 | +how insertion and search take place, we disregard it in this animation. |
| 18 | + |
| 19 | + |
| 20 | +Note that a newly inserted node will always appear as a leaf |
| 21 | +in the tree. |
18 | 22 |
|
19 |
| -In a **binary search tree (BST)** the BST invariant is always maintained:\ |
| 23 | +In a binary search tree the **BST invariant** is always maintained:\ |
20 | 24 | for each
|
21 |
| - subtree t, with root key t.key, the left subtree, t.left, |
22 |
| - contains no node with key greater than k, and the right subtree, |
23 |
| - t.right, contains no node with key smaller than k. |
| 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 |
| 30 | + |
| 31 | +An AVL tree is **balanced** when the difference in heights of the left and right subtrees is no greater than `1`. |
| 32 | + |
24 | 33 |
|
25 |
| -### AVL tree balancing |
26 | 34 |
|
27 | 35 | The AVL tree preserves the balance of the tree by (1) checking after every insertion to detect
|
28 | 36 | when the tree has become unbalanced
|
29 |
| -and (2) performing one or more rotation operations to restore balance when necessary. |
30 |
| -Unbalanced is defined as a difference of more than `1` between the heights of the left and right subtrees. |
| 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 | + |
31 | 43 |
|
32 |
| -(Here **MAYBE insert small pictures, thumbnails?** to show -- unbalanced at gp of new node, |
33 |
| -and also balanced at gp but unblanaced at ggp.) |
34 | 44 |
|
35 |
| -A temporarily unbalanced AVL tree takes on one of two configurations, *zig-zag* or *zig-zig*. The |
| 45 | +### Imbalance configurations |
| 46 | + |
| 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 |
36 | 49 | sequence of rotations depends on the configuration around the node where the imbalance is detected.
|
37 | 50 |
|
38 |
| -### Zig-zig case |
39 | 51 |
|
40 |
| -The *zig-zig* configuration has two mirror-image cases: the child and grandchild nodes or subtrees of the unbalanced node are |
41 |
| -either (1) both left subtrees or (2) both right subtrees. |
| 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 | + |
42 | 56 |
|
43 | 57 |
|
44 |
| -## The left-left case |
| 58 | + |
| 59 | + |
| 60 | +Balance will be restored, using one or two **rotation** |
| 61 | +operations (see below). |
| 62 | + |
| 63 | +### Insertion and rotation |
| 64 | + |
45 | 65 |
|
46 |
| -If the new key was added to the left child of a left child (the |
47 |
| -*left-left* case), the balance can be |
48 |
| -restored with a single _**Right Rotation**_ operation. |
49 | 66 |
|
50 |
| -Note that the imbalance may be located further up the tree than the immediate grandparent of the newly inserted node: |
51 | 67 |
|
52 |
| -**Insert very small diagrams showing (a) imbalance of the grandparent-parent and (b) imbalance of the great grandparent** |
53 |
| -*Note that all diagrams should hae nodes in BST order, and where the subtrees are not necessarily single nodes, represent them as subtree-triangles* |
54 |
| -*Have arrow showing which node is not in blanace* |
55 | 68 |
|
56 |
| -In the diagrams below, t6 is the node where the imbalance is noted. |
| 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. |
57 | 70 |
|
58 |
| -As shown in the diagram below, t6 is the node at which the imbalance has been noted, and t2 is its left child. The clockwise rotation to restore balance makes t2 the parent of t6, while t6 is the *right* child of t2. Additionally, since t2 already had t4 as its right child, t4 is moved to become the left child of t6. Note that the BST invariant is preserved: t4, is bigger than t2, and is also smaller than t6. The rotation reduces the distance from the root to t1 (where the new node was added), so the tree is now |
| 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. |
59 | 77 |
|
60 |
| -**I think there is something wrong with this diagram and the explanation** |
61 |
| -**unless t4 is empty, then the tree was already unbalance before 1 was added??** |
| 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. |
| 82 | + |
| 83 | +Details of the **rotation**, **single** and **double** rotation are found in the AIA tab `More` for this algorithm. |
62 | 84 |
|
63 | 85 |
|
64 | 86 |
|
65 |
| -, as explained in the diagram The 6 and 4 nodes and the edge between them rotate clockwise, and |
66 |
| -the 5 node changes parents from 4 to 6. This reduces the distance from |
67 |
| -the root to the 1 (where the new node was added), restoring the balance |
68 |
| -(the distance to the node rooted at 7 is increased but this does not |
69 |
| -cause the AVL tree balance condition to be violated). Right rotation is |
70 |
| -done by calling rightRotate(t6), where t6 is the tree rooted at 6. |
71 |
| - |
72 |
| -{width=120,height=50} This picture is from Greek for Geeks, and is only a placeholder to show proof of concept inserting diagrams, and to check things like size and cropping. |
73 |
| - |
74 |
| - |
75 |
| -{width=120,height=50} This picture is from Greek for Geeks, and is only a placeholder to show proof of concept inserting diagrams, and to check things like size and cropping. |
76 |
| - |
77 |
| -Test comment |
78 |
| - |
79 |
| -[This shouldn't be seen if the comment signal is correct]: #) |
80 |
| - |
81 |
| -**Check whether the numbering here is still the same in the animation** |
82 |
| -**Note I have added a link to the parent of t6 -- check, since the pointer to the left child of this anonymous node needs to be changed, have we given it a number?** |
83 |
| - |
84 |
| -**Lee - is t4 empty in this case? If not, then the tree would already have been unbalanced previously, when t4 was added??** |
85 |
| - |
86 |
| -``` |
87 |
| - / / |
88 |
| - t6 t2 |
89 |
| - / \ Right Rotation / \ |
90 |
| - t2 7 - - - - - - - > 1 t6 |
91 |
| - / \ < - - - - - - - / \ |
92 |
| - 1 t4 Left Rotation t4 7 |
93 |
| -``` |
94 |
| - |
95 |
| -**9 Jan 4PM I haven't gone beyond this** |
96 |
| - |
97 |
| - |
98 |
| -## The right-right case |
99 |
| - |
100 |
| -The right-right case is the exact opposite. If the tree on the right in |
101 |
| -the diagram above is too unbalanced due to insertion into the subtree |
102 |
| -rooted at 7, we can call rightRotate(t2) to lift that subtree and lower |
103 |
| -the 1 subtree. |
104 |
| - |
105 |
| -## The left-right case (double rotation) |
106 |
| - |
107 |
| -If the new key was added to the right child of the left child (the |
108 |
| -left-right case) and the resulting tree is too unbalanced, the balance can be |
109 |
| -restored with a left rotation at node 2 followed by a right rotation at |
110 |
| -node 6. |
111 |
| -``` |
112 |
| - 6 Rotate 6 Rotate 4 |
113 |
| - / \ left at 2 / \ right at 6 / \ |
114 |
| - 2 7 - - - - - > 4 7 - - - - - > 2 6 |
115 |
| - / \ / \ / \ / \ |
116 |
| - 1 4 2 5 1 3 5 7 |
117 |
| - / \ / \ |
118 |
| - 3 5 1 3 |
119 |
| -``` |
120 |
| -Nodes in the subtree rooted at 4 (where the extra element was added, |
121 |
| -making the tree unbalanced) are moved closer to the root. |
122 |
| -Trees rooted at 1, 3, 5 and 7 are not affected, except the distances from |
123 |
| -the root of 3, 5 and 7 are changed by one, affecting the overall balance. |
124 |
| - |
125 |
| -## The right-left case (double rotation): |
126 |
| - |
127 |
| -If the new key was added to the left child of the right child (the |
128 |
| -right-left case) and the resulting tree is too unbalanced, it is a mirror |
129 |
| -image of the left-right case: |
130 |
| - |
131 |
| -``` |
132 |
| - 2 Rotate 2 Rotate 4 |
133 |
| - / \ right at 6 / \ left at 2 / \ |
134 |
| - 1 6 - - - - - > 1 4 - - - - - > 2 6 |
135 |
| - / \ / \ / \ / \ |
136 |
| - 4 7 3 6 1 3 5 7 |
137 |
| - / \ / \ |
138 |
| - 3 5 5 7 |
139 |
| -``` |
| 87 | + |
| 88 | + |
| 89 | +_**Suggested exercises in AIA**_ |
| 90 | + |
| 91 | +To **zig-zig and zig-zag configurations** and **rotation corrections** in AIA: |
| 92 | + |
| 93 | +-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 | +-For right-right zig-zig and single rotation, enter 30, 40, then slowly 50.\ |
| 95 | +-For left-right zig-zag and double rotation, enter 50, 30, then slowly 40.\ |
| 96 | +-For right-left zig-zag and double rotation enter 30, 50, then slowly 40. |
| 97 | + |
| 98 | +In the above exercises the imbalance takes place near the newly inserted node. To see how an imbalance can quite remote, and how this is handled: |
| 99 | + |
| 100 | + |
| 101 | +For imbalance further up the tree from the newly inserted node: |
| 102 | +-Input 60,40,80,20,50,70,90,15,25,45,55,10. Insert 60..55 quickly (use the speed bar and collapse the pseudocode), then expand the pseudocode and proceed step by step as 10 is inserted. |
| 103 | + |
| 104 | + |
| 105 | + |
| 106 | + |
| 107 | + |
| 108 | + |
| 109 | + |
| 110 | + |
| 111 | + |
| 112 | + |
| 113 | + |
0 commit comments