Balanced Binary Search Trees (BBSTS) : William Fiset
Balanced Binary Search Trees (BBSTS) : William Fiset
Trees (BBSTs)
• William Fiset
What is a BBST?
A Balanced Binary Search Tree (BBST) is a self-
balancing binary search tree. This type of tree will adjust
itself in order to maintain a low (logarithmic) height
allowing for faster operations such as insertions and
deletions.
Complexity of Binary Search
Trees
Operation Average Worst
Right rotation
B C D A
Left rotation
D E E C
does this work? Why are you allowed to change the structure of a tree l
Short answer: In the left tree we know that D < B < E < A < C and
this remains true for the right subtree, so we didn’t break the BST
invariant and, therefore, this is a valid transformation.
Long answer
re BSTs so the BST invariant holds. This means that for every node n, n.
NOTE: The above assumes we only have unique values, otherwise we’d have to consider the case where
n.left ≤ n and n ≤ n.right
care about is that the BST invariant holds. This means we can shuffle/tra
long as the BST invariant remains satisfied!
P
function rightRotate(A):
B := A.left C
B
A.left = B.right
B.right = A
return B
D E
P
function rightRotate(A):
B := A.left C
B
A.left = B.right
B.right = A
return B
D E
P
function rightRotate(A):
B := A.left C
B
A.left = B.right
B.right = A
return B
D E
P
function rightRotate(A):
B := A.left C
B
A.left = B.right
B.right = A
return B
D E
P
function rightRotate(A):
B := A.left C
B
A.left = B.right
B.right = A
return B
D E
P
B
function rightRotate(A):
B := A.left
D A
A.left = B.right
B.right = A
return B
E C
P
B
function rightRotate(A):
B := A.left
D A
A.left = B.right
B.right = A
return B
E C
e left/right pointer referenced it. It’s very important that this link be updated to refer
value of rotateRight.
P
B
function rightRotate(A):
B := A.left
D A
A.left = B.right
B.right = A
return B
E C
e left/right pointer referenced it. It’s very important that this link be updated to refer
value of rotateRight.
In some BBST implementations where you often need to access the
parent/uncle nodes (such as RB trees), it’s convenient for nodes to not only
have a reference to the left and the right child nodes but also the parent node.
This can complicate tree rotations because instead of updating three
pointers, now you have to update six!
function rightRotate(A):
P := A.parent P
B := A.left
A.left = B.right
if B.right != null:
A
B.right.parent = A
B.right = A
A.parent = B
B.parent = P B C
William Fiset
AVL Tree Introduction
ich forces it to remain balanced is the requirement that the balance facto
Node Information to Store
-2
0 (+1)
-1 Right rotation
at if the BF of a node is ∉ {-1, 0, +1}? How do we restore the AVL tree in
-2 -2
0 (+1)
+2
0 (-1)
+1 Left rotation
at if the BF of a node is ∉ {-1, 0, +1}? How do we restore the AVL tree in
+2 +2
0 (-1)
-1 Right rotation +1 Left rotation
# Public facing insert method. Returns true # on successful insert
and false otherwise.
function insert(value):
if value == null:
return false
if cmp < 0:
node.left = insert(node.left, value)
else:
node.right = insert(node.right, value)
# Rebalance tree
return balance(node)
function update(node):
function leftRightCase(node):
node.left = leftRotation(node.left)
return leftLeftCase(node)
function rightRightCase(node):
return leftRotation(node)
function rightLeftCase(node):
node.right = rightRotation(node.right)
return rightRightCase(node)
AVL Tree Rotation Method
function rightRotate(A):
B := A.left
A.left = B.right
B.right = A
# After rotation update
balance
# factor and height values.
update(A)
update(B)
return B
rotations require you to call the update method! The left rotation is sy
Next Video: AVL Tree Removals
https://github.com/williamfiset/data-structures
Removing Elements
from an AVL Tree
William Fiset
Removing Elements from a BST
Removing elements from a Binary Search Tree (BST) can be
seen as a two-step process:
20
Find queries:
find(14) 10 31
find(26)
5 15 25 42
2 12 19 35 47
11 14 33 37
Find Phase
20
Find queries:
find(14) 10 31
find(26)
5 15 25 42
2 12 19 35 47
11 14 33 37
Find Phase
20
Find queries:
find(14) 10 31
find(26)
5 15 25 42
2 12 19 35 47
11 14 33 37
Find Phase
20
Find queries:
find(14) 10 31
find(26)
5 15 25 42
2 12 19 35 47
11 14 33 37
Find Phase
20
Find queries:
find(14) 10 31
find(26)
5 15 25 42
2 12 19 35 47
11 14 33 37
Find Phase
20
Find queries:
find(14) 10 31
find(26)
5 15 25 42
2 12 19 35 47
11 14 33 37
Find Phase
20
Find queries:
find(14) 10 31
find(26)
5 15 25 42
2 12 19 35 47
11 14 33 37
Find Phase
20
Find queries:
find(14) 10 31
find(26)
5 15 25 42
2 12 19 35 47
11 14 33 37
Find Phase
20
Find queries:
find(14) 10 31
find(26)
5 15 25 42
2 12 19 35 47
11 14 33 37
Find Phase
20
Find queries:
find(14) 10 31
find(26)
5 15 25 42
2 12 19 35 47
11 14 33 37
Find Phase
20
Find queries:
find(14) 10 31
find(26)
5 15 25 42
2 12 19 35 47
11 14 33 37
4 9
1 7 10
6 8
Remove phase
Case I: Leaf node
5
Suppose we want to remove 8 from the BST
on the right. First we would find 8 then 4 9
remove it immediately since it’s a leaf node
1 7 10
6 8
Remove phase
Case I: Leaf node
5
Suppose we want to remove 8 from the BST
on the right. First we would find 8 then 4 9
remove it immediately since it’s a leaf node
1 7 10
6 8
Remove phase
Case I: Leaf node
5
Suppose we want to remove 8 from the BST
on the right. First we would find 8 then 4 9
remove it immediately since it’s a leaf node
1 7 10
6 8
Remove phase
Case I: Leaf node
5
Suppose we want to remove 8 from the BST
on the right. First we would find 8 then 4 9
remove it immediately since it’s a leaf node
1 7 10
6 8
Remove phase
Case I: Leaf node
5
Suppose we want to remove 8 from the BST
on the right. First we would find 8 then 4 9
remove it immediately since it’s a leaf node
1 7 10
6 8
Remove phase
Case I: Leaf node
5
Suppose we want to remove 8 from the BST
on the right. First we would find 8 then 4 9
remove it immediately since it’s a leaf node
1 7 10
6 8
Remove phase
Case I: Leaf node
5
Suppose we want to remove 8 from the BST
on the right. First we would find 8 then 4 9
remove it immediately since it’s a leaf node
1 7 10
6
Remove phase
Cases II & III: either the left/right child
node is a subtree
moving the root node of the BST, in which case its immediate child becomes the
Remove phase
Suppose we wish to remove 9, then we
encounter case II with a left subtree
4 9
3 7
6 8
Remove phase
Suppose we wish to remove 9, then we
encounter case II with a left subtree
4 9
3 7
6 8
Remove phase
Suppose we wish to remove 9, then we
encounter case II with a left subtree
4 9
3 7
6 8
Remove phase
Suppose we wish to remove 9, then we
encounter case II with a left subtree
4 9
3 7
6 8
Remove phase
Suppose we wish to remove 9, then we
encounter case II with a left subtree
3 7
6 8
Remove phase
Suppose we wish to remove 9, then we
encounter case II with a left subtree
3 7
6 8
Remove phase
Suppose we wish to remove 9, then we
encounter case II with a left subtree
4 7
3 6 8
Remove phase
Suppose we wish to remove 9, then we
encounter case II with a left subtree
4 7
3 6 8
Remove phase
Case IV: Node to remove has both a left
subtree and a right subtree
In which subtree will the successor of the node we are trying to remove
Remove phase
Case IV: Node to remove has both a left
subtree and a right subtree
In which subtree will the successor of the node we are trying to remove
Once the successor node has been identified (if it exists), replace
the value of the node to remove with the value in the successor
node.
TE: This is a removal example for BSTs in general, not an AVL tree per
5 20
4 18 25
2 11 19 33
1 3 14 28
12 15 31
Let’s remove node 7. This is a case IV removal.
TE: This is a removal example for BSTs in general, not an AVL tree per
5 20
4 18 25
2 11 19 33
1 3 14 28
12 15 31
Now choose the successor to be either the smallest value in the right subtree
or the largest in the left subtree. Let’s do the former. To do this, dig as far left
as possible in the right subtree.
5 20
4 18 25
2 11 19 33
1 3 14 28
12 15 31
Now choose the successor to be either the smallest value in the right subtree
or the largest in the left subtree. Let’s do the former. To do this, dig as far left
as possible in the right subtree.
5 20
4 18 25
2 11 19 33
1 3 14 28
12 15 31
Now choose the successor to be either the smallest value in the right subtree
or the largest in the left subtree. Let’s do the former. To do this, dig as far left
as possible in the right subtree.
5 20
4 18 25
2 11 19 33
1 3 14 28
12 15 31
Now choose the successor to be either the smallest value in the right subtree
or the largest in the left subtree. Let’s do the former. To do this, dig as far left
as possible in the right subtree.
5 20
4 18 25
2 11 19 33
1 3 14 28
12 15 31
e value from the node found in right subtree (11) to the node we want to
5 20
4 18 25
2 11 19 33
1 3 14 28
12 15 31
e value from the node found in right subtree (11) to the node we want to
11
5 20
4 18 25
2 11 19 33
1 3 14 28
12 15 31
we found in the right subtree. Luckily, the node we find will always be
11
5 20
4 18 25
2 11 19 33
1 3 14 28
12 15 31
we found in the right subtree. Luckily, the node we find will always be
11
5 20
4 18 25
2 11 19 33
1 3 14 28
12 15 31
we found in the right subtree. Luckily, the node we find will always be
11
5 20
4 18 25
2 19 33
1 3 14 28
12 15 31
we found in the right subtree. Luckily, the node we find will always be
11
5 20
4 18 25
2 19 33
1 3 14 28
12 15 31
we found in the right subtree. Luckily, the node we find will always be
11
5 20
4 18 25
2 19 33
1 3 14 28
12 15 31
we found in the right subtree. Luckily, the node we find will always be
11
5 20
4 18 25
2 14 19 33
1 3 12 15 28
31
Augmenting BST Removal
Algorithm for AVL Tree
Augmenting the removal algorithm from a plain BST implementation to
an AVL tree is just as easy as adding two lines of code:
# Rebalance tree
Next Video: AVL Tree Source Code
https://github.com/williamfiset/data-structures
AVL Tree
Source Code
William Fiset
Source Code Link
Implementation source code and tests can all be found at
the following link:
github.com/williamfiset/data-structures