Skip to content

Commit 56baba0

Browse files
committed
2 parents 2f6038c + 90b7fc8 commit 56baba0

File tree

3 files changed

+146
-105
lines changed

3 files changed

+146
-105
lines changed

src/algorithms/controllers/AVLTreeInsertion.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -678,6 +678,7 @@ export default {
678678
(vis, r, b, rr, rrr) => {
679679
// show the rotation type and the node to be rotated
680680
vis.graph.setFunctionName(`balanceCase: `);
681+
vis.graph.setFunctionName(`Rotation: `);
681682
vis.graph.setFunctionInsertText(`RR`);
682683
vis.graph.setFunctionNode(`${r}`);
683684
vis.graph.clearSelect_Circle_Count();
@@ -714,6 +715,7 @@ export default {
714715
(vis, r, b, rl, rlr) => {
715716
// show the rotation type and the node to be rotated
716717
vis.graph.setFunctionName(`balanceCase: `);
718+
vis.graph.setFunctionName(`Rotation: `);
717719
vis.graph.setFunctionInsertText(`LR`);
718720
vis.graph.clearSelect_Circle_Count();
719721
vis.graph.setSelect_Circle_Count(r);
@@ -751,6 +753,7 @@ export default {
751753
(vis, r, b, rr, rrl) => {
752754
// show the rotation type and the node to be rotated
753755
vis.graph.setFunctionName(`balanceCase: `);
756+
vis.graph.setFunctionName(`Rotation: `);
754757
vis.graph.setFunctionInsertText(`RL`);
755758
vis.graph.setFunctionNode(`${r}`);
756759
vis.graph.clearSelect_Circle_Count();

src/algorithms/explanations/AVLExp.md

Lines changed: 122 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -1,121 +1,146 @@
11
# AVL Trees
22

3-
An AVL tree is **self-balancing** binary search tree.
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.
7-
8-
### Binary Search Trees
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.
18-
19-
In a **binary search tree (BST)** the BST invariant is always maintained:\
20-
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.
24-
25-
### AVL tree balancing
26-
27-
The AVL tree preserves the balance of the tree by (1) checking after every insertion to detect
28-
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.
31-
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-
35-
A temporarily unbalanced AVL tree takes on one of two configurations, *zig-zag* or *zig-zig*. The
36-
sequence of rotations depends on the configuration around the node where the imbalance is detected.
37-
38-
### Zig-zig case
39-
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.
42-
43-
44-
## The left-left case
45-
46-
If the new key was added to the left child of the left child (the
47-
*left-left* case), the balance can be
48-
restored with a single _**Right Rotation**_ operation.
3+
An AVL tree is a kind of **binary search tree** that is
4+
**self-balancing**.
5+
6+
Unlike a basic binary search tree, which can exhibit *O(n)* worst case
7+
behavior for both search and insert, an AVL tree is always balanced, so
8+
the worst case *O(log n)*. The way balanced is maintained is quite
9+
complicated; we suggest experimenting with the examples at the end of
10+
this background.
11+
12+
A **binary search tree (BST)** is either empty or else it is a root
13+
node containing a key and two subtrees, which are binary search trees.
14+
Binary trees are ordered, so keys in the left subtree are smaller (or
15+
equal to) the key in the root and keys in the right subtree are greater
16+
(or equal to). Normally there is additional data in each node as well
17+
as the key, disregarded here. For an **AVL tree**, nodes also contain
18+
the *height* of the tree; this is used in the insertion algorithm to
19+
ensure the tree is balanced. The two children of an AVL tree node have
20+
*a height difference of at most one*. The height is ignored for search
21+
and AVL tree search is identical to BST search.
22+
23+
## Insertion
24+
25+
BST insertion traverses down the tree from the root (going left or
26+
right at each stage, depending on the comparison between the key in
27+
the node and the key to be inserted) then adds new leaf containing the
28+
inserted key. AVL tree insertion does the same, but additionally, the
29+
height information is updated and the tree may be adjusted to restore the
30+
balance. The coding here is recursive, with each recursive insert call
31+
going one step further down the tree. After each recursive call returns
32+
(implicitly traversing back up the tree to the root) the height adjustment
33+
and re-balancing is performed. The collapsed pseudocode is simply BST
34+
insertion code containing recursive calls, with code for height update
35+
and re-balancing added at the end. The new height is simply the maximum
36+
height of the two subtrees plus 1.
37+
38+
### Tree re-balancing
39+
40+
If the difference between the heights of the left and right subtrees is
41+
more than one, the tree is considered unbalanced and must be rearranged
42+
so that it is balanced. This is done by **local** operations, called
43+
**rotations**, that simply re-assign several pointers in the vicinity
44+
of the node. A rotation will raise up one subtree and lower another;
45+
the AVL insertion algorithm chooses what rotations to perform so as
46+
to ensure the tree is balanced after the insertion operation has been
47+
completed (assuming it was balanced to begin with).
48+
49+
An AVL tree node can only become unbalanced if insertion into one of the
50+
"grandchildren" (sub-sub-trees) increased the height of the tree. There
51+
are four grandchildren (called "left-left", "left-right", "right-left"
52+
and "right-right"), which must be handled separately. For the left-left
53+
and right-right cases a single rotation operation will restore balance.
54+
The other two cases each require two rotation operations.
55+
56+
#### Single rotations
57+
58+
A single rotation transforms the tree as shown in the diagram below,
59+
where t1, t4 and t7 are subtrees that may be of any size (in the "More"
60+
tab there is a W3Schools link that has an animation of these
61+
rotations).
62+
```
63+
/ /
64+
t6 t2
65+
/ \ Right Rotation / \
66+
t2 t7 - - - - - - - > t1 t6
67+
/ \ < - - - - - - - / \
68+
t1 t4 Left Rotation t4 t7
69+
```
4970

50-
Note that the imbalance may be located further up the tree than the immediate grandparent of the newly inserted node:
71+
Going from left to right (a **right rotation** of t6), subtree t1 is
72+
raised and t7 is lowered, but the ordering is preserved. You can think of
73+
t6, t2 and the edge between them being rotated clockwise, so t2 becomes
74+
the parent and t6 becomes the right child. Additionally, the parent of t4
75+
changes and the root of the tree changes (so the pointer from its parent
76+
changes). If t6 was unbalanced due to an insertion into t1 (the left-left
77+
case), this restores the balance. Similarly, the inverse operation, going
78+
from right to left (a **left rotation** of t2), restores the balance if
79+
unbalance was caused by insertion into t7 (the right-right case). The AIA
80+
pseudocode for rotation uses variables names consistent with this diagram.
5181

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*
82+
#### Double rotations
5583

84+
If the tree becomes unbalanced due to insertion into t4 (the left-right
85+
case), balance can be restored by performing a left rotation at t2
86+
followed by a right rotation at t6, as shown in the following digram:
5687

57-
, as explained in the diagram
58-
below. The 6 and 4 nodes and the edge between them rotate clockwise, and
59-
the 5 node changes parents from 4 to 6. This reduces the distance from
60-
the root to the 1 (where the new node was added), restoring the balance
61-
(the distance to the node rooted at 7 is increased but this does not
62-
cause the AVL tree balance condition to be violated). Right rotation is
63-
done by calling rightRotate(t6), where t6 is the tree rooted at 6.
88+
```
89+
/ / /
90+
t6 Rotate t6 Rotate t4
91+
/ \ left at t2 / \ right at t6 / \
92+
t2 t7 - - - - - > t4 t7 - - - - - > t2 t6
93+
/ \ / \ / \ / \
94+
t1 t4 t2 t5 t1 t3 t5 t7
95+
/ \ / \
96+
t3 t5 t1 t3
97+
```
6498

65-
![Alt text if image doesn't open: AVL-left-left](images/AVL/AVL-left-left.jpg){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.
66-
99+
Note that subtree t4 is broken into three parts but all these parts are
100+
raised whereas t7 is lowered (and the order is preserved). The right-left
101+
case is the mirror image and balance can be restored with a right rotation
102+
followed by a left rotation (for brevity we omit the details).
67103

104+
## Examples
68105

106+
The following examples of inputs result in rotation for the last key
107+
inserted. You can copy/paste these into AIA, use the progress bar to
108+
get to the point where the last key is inserted and step through the
109+
execution; expand the pseudocode to show details of the rotations being
110+
performed.
69111

112+
### Left-left cases (right rotations)
70113

114+
The following examples show a simplest case (where t4 is empty), a
115+
case most like the first diagram above, a case where the rotation is
116+
not at the root and a case where insertion is several levels below the
117+
rotation point.
71118

72119
```
73-
6 2
74-
/ \ Right Rotation / \
75-
2 7 - - - - - - - > 1 6
76-
/ \ < - - - - - - - / \
77-
1 4 Left Rotation 4 7
120+
60,20,10
121+
60,20,70,10,40,15
122+
60,20,70,10,5
123+
60,20,70,10,40,80,30,5,15,12
78124
```
79125

80-
## The right-right case
81-
82-
The right-right case is the exact opposite. If the tree on the right in
83-
the diagram above is too unbalanced due to insertion into the subtree
84-
rooted at 7, we can call rightRotate(t2) to lift that subtree and lower
85-
the 1 subtree.
126+
### Right-right cases (left rotations)
86127

87-
## The left-right case (double rotation)
128+
In the following examples the trees are mirror images of the ones above.
88129

89-
If the new key was added to the right child of the left child (the
90-
left-right case) and the resulting tree is too unbalanced, the balance can be
91-
restored with a left rotation at node 2 followed by a right rotation at
92-
node 6.
93130
```
94-
6 Rotate 6 Rotate 4
95-
/ \ left at 2 / \ right at 6 / \
96-
2 7 - - - - - > 4 7 - - - - - > 2 6
97-
/ \ / \ / \ / \
98-
1 4 2 5 1 3 5 7
99-
/ \ / \
100-
3 5 1 3
131+
20,60,70
132+
20,10,60,40,70,65
133+
20,10,60,40,35
134+
20,10,60,5,40,70,50,65,80,67
101135
```
102-
Nodes in the subtree rooted at 4 (where the extra element was added,
103-
making the tree unbalanced) are moved closer to the root.
104-
Trees rooted at 1, 3, 5 and 7 are not affected, except the distances from
105-
the root of 3, 5 and 7 are changed by one, affecting the overall balance.
106136

107-
## right-left case (double rotation):
137+
### Left-right and right-left cases (double rotations)
108138

109-
If the new key was added to the left child of the right child (the
110-
right-left case) and the resulting tree is too unbalanced, it is a mirror
111-
image of the left-right case:
139+
These cases require double rotations.
112140

113141
```
114-
2 Rotate 2 Rotate 4
115-
/ \ right at 6 / \ left at 2 / \
116-
1 6 - - - - - > 1 4 - - - - - > 2 6
117-
/ \ / \ / \ / \
118-
4 7 3 6 1 3 5 7
119-
/ \ / \
120-
3 5 5 7
142+
60,20,40
143+
60,20,70,40,10,30
144+
20,60,40
145+
20,10,60,40,70,30
121146
```

src/algorithms/extra-info/AVLInfo.md

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,35 @@
11
<style>
22
a:link {
3-
color: #90ee90;
3+
color: #1e28f0;
44
}
55
a:visited{
6-
color: #ffaeb9;
6+
color: #3c1478;
77
}
88
a:hover{
9-
color: #B22222;
9+
color: #1e288c;
1010
}
1111
</style>
1212

1313
## Extra Info
1414

15-
-----
15+
W3Schools Link: [**AVL Trees**][G4GLink]
1616

17-
<!-- Geeks for Geeks Link: [**AVL Tree**][G4GLink] -->
17+
[G4GLink]: https://www.w3schools.com/dsa/dsa_data_avltrees.php
1818

19-
<!-- [G4GLink]: https://www.w3schools.com/dsa/dsa_data_avltrees.php -->
19+
## Exercises/Exploration
20+
21+
With insertion of three distinct keys there are six orders in which the
22+
keys may appear. How many different AVL trees are there with three
23+
given distinct keys? Explore how insertion takes place for the six
24+
different orders.
25+
26+
In the background it says that unbalance can only be caused by insertion
27+
into a grandchild of a node. Why can't it be caused by just adding a
28+
new child to a node?
29+
30+
In the worst case for simple binary trees, every node except one has a
31+
single chlild. Find some worst case AVL trees.
32+
33+
The AIA insertion code is recursive. What possible ways are there to
34+
write a non-recursive version?
2035

21-
Geeks for Geeks Link:
22-
<a href="https://www.w3schools.com/dsa/dsa_data_avltrees.php" target="_blank">AVL Tree</a>

0 commit comments

Comments
 (0)