7 Trees3

You might also like

Download as pptx, pdf, or txt
Download as pptx, pdf, or txt
You are on page 1of 65

AVL TREES (Summary)

• We want binary search tree operations to


perform in O(log N) time.

• With normal BSTs, there is a possibility that


the height may go beyond O(log N) and
towards O(N).
• If we need to guarantee that every BST
operation performs in O(log N) time, we must
ensure that the height is O(log N) ⇒
BALANCED TREES
1
AVL TREES (Summary)
• AVL Trees
– An empty binary tree is an AVL tree
– If T is a non-empty binary tree with TL and TR
as its left and right subtrees, then T is an
AVL tree if
• TL and TR are AVL trees, and
• | Height(TL) – Height(TR) | ≤ 1
• An AVL Search Tree is an AVL Tree with
the BST Property.
2
AVL TREES (Summary)
• Let S(h) be the minimum number of
nodes of an AVL tree of height h.

• h = O(log N)

• For every N, there is an AVL tree of N


nodes.

3
IMPLEMENTING AVL TREES
• The private data needs another field to
keep the height of the node.

• The height is maintained by adding 1 to


the maximum of the heights of the
children nodes.

4
IMPLEMENTING AVL TREES
• The find, findMin and findMax operations
are just like in BinarySearchTrees
• The makeEmpty, operator=, printTree
etc., are all same.

• The insert and remove operations are


different since they have to guarantee the
AVL-tree property.

5
INSERTING TO AN AVL TREE
Suppose we insert 6 to the AVL tree.

5
Height difference (balance factor) is 2
2
2 5
8 -1 (right subtree is empty)

1 4 7 1

3 6 0

6
INSERTING TO AN AVL TREE
Suppose we insert 6 to the previous AVL tree.

8 is the node whose balance is disrupted


5
We should reorganize the tree rooted at 8.
2
2 5
8

1 4 7 1

3 6 0

7
INSERTING TO AN AVL TREE
Suppose we insert 6 to the previous AVL tree.
3 Now this is
5 5 balanced.

2 2 1

2 5
8 2 7

Rotate around 7

1 4 7 1 1 4 6 8 0
0

3 6 0 3

8
INSERTING TO AN AVL TREE
• Just insert like a normal BST insert

9
INSERTING TO AN AVL TREE
• Let’s define the balance factor as the
difference between the heights of left and
right subtrees.
• Some nodes may become unbalanced, that is
have their balance factors become 2 (from 1)
or –2 (from –1).
• Only the balance factors of the nodes on the
path from the root to the newly inserted node
may change.

10
INSERTING TO AN AVL TREE
• Just insert like a normal BST insert
• Only nodes on the path from the inserted
node to the root may have their subtrees
altered 5

2
2 85

1 4 7 1

3 6 0

11
INSERTING TO AN AVL TREE
• Just insert like a normal BST insert
• Only nodes on the path from the inserted
node to the root may have their subtrees
altered 5

•As we follow from the 2

inserted node up 2 85

towards the root


updating the heights we 1 4 7 1

may find a node whose


new balance violates the 3 6 0
AVL condition.
12
INSERTING TO AN AVL TREE
• Fixing the subtree rooted at the deepest such
node guarantees that the whole tree has the
AVL property.
5
2

2 85

1 4 7 1

3 6 0

13
INSERTING TO AN AVL TREE
• Let us call the node that must be rebalanced
as a
• Since a has at most two children and a height
imbalance requires that a’s two subtrees’
heights differ by two, there are four cases to
consider:

14
IMBALANCE CASE 1
a k2
h+2 (was h+1)

h+1
(was h)
k1

h-1
h-1 Z
h
(was Y
h-1) X

The insertion is into the left subtree of the left child of a

15
IMBALANCE CASE 1
h+2 (was h+1)
a k2 k1 h+1
Single Rotation
h+1
(was h)
k1 h
k2 h

h-1
h
h-1 Z h-1
(was h-1) h-1
Y X Y Z
X

The insertion is into the left subtree of the left child of a

16
IMBALANCE CASE 1 EXAMPLE

5 5

2 5
8 k2 2 7 k1

8
1 4 7
k1 1 4 6 k2

3 6 3

17
IMBALANCE CASE 2
k1 a

