@@ -10,93 +10,17 @@ renamed according to new structure
1010\\Note{ modified from BST - best check actual running BST Real code for
1111search and use that XXX still needs unification with BST
1212
13- Terminology (might change???)
14- For BST we confound t.key and t->key, eg, we have c <- c.left. Its not
15- too bad with BST code, but here the code gets more complex, with
16- multiple levels of the tree involved using c.left.left is a bit too
17- dodgy(?). So we use:
18-
19- root(t) = (*t)
20- left(t) = *(t->left) (or Empty) ?????
21- right() similarly
22- root(t).key, root(t).height, etc
23- left(t).height, etc ???
24- XXX maybe use height(t), key(t), left(t), right(t)
13+ Terminology (changed, might change again but this looks OK I reckon)
14+ XXX should change BST (et al?) so it is consistent
15+ We brush over the fact that pointers are used and use record notation
16+ "." where C "->" would be used (implicit dereference of pointer).
17+ t <- t.left etc is the most dubious looking code if we think of records
18+ and not pointers.
19+ Basically t = Empty or, otherwise, t.key, t.left and t.right exist (we
20+ don't explicitly use t.height in the code but could). Creating a new
21+ singleton tree is done in a single step.
2522\\Note}
2623
27- \\Overview{ A binary tree is either is either empty (Empty) or else it
28- it has a root node and two subtrees (which are binary trees).
29- The root node t has a key, t.key. Ordinarily it would also
30- hold other data (t.data), which the user would like to find by
31- searching for the key. Since this attribute has no impact on
32- how insertion and search take place, we disregard it here.
33- Note that a newly inserted node will always appear as a leaf
34- in the tree. The BST invariant is always maintained: for each
35- subtree t, with root key t.key, the left subtree, t.left,
36- contains no node with key greater than k, and the right subtree,
37- t.right, contains no node with key smaller than k.
38- XXX AVL trees balanced, shorten above
39- Need to have these rotation explanations here as we can't format
40- explanations properly it seems:
41-
42- ## The left-left case
43-
44- If the new key was added to the left child of the left child (the
45- left-left case) and the resulting tree is too unbalanced, the balance can be
46- restored with a "Right rotation" operation, as explained in the diagram
47- below. The 6 and 4 nodes and the edge between them rotate clockwise, and
48- the 5 node changes parents from 4 to 6. This reduces the distance from
49- the root to the 1 (where the new node was added), restoring the balance
50- (the distance to the node rooted at 7 is increased but this does not
51- cause the AVL tree balance condition to be violated). Right rotation is
52- done by calling rightRotate(t6), where t6 is the tree rooted at 6.
53-
54- '''
55- 6 2
56- / \\ Right Rotation / \\
57- 2 7 - - - - - - - > 1 6
58- / \\ < - - - - - - - / \\
59- 1 4 Left Rotation 4 7
60- '''
61-
62- ## The right-right case
63-
64- The right-right case is the exact opposite. If the tree on the right in
65- the diagram above is too unbalanced due to insertion into the subtree
66- rooted at 7, we can call rightRotate(t2) to lift that subtree and lower
67- the 1 subtree.
68-
69- ## The left-right case (double rotation)
70-
71- If the new key was added to the right child of the left child (the
72- left-right case) and the resulting tree is too unbalanced, the balance can be
73- restored with a left rotation at node 2 followed by a right rotation at
74- node 6.
75- '''
76- 6 Rotate 6 Rotate 4
77- / \\ left at 2 / \\ right at 6 / \\
78- 2 7 - - - - - > 4 7 - - - - - > 2 6
79- / \\ / \\ / \\ / \\
80- 1 4 2 5 1 3 5 7
81- / \\ / \\
82- 3 5 1 3
83- '''
84- Nodes in the subtree rooted at 4 (where the extra element was added,
85- making the tree unbalanced) are moved closer to the root.
86- Trees rooted at 1, 3, 5 and 7 are not affected, except the distances from
87- the root of 3, 5 and 7 are changed by one, affecting the overall balance.
88-
89- ## right-left case (double rotation):
90-
91- If the new key was added to the left child of the right child (the
92- right-left case) and the resulting tree is too unbalanced, it is a mirror
93- image of the left-right case:
94-
95- XXX edit diagram above (tree on left won't be consistent with previous
96- examples but thats OK I think)
97-
98- \\Overview}
99-
10024\\Note{ For both insertion and search, the animation should be as
10125consistent
10226as possible with BST
@@ -124,14 +48,14 @@ AVLT_Insert(t, k) // returns t with key k inserted \\B AVLT_Insert(t, k)
12448 This is the base case of the recursion.
12549 \\Expl}
12650 \\In}
127- if k < root(t) .key \\B if k < root(t).key
51+ if k < t .key \\B if k < root(t).key
12852 \\Expl{ The key in the root determines if we insert into the left or
12953 right subtree.
13054 \\Expl}
13155 \\In{
13256 insert k into the left subtree of t \\Ref insertLeft
13357 \\In}
134- else if k > root(t) .key \\B else if k > root(t).key
58+ else if k > t .key \\B else if k > root(t).key
13559 \\Note{ XXX allow duplicate keys or not???
13660 Should be possible, but have to carefully review code to make sure its
13761 correct. What does BST code do?
@@ -169,14 +93,10 @@ recursive call plus we need a chunk at this level of recursion just
16993before the call so we can step back to it
17094\\Note}
17195// *recursively* call insert with the left subtree \\B prepare for the left recursive call
172- AVLT_Insert(left(t) , k) \\B left(t) <- AVLT_Insert(left(t), k)
96+ t.left <- AVLT_Insert(t.left , k) \\B left(t) <- AVLT_Insert(left(t), k)
17397\\Expl{
174- The left subtree is replaced by the result of this recursive call
98+ The (possibly empty) left subtree is replaced by the result of this recursive call.
17599\\Expl}
176- \\Note{
177- XXX should this be left(t) <- AVLT_Insert(left(t), k) or is the
178- explanation enough? (same for right)
179- \\Note}
180100\\Code}
181101
182102
@@ -188,16 +108,16 @@ recursive call plus we need a chunk at this level of recursion just
188108before the call so we can step back to it
189109\\Note}
190110// *recursively* call insert with the right subtree \\B prepare for the right recursive call
191- AVLT_Insert(right(t) , k) \\B right(t) <- AVLT_Insert(right(t), k)
111+ t.right <- AVLT_Insert(t.right , k) \\B right(t) <- AVLT_Insert(right(t), k)
192112\\Expl{
193- The right subtree is replaced by the result of this recursive call
113+ The (possibly empty) right subtree is replaced by the result of this recursive call.
194114\\Expl}
195115\\Code}
196116
197117\\Code{
198118rotateIfNeeded
199119switch balanceCase(t) of \\B switch balanceCase of
200- \\Expl{ If the "balance" of t (left(t). height - right(t) .height) is between -1
120+ \\Expl{ If the "balance" of t (t.left. height - t.right .height) is between -1
201121and 1, inclusive, we just
202122return t. Otherwise we must determine which sub-sub-tree the new element was
203123inserted into and use "rotation" operations to raise up that subtree and
@@ -216,7 +136,7 @@ case Balanced:// sufficiently balanced \\B case Balanced
216136case Left-Left:// Left-Left insertion, unbalanced \\B perform right rotation to re-balance t
217137\\Expl{
218138 Key k was inserted into the left-left subtree and made t unbalanced
219- (balance > 1 and k < left(t) .key).
139+ (balance > 1 and k < t.left .key).
220140 We must re-balance the tree with a "right rotation" that lifts up this
221141 subtree. See Background (click at the top of the right panel)
222142 for diagrams etc explaining rotations.
@@ -227,7 +147,7 @@ case Left-Left:// Left-Left insertion, unbalanced \\B perform right rotation to
227147case Right-Right:// Right-Right insertion, unbalanced \\B perform left rotation to re-balance t
228148\\Expl{
229149 Key k was inserted into the right-right subtree and made t unbalanced
230- (balance < -1 and k > right(t) .key).
150+ (balance < -1 and k > t.right .key).
231151 We must re-balance the tree with a "left rotation" that lifts up this
232152 subtree. See Background (click at the top of the right panel)
233153 for diagrams etc explaining rotations.
@@ -238,38 +158,50 @@ case Right-Right:// Right-Right insertion, unbalanced \\B perform left rotation
238158case Left-Right:// Left-Right insertion, unbalanced \\B perform left rotation on the left subtree
239159\\Expl{
240160 Key k was inserted into the left-right subtree and made t unbalanced
241- (balance > 1 && k > left(t) .key).
242- Balance can be restored by performing a "left rotation" on left(t) (this
161+ (balance > 1 && k > t.left .key).
162+ Balance can be restored by performing a "left rotation" on t.left (this
243163 lifts up the subtree) followed by a right rotation of t (in case the first
244164 rotation made the left-left subtree too deep).
245165 See Background (click at the top of the right panel)
246166 for diagrams etc explaining rotations.
247167\\Expl}
248168\\In{
249- perform leftRotate(left(t)) ; // raise Left-Right subtree \\B left(t) <- leftRotate(left(t));
169+ t.left <- leftRotate(t.left) ; // raise Left-Right -Right subtree \\B left(t) <- leftRotate(left(t));
250170 \\Expl{
251- The result returned is the new left(t). This lowers the Left-Left
252- subtree.
171+ This also raises the root of the Left-Right subtree.
172+ The Left-Right-Left subtree remains at the same level but is now the
173+ Left-Left-Right subtree (it is raised in the next step).
253174 \\Expl}
254175 return rightRotate(t) // raise Left-Left subtree to balance \\B return rightRotate(t) after leftRotate
176+ \\Expl{
177+ This raises what was previously the Left-Right-Left subtree, so the
178+ whole of the previous Left-Right subtree is now higher (and the
179+ Right subtree is lower).
180+ \\Expl}
255181\\In}
256182case Right-Left:// Right-Left insertion, unbalanced \\B perform right rotation on the right subtree
257183\\Expl{
258184 Key k was inserted into the right-left subtree and made t unbalanced
259- (balance < -1 && k < right(t) .key).
260- Balance can be restored by performing a "right rotation" on right(t) (this
185+ (balance < -1 && k < t.right .key).
186+ Balance can be restored by performing a "right rotation" on t.right (this
261187 lifts up the subtree) followed by a left rotation of t (in case the first
262188 rotation made the right-right subtree too deep).
263189 See Background (click at the top of the right panel)
264190 for diagrams etc explaining rotations.
265191\\Expl}
266192\\In{
267- perform rightRotate(right(t)) ; // raise Right-Left subtree \\B right(t) <- rightRotate(right(t));
193+ t.right <- rightRotate(t.right) ; // raise Right-Left -Left subtree \\B right(t) <- rightRotate(right(t));
268194 \\Expl{
269- The result returned is the new right(t). This lowers the Right-Right
270- subtree.
195+ This also raises the root of the Right-Left subtree.
196+ The Right-Left-Right subtree remains at the same level but is now the
197+ Right-Right-Left subtree (it is raised in the next step).
271198 \\Expl}
272199 return leftRotate(t) // raise Right-Right subtree to balance \\B return leftRotate(t) after rightRotate
200+ \\Expl{
201+ This raises what was previously the Right-Left-Right subtree, so the
202+ whole of the previous Right-Left subtree is now higher (and the
203+ Left subtree is lower).
204+ \\Expl}
273205\\In}
274206// ==== rotation functions ====
275207leftRotate(t2) // raises Right-Right + lowers Left-Left subtrees \\B leftRotate(t2)
@@ -280,8 +212,8 @@ See Background (click at the top of the right panel)
280212for diagrams etc explaining rotations.
281213\\Expl}
282214 \\In{
283- t6 <- right(t2) \\B t6 = right(t2)
284- t4 <- left(t6) // may be Empty \\B t4 = left(t6)
215+ t6 <- t2.right \\B t6 = right(t2)
216+ t4 <- t6.left // may be Empty \\B t4 = left(t6)
285217 t6.left <- t2 \\B t6.left = t2
286218 t2.right <- t4 // may be Empty \\B t2.right = t4
287219 recompute heights of t2 and t6 \\B recompute heights of t2 and t6
@@ -298,8 +230,8 @@ See Background (click at the top of the right panel)
298230for diagrams etc explaining rotations.
299231\\Expl}
300232 \\In{
301- t2 <- left(t6) \\B t2 = left(t6)
302- t4 <- right(t2) // may be Empty \\B t4 = right(t2)
233+ t2 <- t6.left \\B t2 = left(t6)
234+ t4 <- t2.right // may be Empty \\B t4 = right(t2)
303235 t2.right <- t6 \\B t2.right = t6
304236 t6.left <- t4 // may be Empty \\B t6.left = t4
305237 \\Note{ Animation here should be as smooth an intuitive as possible.
0 commit comments