Search code examples
pythonalgorithmsortingmergesortpseudocode

How can I convert pseudocode to mergesort algorithm?


I need to convert pseudocode into a merge sort algorithm that mirrors that pseudocode. I am new to pseudocode so I'm having trouble with this. Can anyone tell me what is wrong with my algorithm? Please note that the arrays in the pseudocode are 1-indexed.

PSEUDOCODE:

MergeSort(A[1 .. n]):
   if n > 1
      m ← bn/2c
      MergeSort(A[1 .. m])
      MergeSort(A[m + 1 .. n])
      Merge(A[1 .. n], m)

Merge(A[1 .. n], m):
   i ← 1; j ← m + 1
   for k ← 1 to n
      if j > n
         B[k] ← A[i]; i ← i + 1
      else if i > m
         B[k] ← A[j]; j ← j + 1
      else if A[i] < A[ j]
         B[k] ← A[i]; i ← i + 1
      else
         B[k] ← A[j]; j ← j + 1
   for k ← 1 to n
      A[k] ← B[k]

MY CODE

def mergeSort(arr):
    n = len(arr)
    if n > 1:
        m = n//2
        mergeSort(arr[:m])
        mergeSort(arr[m:])
        merge(arr, m)

def merge(arr, m):
    n = len(arr)
    i = 0
    j = m
    b = [0] * n
    
    for k in range(n):
        if j >= n:
            b[k] = arr[i]
            i += 1
        elif i > m-1:
            b[k] = arr[j]
            j += 1
        elif arr[i] < arr[j]:
            b[k] = arr[i]
            i += 1
        else:
            b[k] = arr[j]
            j += 1
    for k in range(n):
        arr[k] = b[k] 

Solution

  • The thing is that in the pseudo code version, the notation A[1..m] is supposed to mean a partition of the array, but in-place, not as a new array (slice): it is like a window on a part of the array, with its own indexing, but not copied.

    The translation to list slicing in Python does not reflect this. arr[:m] creates a new list, and so whatever mergeSort(arr[:m]) does with that new list, it doesn't touch arr itself: all that work is for nothing, as it doesn't mutate arr, but a sliced copy of it, which we lose access to.

    A solution is to not create slices, but to pass the start/end indices of the intended partition to the function call.

    Here is the adapted code:

    def mergeSort(arr):
        mergeSortRec(arr, 0, len(arr))
    
    def mergeSortRec(arr, start, end):
        n = end - start
        if n > 1:
            m = start + n//2
            mergeSortRec(arr, start, m)
            mergeSortRec(arr, m, end)
            merge(arr, start, m, end)
    
    def merge(arr, start, m, end):
        n = end - start
        i = start
        j = m
        b = [0] * n
        
        for k in range(n):
            if j >= end:
                b[k] = arr[i]
                i += 1
            elif i >= m:
                b[k] = arr[j]
                j += 1
            elif arr[i] < arr[j]:
                b[k] = arr[i]
                i += 1
            else:
                b[k] = arr[j]
                j += 1
        for k in range(n):
            arr[start + k] = b[k]