k2

The insertion is into the right subtree of the right child of a


(symmetric situation)
18
IMBALANCE CASE 2
k1 a k2

k2 k1

Y X Y Z

The insertion is into the right subtree of the right child of a


(symmetric situation)
19
IMBALANCE CASE 2 EXAMPLE

1 k1
3

4 k2

20
IMBALANCE CASE 2 EXAMPLE

2 2

1 k1
3 1 4 k2

4 k2 k1 3 5

21
IMBALANCE CASE 3
a k2

k1

X Y

The insertion is into the right subtree of the left child of a

22
IMBALANCE CASE 3
a k2 k1

k1 k2

Z X

X Y Y Z

The insertion is into the right subtree of the left child of a

Single rotation does not solve the balancing problem


23
IMBALANCE CASE 3
a k2 Let’s look at the subtree Y in more
detail.
a k3
k1

k1
Z

X Y k2
D

B C

The insertion is into the right subtree of the left child of a


24
IMBALANCE CASE 3
a k3 Double Rotation
k2

k1 k1 k3

k2
D

A B C D
A

B C

The insertion is into the right subtree of the left child of a

25
IMBALANCE CASE 3 EXAMPLE
a k3 14

3 17

k1
1 5 19

k2
D
0 2 4 7

B C 8

26
IMBALANCE CASE 3 EXAMPLE
k2 5

3
14
k1 k3
1 4 7 17

19
14 0 2 8
A B C D

3 17

1 5

19

0 2 4 7

8 27
INBALANCE CASE 4

k1 a Double Rotation k2

k1 k3
k3

k2
A
A B C D
D

B C

The insertion is into the left subtree of the right child of a

28
Single Rotation vs. Double Rotation
• Single rotation if insertion occurs on
the “outside”
• An insertion into the left subtree of
the left child of a (Case 1)
• An insertion into the right subtree
of the right child of a (Case 2)

29
Single Rotation vs. Double Rotation
• Double rotation if insertion occurs on
the “inside”
• An insertion into the right subtree
of the left child of a (Case 3)
• An insertion into the left subtree of
the right child of a (Case 4)

30
IMPLEMENTING AVL TREES
template <class Comparable>
class AvlTree;

template <class Comparable>


class AvlNode
{
Comparable element;
AvlNode *left;
AvlNode *right;
int height;

AvlNode( const Comparable & theElement,


AvlNode *lt, AvlNode *rt, int h = 0 )
: element( theElement ), left( lt ), right( rt ), height( h ) { }

friend class AvlTree<Comparable>;


};
31
IMPLEMENTING AVL TREES
template <class Comparable>
class AvlTree
{
public:
explicit AvlTree( const Comparable & notFound );
AvlTree( const AvlTree & rhs );
~AvlTree( );

const Comparable & findMin( ) const;


const Comparable & findMax( ) const;
const Comparable & find( const Comparable & x ) const;
bool isEmpty( ) const;
void printTree( ) const;

void makeEmpty( );
void insert( const Comparable & x );
void remove( const Comparable & x );

const AvlTree & operator=( const AvlTree & rhs ); 32


IMPLEMENTING AVL TREES
AvlNode<Comparable> *root;
const Comparable ITEM_NOT_FOUND;

const Comparable & elementAt( AvlNode<Comparable> *t ) const;

void insert( const Comparable & x, AvlNode<Comparable> * & t ) const;


void remove(const Comparable & x, AvlNode<Comparable> * & t ) const;

AvlNode<Comparable> * findMin( AvlNode<Comparable> *t ) const;


AvlNode<Comparable> * findMax( AvlNode<Comparable> *t ) const;
AvlNode<Comparable> * find( const Comparable & x, AvlNode<Comparable> *t )
const;
void makeEmpty( AvlNode<Comparable> * & t ) const;
void printTree( AvlNode<Comparable> *t ) const;
AvlNode<Comparable> * clone( AvlNode<Comparable> *t ) const;

// Avl manipulations
int height( AvlNode<Comparable> *t ) const;
int max( int lhs, int rhs ) const;
void rotateWithLeftChild( AvlNode<Comparable> * & k2 ) const;
void rotateWithRightChild( AvlNode<Comparable> * & k1 ) const;
void doubleWithLeftChild( AvlNode<Comparable> * & k3 ) const;
void doubleWithRightChild( AvlNode<Comparable> * & k1 ) const;
}; 33
COMPUTING THE HEIGHT

