Mergesort Cutaway
Sorting an array can be done in different ways. It ranges from the simpler bubble sort to more complicated ones such as the merge sort.
What is mergesort?
Bottom-up mergesort starts by continuously dividing an array into smaller sublists until each sublist is of size 1. Then, pairs of individual sublists are merged in a sorted order, to form arrays of size 2. This process continues until only one merged list remains. This final list is the sorted array.
The term mergesort is a combination of two subwords: merge - that is to merge smaller arrays into bigger ones and sort - meaning to rearrange terms in order – ascending or descending.
Why mergesort?
Mergesort is one of the efficient sorting algorithms. It outshines the capabilities of bubble sort by a large margin. Mergesort has best and worst case complexity of \(O(n log n)\) compared to the even worse complexity of the bubble sort going up to \(O(n^2)\).
Where is mergesort used?
Mergesort is one of the typical sorting algorithms used for sorting arrays or sequences of numbers. It is the method used by many builtin functions of programming languages due to its efficiency and short sorting time.
Mergesort implementation
|
|
The _rsplit()
function recursively splits the array into sublists of 1 and adds
them to a list of sublists (frag_list
). The _merge()
recursively merges these
sublists, two at a time and appends them to frag_list
and continues until just
one sublist remains. This final sublist is the sorted list.
Mergesort:ascending=True,cutaway=True
<< s p l i t >> [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
<< s p l i t >> [10, 9, 8, 7, 6]
<< s p l i t >> [10, 9]
<< s p l i t >> [10]
<< s p l i t >> [9]
<< s p l i t >> [8, 7, 6]
<< s p l i t >> [8]
<< s p l i t >> [7, 6]
<< s p l i t >> [7]
<< s p l i t >> [6]
<< s p l i t >> [5, 4, 3, 2, 1]
<< s p l i t >> [5, 4]
<< s p l i t >> [5]
<< s p l i t >> [4]
<< s p l i t >> [3, 2, 1]
<< s p l i t >> [3]
<< s p l i t >> [2, 1]
<< s p l i t >> [2]
<< s p l i t >> [1]
>>merge<< [[10], [9], [8], [7], [6], [5], [4], [3], [2], [1]]
>>merge<< [[8], [7], [6], [5], [4], [3], [2], [1], [9, 10]]
>>merge<< [[6], [5], [4], [3], [2], [1], [9, 10], [7, 8]]
>>merge<< [[4], [3], [2], [1], [9, 10], [7, 8], [5, 6]]
>>merge<< [[2], [1], [9, 10], [7, 8], [5, 6], [3, 4]]
>>merge<< [[9, 10], [7, 8], [5, 6], [3, 4], [1, 2]]
>>merge<< [[5, 6], [3, 4], [1, 2], [7, 8, 9, 10]]
>>merge<< [[1, 2], [7, 8, 9, 10], [3, 4, 5, 6]]
>>merge<< [[3, 4, 5, 6], [1, 2, 7, 8, 9, 10]]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
The above cutaway view first shows how the array is split and later how pairs of sublists get merged and appended to the list of lists until the final sorted list is generated.
Top-down mergesort implementation
|
|
The output of this program is as follows:
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1] ---> [10, 9, 8, 7, 6] << s p l i t >> [5, 4, 3, 2, 1]
[10, 9, 8, 7, 6] ---> [10, 9] << s p l i t >> [8, 7, 6]
[10, 9] ---> [10] << s p l i t >> [9]
[10] >> merge << [9] ---> [9, 10]
[8, 7, 6] ---> [8] << s p l i t >> [7, 6]
[7, 6] ---> [7] << s p l i t >> [6]
[7] >> merge << [6] ---> [6, 7]
[8] >> merge << [6, 7] ---> [6, 7, 8]
[9, 10] >> merge << [6, 7, 8] ---> [6, 7, 8, 9, 10]
[5, 4, 3, 2, 1] ---> [5, 4] << s p l i t >> [3, 2, 1]
[5, 4] ---> [5] << s p l i t >> [4]
[5] >> merge << [4] ---> [4, 5]
[3, 2, 1] ---> [3] << s p l i t >> [2, 1]
[2, 1] ---> [2] << s p l i t >> [1]
[2] >> merge << [1] ---> [1, 2]
[3] >> merge << [1, 2] ---> [1, 2, 3]
[4, 5] >> merge << [1, 2, 3] ---> [1, 2, 3, 4, 5]
[6, 7, 8, 9, 10] >> merge << [1, 2, 3, 4, 5] ---> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Note that the recursive mergesort function recurses all the way to the point where the array length is just 1. This is the base case. When all these recursive calls return, they merge the (now sorted) split array segments in the correct order and assemble the complete sorted array.