0% found this document useful (0 votes)
16 views66 pages

l14 Balancedbst Avl

Uploaded by

syperez
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
16 views66 pages

l14 Balancedbst Avl

Uploaded by

syperez
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 66

1

CSCI 104
Binary Search Trees and
Balanced Binary Search Trees
using AVL Trees
Mark Redekopp
David Kempe

© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
2

Properties, Insertion and Removal

BINARY SEARCH TREES

© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
3

Binary Search Tree


• Binary search tree = binary tree where all nodes meet the
binary search property which states:
– All values of nodes in left subtree are less-than (or equal in some
implementations) than the parent’s value
– All values of nodes in right subtree are greater-than (or equal in some
implementations) than the parent’s value
• BSTs generally implement maps/sets 25
(where keys must be unique) and
18 47
support 3 primary operations:
– Insert
7 20 32 56
– Remove
– Find/Lookup If we wanted to print the values
in sorted order would you use an
pre-order, in-order, or post-order
traversal?
© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
4

BST-Find
• To find a node with a given key
– If node pointer is NULL, the key does NOT exist in the tree, STOP!
– Otherwise, check if current node's key equals the desired key
• If so, STOP! and return a pointer to that node
– If desired key is LESS-THAN current node's key, go LEFT
– If desired key is GREATER-THAN current node's key, go RIGHT

25

18 47

7 32 56

© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
5

BST Insertion
• To insert an item walk the tree (go left if value is less than node, right if
greater than node) until you find an empty location, at which point you
insert the new value
• Practice: Build a BST from the data values below

Insertion Order: 25, 18, 47, 7, 20, 32, 56 Insertion Order: 7, 18, 20, 25, 32, 47, 56

Important: To be efficient (useful) we need to keep the binary search tree


balanced, but that is NOT guaranteed by the basic insert() algorithm.
© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
6

BST Insertion
• To insert an item, walk the tree (go left if value is less than node, right if
greater than node) until you find an empty location, at which point you
insert the new value
• Practice: Build a BST from the data values below
• https://www.cs.usfca.edu/~galles/visualization/BST.html
Insertion Order: 25, 18, 47, 7, 20, 32, 56 Insertion Order: 7, 18, 20, 25, 32, 47, 56

25 7

18 47 18

20
7 20 32 56
25

32

47
A major topic we will talk about is algorithms
to keep a BST balanced as we do
insertions/removals 56
© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
7

Successors & Predecessors


• Let's take a quick tangent that will be necessary when we
implement BST Removal
• Given a node in a BST
– Its predecessor is defined as the next smallest value in the tree
– Its successor is defined as the next biggest value in the tree
• Where would you expect to find a node's predecessor?
• Where would find a node's successor?
// Node definition
m struct TNode
{
int val;
TNode *left, *right;
Tnode *parent;
};

© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
8

Predecessors Pred(50)

• If left child exists, predecessor is the 50

right most node of the left subtree 20 60


• Else walk up the ancestor chain until you
10 30
traverse the first right child pointer (find
the first node who is a right child of his 25
parent…that parent is the predecessor) Pred(25)

– If you get to the root w/o finding a node 50


who is a right child, there is no predecessor
20 60
If you have no left pointer, then realize that you must be
someone's successor [ succ(pred(m)) = m].
Think about who, if they wanted to find their successor (go 10 30
right once and left as far as you can), would land on you.
25
Code to check if you are the left child of your parent:

© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
9

Predecessors Pred(50) = 30
• If left child exists, predecessor is the 50
right most node of the left subtree
20 60
• Else walk up the ancestor chain until
you traverse the first right child 10 30
pointer (find the first node who is a
25
right child of his parent…that parent is
Pred(25)=20
the predecessor)
50
– If you get to the root w/o finding a node
who is a right child, there is no 20 60
predecessor
10 30

25

© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
10

Successors Succ(20)
• If right child exists, successor is the 50
left most node of the right subtree
20 60
• Else walk up the ancestor chain until
you traverse the first left child pointer 10 30
(find the first node who is a left child
25
of his parent…that parent is the
Succ(30)
successor)
50
– If you get to the root w/o finding a node
who is a left child, there is no successor 20 60