/**
* Return the height of node t, or -1, if NULL.
*/
template <class Comparable>
int AvlTree<Comparable>::height( AvlNode<Comparable> *t )
const
{
if (t == NULL)
return -1;

return t->height;
}

34
(private) max
/**
* Return maximum of lhs and rhs.
*/
template <class Comparable>
int AvlTree<Comparable>::max( int lhs, int rhs )
const
{
if (lhs > rhs)
return lhs;

return rhs;
}

35
(private) INSERT
template <class Comparable>
void AvlTree<Comparable>::insert
( const Comparable & x, AvlNode<Comparable> * & t ) const
{
if ( t == NULL )
t = new AvlNode<Comparable>( x, NULL, NULL );

else if ( x < t->element ) {


// X should be inserted to the left tree!
insert( x, t->left );

// Check if the left tree is out of balance (left subtree grew in height!)
if ( height( t->left ) - height( t->right ) == 2 )
if ( x < t->left->element ) // X was inserted to the left-left subtree!
rotateWithLeftChild( t );
else // X was inserted to the left-right subtree!
doubleWithLeftChild( t );
}

36
(private) INSERT
else if( t->element < x )
{ // Otherwise X is inserted to the right subtree
insert( x, t->right );
if ( height( t->right ) - height( t->left ) == 2 )
// height of the right subtree increased
if ( t->right->element < x )
// X was inserted to right-right subtree
rotateWithRightChild( t );
else // X was inserted to right-left subtree
doubleWithRightChild( t );
}
else
; // Duplicate; do nothing

// update the height the node


t->height = max( height( t->left ), height( t->right ) ) + 1;
}
37
ROTATIONS-rotateWithLeftChild
/**
* Rotate binary tree node with left child.
* For AVL trees, this is a single rotation for case 1.
* Update heights, then set new root.
*/
template <class Comparable>
void AvlTree<Comparable>::rotateWithLeftChild(
AvlNode<Comparable> * & k2 ) const
{
AvlNode<Comparable> *k1 = k2->left;
k2->left = k1->right;
k1->right = k2;
k2->height = max( height( k2->left ), height( k2->right ) ) + 1;
k1->height = max( height( k1->left ), k2->height ) + 1;
k2 = k1;
}
38
ROTATIONS-rotateWithLeftChild
void AvlTree<Comparable>::
rotateWithLeftChild( AvlNode<Comparable> * & k2 ) const
{
AvlNode<Comparable> *k1 = k2->left;
k2->left = k1->right;
k1->right = k2;
k2->height = max( height( k2->left ), height( k2->right ) ) + 1;
k1->height = max( height( k1->left ), k2->height ) + 1;
k2 = k1;
} k2 h+2 (was h+1)

h+1(was h) k1

h-1
h-1
Z
h (was h-1)
Y
X
39
ROTATIONS-rotateWithLeftChild
void AvlTree<Comparable>::
rotateWithLeftChild( AvlNode<Comparable> * & k2 ) const
{
AvlNode<Comparable> *k1 = k2->left;
k2->left = k1->right;
k1->right = k2;
k2->height = max( height( k2->left ), height( k2->right ) ) + 1;
k1->height = max( height( k1->left ), k2->height ) + 1;
k2 = k1;
}
k1 k2 h+2 (was h+1)

h+1
(was h)

h-1
h-1
Z
h
(was h-1) Y
X
40
ROTATIONS-rotateWithLeftChild
void AvlTree<Comparable>::
rotateWithLeftChild( AvlNode<Comparable> * & k2 ) const
{
AvlNode<Comparable> *k1 = k2->left;
k2->left = k1->right;
k1->right = k2;
k2->height = max( height( k2->left ), height( k2->right ) ) + 1;
k1->height = max( height( k1->left ), k2->height ) + 1;
k2 = k1;
} k2 h+2 (was h+1)
k1

h+1
(was h)

