0% found this document useful (0 votes)
77 views19 pages

05 Recursion Part 2 (Merge Sort)

The document describes the recursive implementation of merge sort. It divides the array recursively into smaller sub-arrays of size 1, sorts those sub-arrays using a base case of returning a single element array, and then merges the sorted sub-arrays together using a merge function to produce the final sorted array. The recursive calls sort the sub-problems, while the merging combines the solutions to produce the final sorted list.

Uploaded by

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

05 Recursion Part 2 (Merge Sort)

The document describes the recursive implementation of merge sort. It divides the array recursively into smaller sub-arrays of size 1, sorts those sub-arrays using a base case of returning a single element array, and then merges the sorted sub-arrays together using a merge function to produce the final sorted array. The recursive calls sort the sub-problems, while the merging combines the solutions to produce the final sorted list.

Uploaded by

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

Merge Sort

✦ Last week we have seen the iterative version of merge sort


✦ The iterative definition is based on bottom-up strategy
❖ Begin with individual elements
❖ Iteratively merge groups of increasing sizes
✦ Merge sort can also be described recursively
✦ The recursive definition is based on top-down strategy
❖ Begin with the full array to be sorted
❖ Divide the array into shorter arrays to be sorted
❖ Sort the shorter arrays recursively
Merge Sort: Divide
0 1 2 3 4 5 6 7
41 31 93 15 40 32 9 70
split into two lists and
msort each shorter list
0 1 2 3 4 5 6 7

41 31 93 15 40 32 9 70
Divide

0 1 2 3 4 5 6 7

41 31 93 15 40 32 9 70

0 1 2 3 4 5 6 7

41 31 93 15 40 32 9 70
Merge Sort: Conquer
0 1 2 3 4 5 6 7
41 31 93 15 40 32 9 70

0 1 2 3 4 5 6 7

41 31 93 15 40 32 9 70
Conquer

0 1 2 3 4 5 6 7

41 31 93 15 40 32 9 70

0 1 2 3 4 5 6 7

41 31 93 15 40 32 9 70
base case only 1 item,
consider it already sorted
Merge Sort: Conquer
0 1 2 3 4 5 6 7
41 31 93 15 40 32 9 70

0 1 2 3 4 5 6 7

41 31 93 15 40 32 9 70
Conquer

0 1 2 3 4 5 6 7

31 41 15 93 32 40 9 70
merge sorted
lists
0 1 2 3 4 5 6 7

41 31 93 15 40 32 9 70
Merge Sort: Conquer
0 1 2 3 4 5 6 7
41 31 93 15 40 32 9 70

0 1 2 3 4 5 6 7

15 31 41 93 9 32 40 70
Conquer
merge sorted
lists
0 1 2 3 4 5 6 7

31 41 15 93 32 40 9 70

0 1 2 3 4 5 6 7

41 31 93 15 40 32 9 70
Merge Sort: Conquer
0 1 2 3 4 5 6 7
9 15 31 32 40 41 70 93
merge sorted
lists
0 1 2 3 4 5 6 7

15 31 41 93 9 32 40 70
Conquer

0 1 2 3 4 5 6 7

31 41 15 93 32 40 9 70

0 1 2 3 4 5 6 7

41 31 93 15 40 32 9 70
Recursive Version of Merge Sort
01 def rmSort(a):
02 if len(a) == 1:
03 return a
04 mid = len(a)//2
05 a1 = rmSort(a[0:mid])
06 a2 = rmSort(a[mid:len(a)])
07 return merge2(a1, a2)
Recursive Version of Merge Sort
01 def rmSort(a):
02 if len(a) == 1: base case – single element

03 return a
04 mid = len(a)//2
05 a1 = rmSort(a[0:mid]) recursive call to smaller instances of the
original problem
06 a2 = rmSort(a[mid:len(a)])
07 return merge2(a1, a2)
merge results from two sub-problems
Recursive Version of Merge Sort
# takes in 2 sorted lists (a1 and a2)
# returns a1 + a2 sorted
def merge2(a1, a2): Repeat as long as
i = 0 there is at least 1 element in a1 OR
j = 0 there is at least 1 element in a2
r = []
while i < len(a1) or j < len(a2):
if (j == len(a2)) or (i < len(a1) and a1[i] < a2[j]):
r.append(a1[i]) # pick item from a1
i += 1
else:
r.append(a2[j]) # pick item from a2
j += 1
return r

