0% found this document useful (0 votes)
3 views51 pages

Python Week7 Lecture4 Handout

The document discusses dynamic sorted data structures, specifically focusing on binary search trees (BST) for efficient insertion, deletion, and searching of values. It explains the structure of a BST, the implementation of various operations such as insertion, deletion, finding minimum and maximum values, and traversing the tree using inorder traversal. The document also includes Python code snippets for creating and manipulating a BST.

Uploaded by

ramkeerrthana23
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)
3 views51 pages

Python Week7 Lecture4 Handout

The document discusses dynamic sorted data structures, specifically focusing on binary search trees (BST) for efficient insertion, deletion, and searching of values. It explains the structure of a BST, the implementation of various operations such as insertion, deletion, finding minimum and maximum values, and traversing the tree using inorder traversal. The document also includes Python code snippets for creating and manipulating a BST.

Uploaded by

ramkeerrthana23
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/ 51

NPTEL MOOC

PROGRAMMING,
DATA STRUCTURES AND
ALGORITHMS IN PYTHON
Week 7, Lecture 4

Madhavan Mukund, Chennai Mathematical Institute


http://www.cmi.ac.in/~madhavan
Dynamic sorted data

Sorting is useful for efficient searching

What if the data is changing dynamically?

Items are periodically inserted and deleted

Insert/delete in sorted list take time O(n)

Like priority queues, move to a tree structure


Binary search tree
For each node with 5
value v

Values in left
subtree < v 2 8

Values in right
subtree > v
1 4 9
No duplicate values
Binary search tree
For each node with 5
value v

Values in left
subtree < v 2 8

Values in right
subtree > v
1 4 9
No duplicate values
Binary search tree
For each node with 5
value v

Values in left
subtree < v 2 8

Values in right
subtree > v
1 4 9
No duplicate values
Binary search tree
For each node with 5
value v

Values in left
subtree < v 2 8

Values in right
subtree > v
1 4 9
No duplicate values
Binary search tree
For each node with 5
value v

Values in left
subtree < v 2 8

Values in right
subtree > v
1 4 9
No duplicate values
Binary search tree
Each node has a value and points to its children
value left right

5 5

8 None
2 8
9 None None

1 None None 1 4 9
4 None None
A better representation

Add a frontier with empty node: all fields None

Empty tree is a single empty node

Leaf node has value that is not None, left and right
children point to empty nodes

Makes it easier to write recursive functions to


traverse the tree
Binary search tree 5

value left right


2 8
5

1 4 9
2 8 None

1 None None 9 None None

4 None None
Binary search tree 5

value left right


2 8
5

1 4 9
2 8