10 30

25

© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
11

Successors Succ(20) = 25
• If right child exists, successor is the 50
left most node of the right subtree
20 60
• Else walk up the ancestor chain until
you traverse the first left child pointer 10 30
(find the first node who is a left child
25
of his parent…that parent is the
Succ(30)=50
successor)
50
– If you get to the root w/o finding a node
who is a left child, there is no successor 20 60

10 30

25

© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
12

BST Removal
• How we remove is based on the number of children the node has…
– First find the value to remove by walking the tree
– 0 children: If the value is in a leaf node, simply remove that leaf node
– 1 child: Promote the child into the node's location
– 2 children: Swap the value with its in-order successor or predecessor and then
remove from its new location
• We can maintain the BST properties by putting a value's successor or predecessor in its
place
• After swap, we have converted to 0-children or 1-child case (i.e. non-leaf node's
successor or predecessor is guaranteed to not have 2 children) which we then perform
Remove 25 Remove 30 Remove 20
50
Either swap with
50 50 50 predecessor
10 60
20 60 20 60 20 60
20 30 50
10 30 10 30 10 30 25 60
5 25 35
25 25 5 25 35
…or swap with
10 30
Leaf node so 1-Child so just 20 is a non-leaf so can't delete it
where it is…swap w/ successor successor
just delete it 22 promote child
or predecessor 5 20 35
© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
13

Worst Case BST Efficiency


• Insertion
#include<iostream>

// Node definition
– Balanced: _________ template <typename T>
struct TNode

– Unbalanced: _________
{
T val;
TNode *left, *right;
• Removal };
Tnode *parent;

– Balanced: ________ // Bin. Search Tree


template <typename T>
– Unbalanced: _________ class BST
{

• Find/Search
public:
BTree();
~BTree();
– Balanced: __________ virtual bool empty();
virtual void insert(const T& v);
virtual void remove(const T& v);
– Unbalanced: __________ virtual T* find(const T& v);
protected:
TNode<T>* root_;
};
© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
14

BST Efficiency
• Insertion
#include<iostream>

// Node definition
– Balanced: O(log n) template <typename T>
struct TNode

– Unbalanced: O(n)
{
T val;
TNode *left, *right;
• Removal };
Tnode *parent;

– Balanced : O(log n) // Bin. Search Tree


template <typename T>
– Unbalanced: O(n) class BST
{

• Find/Search
public:
BTree();
~BTree();
– Balanced : O(log n) virtual bool empty();
virtual void insert(const T& v);
virtual void remove(const T& v);
– Unbalanced: O(n) virtual T* find(const T& v);
protected:
TNode<T>* root_;
};
© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
15

Trees & Maps/Sets


• C++ STL "maps" and "sets" use binary search trees
internally to store their keys (and values) that can grow
or contract as needed
• This allows O(log n) time to find/check membership
– BUT ONLY if we keep the tree balanced!
Map::find("Greg") key value Map::find("Mark")

Returns iterator to "Jordan" Student Returns iterator to end()


corresponding object [i.e. NULL]
pair<string, Student>

"Frank" Student "Percy" Student


object object

"Anne" Student "Greg" Student "Tommy" Student


object object object

© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
16

The key to balancing…

TREE ROTATIONS

© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
17

BST Subtree Ranges


• Consider a binary search tree, what range of values could be in
the subtree rooted at each node
– At the root, any value could be in the "subtree"
– At the first left child?
– At the first right child?
What values
might be in (-inf, inf) (-inf,inf)
the subtree z x
rooted here
( ) ( ) ( ) ( )
y d a y
( ) ( ) ( ) ( )
x c b z
( ) ( ) ( ) ( )
a b c d

© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
18

BST Subtree Ranges


• Consider a binary search tree, what range of values could be in
the subtree rooted at each node
– At the root, any value could be in the "subtree"
– At the first left child?
– At the first right child?
(-inf, inf) (-inf, inf)

z x
(-inf, z) (z, inf) (-inf, x) (x, inf)
y d a y
(-inf, y) (y,z) (x, y) (y, inf)
x c b z
(-inf, x) (x,y) (y,z) (z,inf)
a b c d

© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
19

Right Rotation
• Define a right rotation as taking a left child, making it
the parent and making the original parent the new right
child
• Where do subtrees a, b, c and d belong?
– Use their ranges to reason about it…
(-inf, inf)

z Right
y
rotate of
(-inf, z) (z, inf)
z
y d x z
(-inf, y) (y,z)
c ___ ___ ___ ___
x
(-inf, x) (x,y)
a b
© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
20

Right Rotation
• Define a right rotation as taking a left child, making it
the parent and making the original parent the new right
child
• Where do subtrees a, b, c and d belong?
– Use their ranges to reason about it…
(-inf, inf)

z Right
y
rotate of
(-inf, z) (z, inf)
z
y d x z
(-inf, y) (y,z)
c a b c d
x
(-inf, x) (x,y) (y,z) (z, inf)
(-inf, x) (x,y)
a b
© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
21

Left Rotation
• Define a left rotation as taking a right child, making it
the parent and making the original parent the new left
child
• Where do subtrees a, b, c and d belong?
– Use their ranges to reason about it…
(-inf, inf)

y x
Left
rotate of (-inf, x) (x, inf)
x
x z a y
(x, y) (y, inf)
___ ___ ___ ___ b z
(y,z) (z,inf)
c d

© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
22

Left Rotation
• Define a left rotation as taking a right child, making it
the parent and making the original parent the new left
child
• Where do subtrees a, b, c and d belong?
– Use their ranges to reason about it…
(-inf, inf)

y x
Left
rotate of (-inf, x) (x, inf)
x
x z a y
(x, y) (y, inf)
a b c d b z
(-inf, x) (x,y) (y,z) (z, inf)
(y,z) (z,inf)
c d

© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
23

Rotations
• Define a right rotation as taking a left child, making it
the parent and making the original parent the new right
child
• Where do subtrees a, b, and c belong?
– Use their ranges to reason about it…
(-inf, inf) (-inf, inf)

y x
Right rotate
(-inf, y) (y, inf) of y (-inf, x) (x, inf)
x c a y
(-inf, x) (x,y) (x, y) (y, inf)
a b Left rotate b c
of x

© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
24

Implementing Rotations
• Take a moment and identify how many and which
pointers need to be updated to perform the below
right rotation
p 1.
p
2.
(-inf, inf) (-inf, inf)
3.
y x 4.
Right rotate
(-inf, y) (y, inf) of y (-inf, x) (x, inf)
x c a y
(-inf, x) (x,y) (x, y) (y, inf) …
a b b c

© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
25

Rotation's Effect on Height


• When we rotate, it serves to re-balance the tree

z
y
Right rotate
of z
y
h h x z h+1
h+2
x c
h
h h h h

h h

Let's always specify the parent node involved in a rotation (i.e. the
node that is going to move DOWN).

© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
26

Self-balancing tree proposed by Adelson-Velsky and Landis

AVL TREES

© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
27

AVL Trees
• A binary search tree where the height difference between left and right subtrees
of a node is at most 1
– Binary Search Tree (BST): Left subtree keys are less than the root and right subtree keys
are greater
• Two implementations:
– Height: Just store the height of the tree rooted at that node
– Balance: Define b(n) as the balance of a node = Right – Left Subtree Height
• Legal values are -1, 0, 1
• Balances require at most 2-bits if we are trying to save memory.
• Let's use balance for this lecture.

-1 20
4 20
Balance
factors
0 10 -1 30
3 10 2 30

05 1 12 0 25
2 5 2 12 1 25

0 15
1 15 0 3 0 8
1 3 1 8
AVL Tree storing Heights
© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed. AVL Tree storing balances
28

Adding a New Node


• Once a new node is added, can its parent be out of balance?
– No, assuming the tree is "in-balance" when we start.
– Thus, our parent has to have
• A balance of 0
• A balance of 1 if we are a new left child or -1 if a new right child
– Otherwise, it would not be our parent or the parent would have been
out of balance already
• Cases for a newly inserted LEFT child

0 12 -1 12 +112 0 12

0 10 0 20 0 10 0 20

