07/17/2021 20:16 | Category: dsa

Tags: merge_sortsortalgorithm

merge sort

Merge sorts will divide an array in half to sort each side independently using recursion. These are then merged together after the sorting is completed by adding each item from the array's halves into a new array in sorted order.

How it works

The algorithm breaks a list of items into sub-lists to sort recursively.

Each recursive call will create smaller sub-divided list objects that will be sorted through. Once finished, they are joined together in sorted order.

The merge sort does log n merge steps because each merge step doubles the list size. It does n work steps during merging because it looks at every item.

Runtime is O(nlogn)

Big-o

The merge sort runs in good time, O(nlogn). Merge sort uses O(n) space.

Example implementation

This implementation utilizes Python and is parametrized with Pytest.


def merge_sort(data_list: List[int]) -> None:
    merge_sort_recursive(data_list, 0, len(data_list) - 1)


def merge_sort_recursive(data_list: List[int], first: int, last: int) -> None:

    # find the middle of a list and break it up
    if first < last:
        middle = (first + last) // 2
        # break the left half of the list
        merge_sort_recursive(data_list, first, middle)

        # break the right half of the list
        merge_sort_recursive(data_list, middle + 1, last)

        # merge the halves
        merge(data_list, first, middle, last)


def merge(data_list: List[int], first: int, middle: int, last: int) -> None:
    left_half = data_list[first:middle + 1]
    right_half = data_list[middle + 1:last + 1]

    # sentinel values
    # these signal being done with the sorting
    left_half.append(99999999999)
    right_half.append(99999999999)

    i = 0
    j = 0

    for k in range(first, last + 1):
        if left_half[i] <= right_half[j]:
            data_list[k] = left_half[i]
            i += 1
        else:
            data_list[k] = right_half[j]
            j += 1


@pytest.mark.parametrize(
    "data_list",
    [
        ([]),
        ([1]),
        ([1, 2]),
        ([2, 2]),
        ([3, 2]),
        ([3, 2, 4, 8, 7]),
        ([3, 2, 4, 9, 7, 8]),
    ],
)
def test_merge_sort(data_list):
    merge_sort(data_list)

    length = len(data_list)
    for i in range(length-1):
        for j in range(0, length-i-1):
            assert data_list[j] <= data_list[j + 1]