h-1
h-1
Z
h
(was h-1) Y
X
41
ROTATIONS-rotateWithLeftChild
void AvlTree<Comparable>::
rotateWithLeftChild( AvlNode<Comparable> * & k2 ) const
{
AvlNode<Comparable> *k1 = k2->left;
k2->left = k1->right;
k1->right = k2;
k2->height = max( height( k2->left ), height( k2->right ) ) + 1;
k1->height = max( height( k1->left ), k2->height ) + 1;
k2 = k1;
} k2 h+2 (was h+1)
k1

h+1
(was h)

h-1
h-1
Z
h
(was h-1) Y
X
42
ROTATIONS-rotateWithLeftChild
void AvlTree<Comparable>::rotateWithLeftChild ( AvlNode<Comparable> * & k2 ) const
{
AvlNode<Comparable> *k1 = k2->left;
k2->left = k1->right;
k1->right = k2;
k2->height = max( height( k2->left ), height( k2->right ) ) + 1;
k1->height = max( height( k1->left ), k2->height ) + 1;
k2 = k1;
}
k2 h
k1

h+1
(was h)

h-1
h-1
Z
h
(was h-1) Y
X
43
ROTATIONS-rotateWithLeftChild
void AvlTree<Comparable>:: rotateWithLeftChild( AvlNode<Comparable> * & k2 ) const
{
AvlNode<Comparable> *k1 = k2->left;
k2->left = k1->right;
k1->right = k2;
k2->height = max( height( k2->left ), height( k2->right ) ) + 1;
k1->height = max( height( k1->left ), k2->height ) + 1;
k2 = k1;
}
k2 h
k1

h+1

h-1
h-1
Z
h
(was h-1) Y
X
44
ROTATIONS-rotateWithLeftChild
void AvlTree<Comparable>::rotateWithLeftChild( AvlNode<Comparable> * & k2 ) const
{
AvlNode<Comparable> *k1 = k2->left;
k2->left = k1->right;
k1->right = k2;
k2->height = max( height( k2->left ), height( k2->right ) ) + 1;
k1->height = max( height( k1->left ), k2->height ) + 1;
k2 = k1;
} k2 h

h+1

h-1
h-1
Z
h
(was h-1) Y
X
45
ROTATIONS-rotateWithRightChild
/**
* Rotate binary tree node with right child.
* For AVL trees, this is a single rotation for case 4.
* Update heights, then set new root.
*/
template <class Comparable>
void AvlTree<Comparable>::rotateWithRightChild
( AvlNode<Comparable> * & k1 ) const
{
AvlNode<Comparable> *k2 = k1->right;
k1->right = k2->left;
k2->left = k1;
k1->height = max( height( k1->left ), height( k1->right ) ) + 1;
k2->height = max( height( k2->right ), k1->height ) + 1;
k1 = k2;
}

46
ROTATIONS-DoubleWithLeftChild
/**
* Double rotate binary tree node: first left child.
* with its right child; then node k3 with new left child.
* For AVL trees, this is a double rotation for case 2.
* Update heights, then set new root.
*/
template <class Comparable>
void AvlTree<Comparable>::doubleWithLeftChild
( AvlNode<Comparable> * & k3 ) const
{
rotateWithRightChild( k3->left );
rotateWithLeftChild( k3 );
}

47
ROTATIONS-DoubleWithLeftChild
template <class Comparable>
void AvlTree<Comparable>::doubleWithLeftChild( AvlNode<Comparable> * & k3 )
const
{
rotateWithRightChild( k3->left );
rotateWithLeftChild( k3 );
}
k3

k1

k2
D

B C
48
ROTATIONS-DoubleWithLeftChild
template <class Comparable>
void AvlTree<Comparable>::doubleWithLeftChild( AvlNode<Comparable> * & k3 )
const
{
rotateWithRightChild( k3->left );
rotateWithLeftChild( k3 );
}
k3

k2

k1
D

A B C
49
ROTATIONS-DoubleWithLeftChild
template <class Comparable>
void AvlTree<Comparable>::doubleWithLeftChild
( AvlNode<Comparable> * & k3 ) const
{
rotateWithRightChild( k3->left );
rotateWithLeftChild( k3 ); k3
}

k2

k1
D

A B C