To be a newly inserted LEFT child - To be a newly inserted LEFT child -


Option
© 2022 by Mark Redekopp. This content 1 and may not be shared, uploaded, or distributed.
is protected Option 2
29

Losing Balance
• If our parent is NOT out of balance, is it possible our
grandparent is out of balance?
• Sure, so we need a way to re-balance it

-2 2
-1 15 1 10

-1
0 12 -1
0 15

0 10
0 12

© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
30

To Zig or Zag
• The rotation(s) required to g
0 12
g
-2 20 2 10
balance a tree is/are
p p
dependent on the -1 12 0 10 0 20 1 12
grandparent, parent, child
0 10 0 20
relationships
Left-left or Right-right
• We can refer to these as (a.k.a. Zig-zig)
the zig-zig (left-left or right- [Single left/right rotation at grandparent]
right) case and zig-zag case
(left-right or right-left)
g
• Zig-zig requires 1 rotation 0 12
g
-2 20 2 10
• Zig-zag requires 2 rotations p p
0 10 0 20
(first converts to zig-zig) 1 10 -1 20

0 12 0 12
Left-right or Right-left
(a.k.a. Zig-zag)
[Left/right rotation at parent followed by rotation in
opposite direction at grandparent]
© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
31

Disclaimer
• There are many ways to structure an
implementation of an AVL tree…the following
slides represent just 1
– Focus on the bigger picture ideas as that will allow
you to more easily understand other
implementations

© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
32

Insert(n)
• If empty tree => set n as root, b(n) = 0, done!
• Else insert n (by walking the tree to a leaf, p, and
inserting the new node as its child), set balance
-1 12
to 0, and look at its parent, p
0 10 0 20
– If b(p) was -1, then b(p) = 0. Done!
– If b(p) was +1, then b(p) = 0. Done! 1 12

– If b(p) was 0, then update b(p) and call insert-fix(p, n) 0 10 0 20

-1
0 12

0 10

© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
33

Insert-fix(p, n)
General Idea:
Work up ancestor
• Precondition: p and n are balanced: {-1,0,-1} chain updating
• Postcondition: g, p, and n are balanced: {-1,0,-1} balances of the
ancestor chain or
• If p is null or parent(p) is null, return fix a node that is
• Let g = parent(p) out of balance.

• Assume p is left child of g [For right child swap left/right, +/-]


– b(g) += -1 // Update g's balance to new accurate value for now
– Case 1: b(g) == 0, return
– Case 2: b(g) == -1, insertFix(g, p) // recurse Note: If you
– Case 3: b(g) == -2 perform a
rotation to fix a
• If zig-zig then rotateRight(g); b(p) = b(g) = 0 node that is out
• If zig-zag then rotateLeft(p); rotateRight(g); of balance you
– Case 3a: b(n) == -1 then b(p) = 0; b(g) = +1; b(n) = 0; will NOT need
– Case 3b: b(n) == 0 then b(p) = 0; b(g) = 0; b(n) = 0; to recurse. You
– Case 3c: b(n) == +1 then b(p)= -1; b(g) = 0; b(n) = 0;
are done!
© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
34

Insertion
• Insert 10, 20, 30, 15, 25, 12, 5, 3, 8
Empty Insert 10 Insert 20 Insert 30 Zig-zig =>
10 violates balance b(g) = b(p) = 0

1 10 2 10 g 0 20
0 10

0 20
p 0 10 0 30
1 20

n
0 30

Insert 15 Insert 25 Insert 12 Zig-zag & b(n) = 0 =>


b(g) = b(p) = b(n) = 0
-1 20 0 20 0 20 0 20

1 10 0 30 -1 30
g -1 30 0 12 -1 30
1 10 2 10

0 15 0 15 0 25 p -1 15 0 25 0 10 0 15 0 25

0 12 n
© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
35

Insertion
• Insert 10, 20, 30, 15, 25, 12, 5, 3, 8
Zig-zig =>
Insert 5 Insert 3 -1 20 b(g) = b(p) = 0
-1 20 -1 20

-1 12 -1 30 -1 12 -1 30 -1 12 -1 30