None
1 None 9
None
None None
None None
4 None None
None None
None None None None
None None
None None
None None
The class Tree
class Tree:
def __init__(self,initval=None):
self.value = initval
if self.value:
self.left = Tree()
self.right = Tree()
else:
self.left = None
self.right = None
return()
def isempty(self):
return(self.value == None)
Inorder traversal
def inorder(self): 5
if self.isempty():
return([])
else:
return(
2 8
self.left.inorder() +
[self.value] +
self.right.inorder()
)
1 4 9
def __str__(self):
return(str(self.inorder())
Inorder traversal
def inorder(self): 5
if self.isempty():
return([])
else:
return(
2 8
self.left.inorder() +
[self.value] +
self.right.inorder()
)
1 4 9
def __str__(self):
return(str(self.inorder())
Inorder traversal
def inorder(self): 5
if self.isempty():
return([])
else:
return(
2 8
self.left.inorder() +
[self.value] +
self.right.inorder()
)
1 4 9
def __str__(self):
return(str(self.inorder())
Inorder traversal
def inorder(self): 5
if self.isempty():
return([])
else:
return(
2 8
self.left.inorder() +
[self.value] +
self.right.inorder()
)
1 4 9
def __str__(self):
return(str(self.inorder())
Inorder traversal
def inorder(self): 5
if self.isempty():
return([])
else:
return(
2 8
self.left.inorder() +
[self.value] +
self.right.inorder()
)
1 4 9
def __str__(self):
return(str(self.inorder())

1
Inorder traversal
def inorder(self): 5
if self.isempty():
return([])
else:
return(
2 8
self.left.inorder() +
[self.value] +
self.right.inorder()
)
1 4 9
def __str__(self):
return(str(self.inorder())

1 2
Inorder traversal
def inorder(self): 5
if self.isempty():
return([])
else:
return(
2 8
self.left.inorder() +
[self.value] +
self.right.inorder()
)
1 4 9
def __str__(self):
return(str(self.inorder())

1 2 4
Inorder traversal
def inorder(self): 5
if self.isempty():
return([])
else:
return(
2 8
self.left.inorder() +
[self.value] +
self.right.inorder()
)
1 4 9
def __str__(self):
return(str(self.inorder())

1 2 4 5
Inorder traversal
def inorder(self): 5
if self.isempty():
return([])
else:
return(
2 8
self.left.inorder() +
[self.value] +
self.right.inorder()
)
1 4 9
def __str__(self):
return(str(self.inorder())

1 2 4 5 8
Inorder traversal
def inorder(self): 5
if self.isempty():
return([])
else:
return(
2 8
self.left.inorder() +
[self.value] +
self.right.inorder()
)
1 4 9
def __str__(self):
return(str(self.inorder())

Lists values in sorted order 1 2 4 5 8 9


Find a value v

Scan the current node

Go left if v is smaller than this node

Go right if v is larger than this node

Natural generalization of binary search


Find a value v
def find(self,v):

if self.isempty():
return(False)

if self.value == v:
return(True)

if v < self.value:
return(self.left.find(v))
else
return(self.right.find(v))
Minimum
Left most node in the tree
5
def minval(self):

# Assume t is not empty 3 7


if self.left == None:
return(self.value) 1 4 9
else:
return(self.left.minval()) 2 8
Maximum
Right most node in the tree
5
def maxval(self):

# Assume t is not empty 3 7


if self.right == None:
return(self.value) 1 4 9
else:
return(self.right.maxval()) 2 8
Insert v
Insert 21
Try to find v
52
If it is not present, add it
where the search fails 37 74

16 44 91

28 83
Insert v
Insert 21
Try to find v
52
If it is not present, add it
where the search fails 37 74

16 44 91

28 83
Insert v
Insert 21
Try to find v
52
If it is not present, add it
where the search fails 37 74

16 44 91

28 83

21
Insert v
Insert 65
Try to find v
52
If it is not present, add it
where the search fails 37 74

16 44 91

28 83

21
Insert v
Insert 65
Try to find v
52
If it is not present, add it
where the search fails 37 74

16 44 91

28 83

21
Insert v
Insert 65
Try to find v
52
If it is not present, add it
where the search fails 37 74

16 44 65 91

28 83

21
Insert v
Insert 91
Try to find v
52
If it is not present, add it
where the search fails 37 74

16 44 65 91

28 83

21
Insert v
Insert 91
Try to find v
52
If it is not present, add it
where the search fails 37 74

16 44 65 91

28 83

21
Insert v
def insert(self,v):

if self.isempty(): # Add v as a new leaf


self.value = v
self.left = Tree()
self.right = Tree()

if self.value == v: # Value found, do nothing


return

if v < self.value:
self.left.insert(v)
return

if v > self.value:
self.right.insert(v)
return
Delete v
If v is present, delete it Delete 65
If deleted node is a leaf, done
52
If deleted node has only one child,
“promote” that child 37 74

If deleted node has two children,


fill in the hole with 16 44 65 91
self.left.maxval() (or
self.right.minval()) 28 83

Delete self.left.maxval()—
must be leaf or have only one child 21
Delete v
If v is present, delete it Delete 65
If deleted node is a leaf, done
52
If deleted node has only one child,
“promote” that child 37 74

If deleted node has two children,


fill in the hole with 16 44 65 91
self.left.maxval() (or
self.right.minval()) 28 83

Delete self.left.maxval()—
must be leaf or have only one child 21
Delete v
If v is present, delete it Delete 65
If deleted node is a leaf, done
52
If deleted node has only one child,
“promote” that child 37 74

If deleted node has two children,


fill in the hole with 16 44 91
self.left.maxval() (or
self.right.minval()) 28 83

Delete self.left.maxval()—
must be leaf or have only one child 21
Delete v
If v is present, delete it Delete 74
If deleted node is a leaf, done
52
If deleted node has only one child,
“promote” that child 37 74

If deleted node has two children,


fill in the hole with 16 44 91
self.left.maxval() (or
self.right.minval()) 28 83

Delete self.left.maxval()—
must be leaf or have only one child 21
Delete v
If v is present, delete it Delete 74
If deleted node is a leaf, done
52
If deleted node has only one child,
“promote” that child 37 74

If deleted node has two children,


fill in the hole with 16 44 91
self.left.maxval() (or
self.right.minval()) 28 83

Delete self.left.maxval()—
must be leaf or have only one child 21
Delete v
If v is present, delete it Delete 74
If deleted node is a leaf, done
52
If deleted node has only one child,
“promote” that child 37 91

If deleted node has two children, 83


fill in the hole with 16 44
self.left.maxval() (or
self.right.minval()) 28

Delete self.left.maxval()—
must be leaf or have only one child 21
Delete v
If v is present, delete it Delete 37
If deleted node is a leaf, done
52
If deleted node has only one child,
“promote” that child 37 91

If deleted node has two children, 83


fill in the hole with 16 44
self.left.maxval() (or
self.right.minval()) 28

Delete self.left.maxval()—
must be leaf or have only one child 21
Delete v
If v is present, delete it Delete 37
If deleted node is a leaf, done
52
If deleted node has only one child,
“promote” that child 37 91

If deleted node has two children, 83


fill in the hole with 16 44
self.left.maxval() (or
self.right.minval()) 28

Delete self.left.maxval()—
must be leaf or have only one child 21
Delete v
If v is present, delete it Delete 37
If deleted node is a leaf, done
52
If deleted node has only one child,
“promote” that child 37 91

If deleted node has two children, 83


fill in the hole with 16 44
self.left.maxval() (or
self.right.minval()) 28

Delete self.left.maxval()—
must be leaf or have only one child 21
Delete v
If v is present, delete it Delete 37
If deleted node is a leaf, done
52
If deleted node has only one child,
“promote” that child 28 91

If deleted node has two children, 83


fill in the hole with 16 44
self.left.maxval() (or
self.right.minval()) 28

Delete self.left.maxval()—
must be leaf or have only one child 21
Delete v
If v is present, delete it Delete 37
If deleted node is a leaf, done
52
If deleted node has only one child,
“promote” that child 28 91

If deleted node has two children, 83


fill in the hole with 16 44
self.left.maxval() (or
self.right.minval()) 21

Delete self.left.maxval()—
must be leaf or have only one child
Delete v
If v is present, delete it

If deleted node is a leaf, done


52
If deleted node has only one child,
“promote” that child 28 91

If deleted node has two children, 83


fill in the hole with 16 44
self.left.maxval() (or
self.right.minval()) 21

Delete self.left.maxval()—
must be leaf or have only one child
Delete v
def delete(self,v):
if self.isempty():
return

if v < self.value:
self.left.delete(v)
return

if v > self.value:
self.right.delete(v)
return

if v == self.value:
if self.isleaf():
self.makeempty()
elif self.left.isempty():
self.copyright()
else:
self.value = self.left.maxval()
self.left.delete(self.left.maxval())
return
Delete v # Convert leaf to
# empty node
def delete(self,v): def makeempty(self):
if self.isempty(): self.value = None
return self.left = None
self.right = None
if v < self.value:
return
self.left.delete(v)
return

if v > self.value:
self.right.delete(v)
return

if v == self.value:
if self.isleaf():
self.makeempty()
elif self.left.isempty():
self.copyright()
else:
self.value = self.left.maxval()
self.left.delete(self.left.maxval())
return
Delete v # Convert leaf to
# empty node
def delete(self,v): def makeempty(self):
if self.isempty(): self.value = None
return self.left = None
self.right = None
if v < self.value:
return
self.left.delete(v)
return

if v > self.value: # Copy right child values


self.right.delete(v) # to current node
return def copyright(self):
self.value = self.right.value
if v == self.value:
self.left = self.right.left
if self.isleaf():
self.right = self.right.right
self.makeempty()
elif self.left.isempty():
return
self.copyright()
else:
self.value = self.left.maxval()
self.left.delete(self.left.maxval())
return
Complexity

All operations on search trees walk down a single


path

Worst-case: height of the tree

Balanced trees: height is O(log n) for n nodes

Tree can be balanced using rotations — look up


AVL trees

You might also like