50
ROTATIONS-DoubleWithLeftChild
template <class Comparable>
void AvlTree<Comparable>::doubleWithLeftChild
( AvlNode<Comparable> * & k3 ) const
{
rotateWithRightChild( k3->left );
rotateWithLeftChild( k3 );
}

k2

k1 k3

A B C D
51
ROTATIONS-DoubleWithRightChild
/**
* Double rotate binary tree node: first right child.
* with its left child; then node k1 with new right child.
* For AVL trees, this is a double rotation for case 3.
* Update heights, then set new root.
*/
template <class Comparable>
void AvlTree<Comparable>::doubleWithRightChild
( AvlNode<Comparable> * & k1 ) const
{
rotateWithLeftChild( k1->right );
rotateWithRightChild( k1 );
}

52
DELETIONS FROM AN AVL TREE
• Proceed as in the case of a deletion from a
BST.
– node is leaf ⇒ just delete it from the parent
– node has single child ⇒ connect child to the
grantparent node
– two children ⇒ replace with largest child from left
or smallest from right (and delete that grandchild
(which has at most 1 child)

53
DELETIONS FROM AN AVL TREE
• The deletions will upset the balance factors of
some of the remaining nodes.
• So they will have to be re-balanced.

54
DELETION CASE 1
Before deletion
h+3

k1

h+2

k2
h+1

h+1
X Y h or h+1

Heights of subtrees
55
DELETION CASE 1
h+3 h+3
Out of balance
k1 k1

h+2 h+2

k2 h+1 k2 h
Z
Z

h+1
X Y h or h+1 X Y h or h+1

Before deletion After a deletion from subtree Z

56
DELETION CASE 1
h+3
h+2 or h+3
Out of balance k2
k1
Rotation
h+1 or h+2

h+2
k2 h k1
Z
h+1
h or h+1 h
h+1 X
Z
X Y h or h+1
Y

After a deletion from subtree Z

57
DELETION CASE 1
Now Since the height of this
Before h+3 subtree changed, the balance of its
h+2 or h+3 parent may have changed.
k2

h+1 or h+2 Thus we may have to


Rebalance all the
k1 ancestors up to the root.
h+1
At most O(log N) ancestors
h or h+1
h have to be rebalanced.
X
Z

58
DELETION CASE 1
Now The height of this subtree
Before h+3 did NOT change, so
h+2 or h+3 the balance of
k2 its parent will not change

No further action
h+1 or h+2
is necessary
k1
h+1
h or h+1
h
X
Z

59
DELETION CASE 1
• Symmetric cases are handled in a similar way

60
DELETION CASE 2
h+3 • After deletion from Z, it
k1
now has height h.
• X also has height h.
h+2 • Node k1 now has an
k2 imbalance.
h
h+1
Z
h k3

h h-1
or or
h-1 Y Y’ h

(at least ’ height h)
1 side has 61
DELETION CASE 2
h+2
h+3
k3
k1
Double Rotation
h+1
h+2
k2 k1 h+1
k2 h
h+1
Z h h h
h h-1
k3 or
h-1 or
X Y’ h Z
X Y
’ ’
h h-1
or or (at least 1 side has height h)
Y Y’ h
h-1
’ ’
(at least 1 side has height h)

62
DELETION CASE 2
• Now the height of the h+2

original subtree has k3

changed to h+2. h+1


• We now have to check
k2 k1 h+1
its parent and see if
further balancing needs h h h
to be done. or h-1
or
h-1
• At most O(log N) nodes X
Y Y’ h Z

may have to be ’
(at least 1 side has height h)
rebalanced.
• Symmetric cases are
handled similarly.

63
META-SUMMARY
Find Insert Remove
Average Worst Average Worst Average Worst
Case Case Case Case Case Case

Linked O(N) O(N) O(N) O(N) O(N) O(N)


(inc. find)
Lists

Binary
Search O(log N) O(N) O(log N) O(N) O(logN) O(N)

Trees
AVL
O(log N) O(logN) O(log N) O(log N) O(log N) O(log N)
Search
Trees 64
ROAD MAP FROM HERE ON
• Hashing
– insert/delete/find almost O(1)
– lots of wasted space
• Heaps and priority queues
– More interesting tree structures
• Sorting Algorithms
• Disjoint Sets
• Graphs and Graph Algorithms

65

You might also like