Mergesort Divide And Conquer

Posted by VitoDH Blog on December 15, 2019

Chapter 4 - Sorting and Searching - 2 - Mergesort: Sorting by Divide-and-Conquer

Source: Algorithm Design Manual(Skiena)

1. Recursive Approach

  • Partition the elements into two groups
  • Sort each of the smaller problems recursively
  • Interleave the two sorted lists to totally order the elements

2. Analysis

Efficiency

Depends on how efficiently we combine the two sorted halves into a single sorted list

How to merge

  • The smallest overall item in two lists sorted in increasing order must sit at the top of one of the two lists
  • The smallest element can be removed, leaving two sorted lists behind
  • Using at most $n-1$ comparison or O(n) total work we can combine two lists into one

Complexity

  • In general, the work done on the kth level involves merging $2^k$ pairs sorted list, each of size $n/2^{k+1}$, for a total of at most $n-2^k$ comparisons
  • Linear work is done merging all the elements on each level. Each of the n elements appears in exactly one subproblem on each level
  • The number of elements in a subproblem gets halved at each level. So the recursion goes $log(n)$ deep
  • Total run time in the worst case $O(nlogn)$

Advantage

  • Does not rely on random access to eleements as does heapsort or quicksort

Disadvantage

  • Need an auxiliary buffer when sorting arrays

3. Implementation

We first copy each subarray to a separate queue and merge these elements back into the array.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
def mergesort(s,low,high):
    if low < high:
    	middle = int((low+high)/2)
        mergesort(s,low,middle)
        mergesort(s,middle+1,high)
        merge(s,low,middle,high)

def merge(s,low,middle,high):
    buffer1 = []
    buffer2 = []
    
    for i in range(low,middle):
        buffer1.append(s[i])
    for i in range(middle+1,high):
        buffer2.append(a[i])
        
    i = low
    
    while (!(len(buffer1)==0 or len(buffer2)==0)):
        if buffer1[0] <= buffer2[0]:
            s[i] = buffer1.pop(0)
        else:
            s[i] = buffer2.pop(0)
        i += 1
    while len(buffer1)!=0:
        s[i] = buffer1.pop(0)
   		i += 1
    while len(buffer2)!=0:
        s[i] = buffer2.pop(0)
        i += 1