05 Recursion Part 2 (Merge Sort)
05 Recursion Part 2 (Merge Sort)
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
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
✦ 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/
✦ https://stackoverflow.com/questions/33923/what-is-tail-recursion
Road Map