g
-110 0 15 0 25 -210 0 15 0 25 05 0 15 0 25
p
-1 5 3 0 10
0 5 0

0 3

Insert 8 -1 20 Zig-zag & b(n) = -1 => -1 20


b(g) = 1 & b(p) = b(n) = 0

-2 12 -1 30 0 10 -1 30

+1 5 0 15 0 25 05 1 12 0 25

0 3 -1 10 n 0 3 0 8 0 15

0 8
© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
36

Insertion Exercise 1
• Insert key=28
-1 20

0 10 -1 30

05 1 12 0 25

0 15
0 3 0 8

© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
37

Insertion Exercise 2
• Insert key=17
-1 20

0 10 -1 30

05 1 12 0 25

0 15
0 3 0 8

© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
38

Insertion Exercise 3
• Insert key=2
-1 20

0 10 -1 30

05 1 12 0 25

0 15
0 3 0 8

© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
39

Remove Operation
• Remove operations may also require rebalancing via
rotations
• The key idea is to update the balance of the nodes
on the ancestor pathway
• If an ancestor gets out of balance then perform
rotations to rebalance
– Unlike insert, performing rotations during removal does
not mean you are done, but need to continue recursing
• There are slightly more cases to worry about but not
too many more

© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
40

Removal: A First Look


• Let's try removal just by intuition…
– Walk up ancestor chain updating balances
– Fix any out-of-balance node by performing rotations

Remove 25

-1 20 0 10
-2 20

-1 10 -1 30 0 20
-1 10 0 30 05

0 5 0 12 0 25 0 3 0 8 0 12 0 30
05 0 12

0 3 0 8 0 3 0 8

Update Balances Perform rotations using


"taller" of children
© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
41

Remove
• Find node, n, to remove by walking the tree
• If n has 2 children, swap positions with in-order successor (or
predecessor) and perform the next step
– Recall if a node has 2 children we swap with its successor or predecessor who
can have at most 1 child and then remove that node
• Let p = parent(n)
• If p is not NULL,
– If n is a left child, let diff = +1
– If n is a left child to be removed, the right subtree now has greater height, so add diff = +1 to
balance of its parent
– if n is a right child, let diff = -1
– If n is a right child to be removed, the left subtree now has greater height, so add diff = -1 to
balance of its parent
– diff will be the amount added to updated the balance of p
• Delete n and update pointers
• “Patch tree” by calling removeFix(p, diff);
© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
42

RemoveFix(n, diff)
• If n is null, return
• Compute next recursive call's arguments now before altering the tree
– Let p = parent(n) and if p is not NULL let ndiff (nextdiff) = +1 if n is a left child and -1 otherwise
• Assume diff = -1 and follow the remainder of this approach, mirroring if diff = +1
• Case 1: b(n) + diff == -2
– [Perform the check for the mirror case where b(n) + diff == +2, flipping left/right and -1/+1]
– Let c = left(n), the taller of the children
– Case 1a: b(c) == -1 // zig-zig case
• rotateRight(n), b(n) = b(c) = 0, removeFix(p, ndiff)
– Case 1b: b(c) == 0 // zig-zig case
• rotateRight(n), b(n) = -1, b(c) = +1 // Done! Note:
– Case 1c: b(c) == +1 // zig-zag case p = parent of n
• Let g = right(c) n = current node
• rotateLeft(c) then rotateRight(n) c = taller child of n
• If b(g) was +1 then b(n) = 0, b(c) = -1, b(g) = 0
g = grandchild of n
• If b(g) was 0 then b(n) = 0, b(c) = 0, b(g) = 0
• If b(g) was -1 then b(n) = +1, b(c) = 0, b(g) = 0
• removeFix(p, ndiff);
• Case 2: b(n) + diff == -1: then b(n) = -1; // Done!
• Case 3: b(n) + diff == 0: then b(n) = 0, removeFix(p, ndiff)
© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
43

Why this Works (Zig-zig version)


h+2
g p

h+2 h+1
p n g
h
(-)
h+1 n c
h+1 h or h or h+1 h
or h h-1 h-1 or h

h or h or
h-1 h-1

This is symmetrical if p and n are Note the change in height of the


right children. tree, thus the necessity to continue
calling removeFix

© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
44

Why this Works (Zig-zag version)


g n

h+2
p p g
h
(-)
c h+1 n
h h h or h or h
h-1 h-1

h or h or
h-1 h-1

This is symmetrical if p is a right Note the change in height of the


child while n is a left child. tree, thus the necessity to continue
calling removeFix

© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
45

Remove Examples
Remove 15
-1 20 -1 20

n
0 10 -1 30 -1 10 -1 30

n
0 5 1 12 0 25 05 0 12 0 25

0 15 0 15
0 3 0 8 0 3 0 8

Remove 3
-1 20
-1 20

-1 10 -1 30
-1 10 -1 30

n n
05 0 12 0 25 15 0 12 0 25

0 3 0 8 0 3 0 8
© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
46

Remove Examples
Remove 30
n
-1 20 -1 20

n -1 10 0 25
-1 10 -1 30

0 12 1 5 0 12
1 5 0 25

0 8 0 8

Zig-zig & b(c) = -1 =>


n b(n) = b(c) = 0
-2 20
c
0 10

c n
-1 10 0 25 0 20
1 5
g
1 5 0 12 0 12 0 25
0 8

0 8
© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
47

Remove Examples
Remove 20
n n n
-1 20 -1 22 -2 22
succ(n)
c
1 10 1 22 1 10 1 20 0 25
1 10
g
0 5 -1 12 0 25 0 5 -1 12 0 25
0 5 -1 12

0 11 0 11 0 11

Zig-zag & b(g) = -1 =>


b(n) = +1, b(c) = 0, b(g) = 0
g
0 12

c n
0 10 1 22

0 5 0 11 0 25

© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
48

Remove Example 1
Remove 8

-1 20

1 10 -1 30

-1 8 -1 15 1 25 0 35

05 1 12 0 17 028

0 14

© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
49

Remove Example 1
Remove 8 Zig-zag & b(g) = 0 =>
b(n) = -1, b(c) = 0
p
-1 20 -1 20 -1 20
n g
1 10 -1 30 2 10 -1 30 0 12 -1 30
c n c
-1 8 -1 15 1 25 0 35 0 5 -1 15 1 25 0 35 -1 10 0 15 1 25 0 35

g 1
05 1 12 0 17 028 12 0 17 028 0 14 0 17 028
0 5

0 14 0 14

n 0
20

0 12 -1 30

-1 10 0 15 1 25 0 35

0 0 14 0 17 028
5
© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
50

Remove Example 2
Remove 10

-1 20

1 10 -1 30

-1 8 -1 15 1 25 0 35

05 -1 12 0 17 028

0 11

© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
51

Remove Example 2
Remove 10

-1 20 -1 20

-1 30 1 11 -1 30
1 10

-1 15 -1 8 -1 15 1 25 0 35
-1 8 1 25 0 35
n
05 -1 12 0 17 028
05 0 12 0 17 028

0 11 0 10

n
-1 20 -1 20 0 20
n
-1 30 -1 30 1 11 -1 30
1 11 0 11
n
-1 8 0 15 1 25 0 35 -1 8 0 15 1 25 0 35 -1 8 0 15 1 25 0 35

05 0 12 0 17 028 05 0 12 0 17 028 05 0 12 0 17 028

© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
52

Remove Example 3
Remove 30

-1 20

1 10 -1 30

-1 8 -1 15 1 25 0 35

05 1 12 0 17 028

0 14

© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
53

Remove Example 3 else if b(c) == 1 (zig-zag case)


• rotateLeft(c) then rotateRight(n)
• Let g = right(c), b(g) = 0
Remove 30 • If b(g) == +1 then b(n) = 0, b(c) = -1, b(g) = 0
• If b(g) == 0 then b(n) = b(c) = 0, b(g) = 0
-1 20 -1 20 • If b(g) == -1 then b(n) = +1, b(c) = 0, b(g) = 0
• removeFix(parent(p), ndiff);

1 10 -1 30 1 10 -1 35

-1 8 -1 15 1 25 0 35 -1 8 -1 15 1 25 0 30

05 1 12 0 17 028 05 1 12 0 17 028