There is at least 1 element in a1 AND the


current element in a1 is smaller than the
current element in a2
No more elements in a2
Sequence of Calls to rmsort
0 1 2 3 4 5 6 7
41 31 93 15 40 32 9 70
1st 8th

0 1 2 3 4 5 6 7

41 31 93 15 40 32 9 70
Divide
2nd 5th 9th 12th

0 1 2 3 4 5 6 7

41 31 93 15 40 32 9 70
3rd 4th 6th 7th 10th 11th 13th 14th
0 1 2 3 4 5 6 7

41 31 93 15 40 32 9 70
Sequence of Calls to merge2
0 1 2 3 4 5 6 7
9 15 31 32 40 41 70 93
7th
0 1 2 3 4 5 6 7

15 31 41 93 9 32 40 70
Conquer
3rd 6th
0 1 2 3 4 5 6 7

31 41 15 93 32 40 9 70
1st 2nd 4th 5th
0 1 2 3 4 5 6 7

41 31 93 15 40 32 9 70
Complexity of Recursive Merge Sort

✦ Number of comparisons is the same for both iterative and recursive versions
✦ In the recursive version:
❖ There are log n levels of recursion with decreasing group size size (in the above case, it’s 8, 4,
and 2).
❖ For each level, there are (2 x n / size) recursive function calls.
❖ Each recursive function call has a merge2 operation, which conducts up to size comparisons in
the worst case.
✦ Complexity of recursive merge sort is O(n log n).
In-Class Exercise Q3
For the following input arrays, determine the state of
the array just before the final merge step for the two
versions of merge sort:
• bottom-up non-recursive version
• top-down recursive version

(a) [26, 34, 64, 83, 2, 5]

(b) [52, 30, 98, 59, 67, 4, 64, 12, 79]


Another Example: Binary Search

# iterative version of bsearch


def bsearch(array, target):
lower = -1
upper = len(array)

while not (lower + 1 == upper):


mid = (lower + upper)//2
if target == array[mid]: #success
return mid
elif target < array[mid]:
upper = mid #search lower region
else:
lower = mid #search upper region
return -1 #not found
…Another Example: Binary Search

# recursive version of bsearch


01 def rbsearch(array, target, lower=None, upper=None):
02 if lower == None: only happens when
03 lower = -1 rbsearch is called the 1st
04 upper = len(array) time
05
06 if lower + 1 == upper: # base case
07 return -1 # not found
08 mid = (lower + upper)//2
09 if array[mid] == target: # success
10 return mid
11 elif array[mid] < target: # search upper region
12 return rbsearch(array, target, mid, upper)
13 else: # search lower region
14 return rbsearch(array, target, lower, mid)
Summary

✦ An algorithm that uses divide and conquer can be written using iteration or recursion
❖ recursive = “self-similar”
❖ a problem that can be divided into smaller subproblems
❖ a recursive function calls itself
✦ Fundamentals of recursion:
❖ reduction step
❖ base case
✦ Recursive versions of:
❖ merge sort
Further reading materials

✦ Online sources:
❖ http://www.cs.uiuc.edu/~jeffe/teaching/algorithms/notes/01-recursion.pdf
❖ http://www-cs-faculty.stanford.edu/~eroberts/courses/cs106b/chapters/05-intro-to-recursion.pdf
❖ http://introcs.cs.princeton.edu/java/23recursion/

✦ Optional supplementary text (available in Library):


❖ Prichard and Carrano, Data Abstraction and Problem Solving with Java
‣ Chapter 3 “Recursion: The Mirrors”
Optional Reading:
What is “Tail Recursion”?

✦ https://stackoverflow.com/questions/33923/what-is-tail-recursion
Road Map

Algorithm Design and Analysis


(Weeks 1 - 5)

Fundamental Data Structures


Next week ✦ Week 6: Linear data structures (stack, queue)
✦ Week 7: Hierarchical data structure (binary tree)
✦ Week 9: Networked data structure (graph)
✦ Week 10: Graph Algorithms

Computational Intractability and Heuristic Reasoning


(Weeks 11 - 13)

You might also like