0 14 0 14

-1 20 n -2
20
n c
1 10 -2 35 1 10 0 28
g
c
-1 8 -1 15 1 25 -1 8 -1 15 0 25 0 35
g
05 1 12 0 17 028 05 1 12 0 17

0 14 0 14
© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
54

Remove Example 3 (cont) else if b(c) == 1 (zig-zag case)


• rotateLeft(c) then rotateRight(n)
• Let g = right(c), b(g) = 0
Remove 30 (cont.) • If b(g) == +1 then b(n) = 0, b(c) = -1, b(g) = 0
• If b(g) == 0 then b(n) = b(c) = 0, b(g) = 0
• If b(g) == -1 then b(n) = +1, b(c) = 0, b(g) = 0
n 0 • removeFix(parent(p), ndiff);
15

0 10 1 20

1 12 0 17 0 28
-1 8

05 0 14 0 25 0 35

© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
55

Remove Exercise
Remove 35

-1 20

1 10 -1 30

-1 8 -1 15 1 25 0 35

05 1 12 0 17 028

0 14

© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
56

Online Tool
• https://www.cs.usfca.edu/~galles/visualization/AVLtree.html

© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
57

Distribute these 4 to students

FOR PRINT

© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
58

Insert(n)
• If empty tree => set n as root, b(n) = 0, done!
• Else insert n (by walking the tree to a leaf, p, and
inserting the new node as its child), set balance
-1 12
to 0, and look at its parent, p
0 10 0 20
– If b(p) was -1, then b(p) = 0. Done!
– If b(p) was +1, then b(p) = 0. Done! 1 12

– If b(p) was 0, then update b(p) and call insert-fix(p, n) 0 10 0 20

-1
0 12

0 10

© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
59

Insert-fix(p, n)
General Idea:
Work up ancestor
• Precondition: p and n are balanced: {-1,0,-1} chain updating
• Postcondition: g, p, and n are balanced: {-1,0,-1} balances of the
ancestor chain or
• If p is null or parent(p) is null, return fix a node that is
• Let g = parent(p) out of balance.

• Assume p is left child of g [For right child swap left/right, +/-]


– b(g) += -1 // Update g's balance to new accurate value for now
– Case 1: b(g) == 0, return
– Case 2: b(g) == -1, insertFix(g, p) // recurse Note: If you
– Case 3: b(g) == -2 perform a
rotation to fix a
• If zig-zig then rotateRight(g); b(p) = b(g) = 0 node that is out
• If zig-zag then rotateLeft(p); rotateRight(g); of balance you
– Case 3a: b(n) == -1 then b(p) = 0; b(g) = +1; b(n) = 0; will NOT need
– Case 3b: b(n) == 0 then b(p) = 0; b(g) = 0; b(n) = 0; to recurse. You
– Case 3c: b(n) == +1 then b(p)= -1; b(g) = 0; b(n) = 0;
are done!
© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
60

Remove
• Find node, n, to remove by walking the tree
• If n has 2 children, swap positions with in-order successor (or
predecessor) and perform the next step
– Recall if a node has 2 children we swap with its successor or predecessor who
can have at most 1 child and then remove that node
• Let p = parent(n)
• If p is not NULL,
– If n is a left child, let diff = +1
– If n is a left child to be removed, the right subtree now has greater height, so add diff = +1 to
balance of its parent
– if n is a right child, let diff = -1
– If n is a right child to be removed, the left subtree now has greater height, so add diff = -1 to
balance of its parent
– diff will be the amount added to updated the balance of p
• Delete n and update pointers
• “Patch tree” by calling removeFix(p, diff);
© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
61

RemoveFix(n, diff)
• If n is null, return
• Compute next recursive call's arguments now before altering the tree
– Let p = parent(n) and if p is not NULL let ndiff (nextdiff) = +1 if n is a left child and -1 otherwise
• Assume diff = -1 and follow the remainder of this approach, mirroring if diff = +1
• Case 1: b(n) + diff == -2
– [Perform the check for the mirror case where b(n) + diff == +2, flipping left/right and -1/+1]
– Let c = left(n), the taller of the children
– Case 1a: b(c) == -1 // zig-zig case
• rotateRight(n), b(n) = b(c) = 0, removeFix(p, ndiff)
– Case 1b: b(c) == 0 // zig-zig case
• rotateRight(n), b(n) = -1, b(c) = +1 // Done! Note:
– Case 1c: b(c) == +1 // zig-zag case p = parent of n
• Let g = right(c) n = current node
• rotateLeft(c) then rotateRight(n) c = taller child of n
• If b(g) was +1 then b(n) = 0, b(c) = -1, b(g) = 0
g = grandchild of n
• If b(g) was 0 then b(n) = 0, b(c) = 0, b(g) = 0
• If b(g) was -1 then b(n) = +1, b(c) = 0, b(g) = 0
• removeFix(p, ndiff);
• Case 2: b(n) + diff == -1: then b(n) = -1; // Done!
• Case 3: b(n) + diff == 0: then b(n) = 0, removeFix(p, ndiff)
© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
62

OLD ALTERNATE METHOD

© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
63

Insert
• Root => set balance, done!
• Insert, v, and look at its parent, p
– If b(p) = -1, then b(p) = 0. Done!
– If b(p) = +1, then b(p) = 0. Done!
– If b(p) = 0, then update b(p) and call insert-fix(p)

© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
64

Insert-Fix
• For input node, v
– If v is root, done.
– Invariant: b(v) = {-1, +1}
• Find p = parent(v) and assume v = left(p) [i.e. left child]
– If b(p) = 1, then b(p) = 0. Done!
– If b(p) = 0, then b(p) = -1. Insert-fix(p).
– If b(p) = -1 and b(v) = -1 (zig-zig), then b(p) = 0, b(v) = 0, rightRotate(p)
Done!
– If b(p) = -1 and b(v) = 1 (zig-zag), then
• u = right(v), b(u) = 0, leftRotate(n), rightRotate(p)
• If b(u) = -1, then b(v) = 0, b(p) = 1
• If b(u) = 1, then b(v) = -1, b(p) = 0
• Done!

© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
65

Remove
• Let n = node to remove (perform BST find)
• If n has 2 children, swap positions with in-order successor (or
predecessor) and perform the next step
– If you had to swap, let n be the node with the original value that just
swapped down to have 0 or 1 children guaranteed
• Let p = parent(n)
• If n is not in the root position (i.e. p is not NULL) determine its
relationship with its parent
– If n is a left child, let diff = +1
– if n is a right child, let diff = -1
• Delete n and "patch" the tree (update pointers including root)
• removeFix(p, diff);
© 2022 by Mark Redekopp. This content is protected and may not be shared, uploaded, or distributed.
66

RemoveFix(n, diff)
• If n is null, return
• Compute next recursive call's arguments now before we alter the tree
– Let p = parent(n) and if p is not NULL let ndiff = +1 if n is a left child and -1 otherwise
• Assume diff = -1 and follow the remainder of this approach, mirroring if diff = +1
• If (n.balance + diff == -2)
– [Perform the check for the mirror case where n.balance + diff == +2, flipping left/right and -1/+1]
– Let c = left(n), the taller of the children
Note:
– If c.balance == -1 or 0 (zig-zig case)
p = parent of n
• rotateRight(n)
n = current node
• if c.balance was -1 then n.balance = c.balance = 0, removeFix(p, ndiff)
c = taller child of n
• if c.balance was 0 then n.balance = -1, c.balance = +1, done!
g = grandchild of n
– else if c.balance == 1 (zig-zag case)
• Let g = right(c)
• rotateLeft(c) then rotateRight(n)
• If g.balance was +1 then n.balance = 0, c.balance = -1, g.balance = 0
• If g.balance was 0 then n.balance = c.balance = 0, g.balance = 0
• If g.balance was -1 then n.balance = +1, c.balance = 0, g.balance = 0
• removeFix(p, ndiff);
• else if (n.balance + diff == -1) then n.balance = -1, done!
© 2022 by•Mark Redekopp.
else (if Thisn.balance
content is protected +
anddiff
may not== 0) n.balance
be shared, = 0, removeFix(p, ndiff)
uploaded, or distributed.

You might also like