It is notable for having a worst case and average complexity of O(n*log(n)), and a best case complexity of O(n) (for pre-sorted input).

The basic idea is to split the collection into smaller groups by halving it until the groups only have one element or no elements (which are both entirely sorted groups).

Then merge the groups back together so that their elements are in order.

This is how the algorithm gets its divide and conquer description.

Task

Write a function to sort a collection of integers using the merge sort.

The merge sort algorithm comes in two parts:

a sort function and
a merge function

The functions in pseudocode look like this:

functionmergesort(m)
var list left, right, result
if length(m) ≤ 1
return m
elsevar middle = length(m) / 2
for each x in m up to middle - 1
add x to left
for each x in m at and after middle
add x to right
left = mergesort(left)
right = mergesort(right)
if last(left) ≤ first(right)
append right to left
return left
result = merge(left, right)
return result
functionmerge(left,right)
var list result
while length(left) > 0 and length(right) > 0
if first(left) ≤ first(right)
append first(left) to result
left = rest(left)
elseappend first(right) to result
right = rest(right)
if length(left) > 0
append rest(left) to result
if length(right) > 0
append rest(right) to result
return result

Note: better performance can be expected if, rather than recursing until length(m) ≤ 1, an insertion sort is used for length(m) smaller than some threshold larger than 1. However, this complicates the example code, so it is not shown here.

function mergesort(a:Array){//Arrays of length 1 and 0 are always sortedif(a.length<= 1)return a;else{var middle:uint = a.length/2;//split the array into twovarleft:Array = newArray(middle);varright:Array = newArray(a.length-middle);var j:uint = 0, k:uint = 0;//fill the left arrayfor(var i:uint = 0; i < middle; i++)left[j++]=a[i];//fill the right arrayfor(i = middle; i< a.length; i++)right[k++]=a[i];//sort the arraysleft = mergesort(left);right = mergesort(right);//If the last element of the left array is less than or equal to the first//element of the right array, they are in order and don't need to be mergedif(left[left.length-1]<= right[0])returnleft.concat(right); a = merge(left, right);return a;}}

This example creates a generic package for sorting arrays of any type. Ada allows array indices to be any discrete type, including enumerated types which are non-numeric. Furthermore, numeric array indices can start at any value, positive, negative, or zero. The following code handles all the possible variations in index types.

# FLEX version: A demonstration of FLEX for manipulating arrays #PROC flex merge =([]DATA in left, in right)[]DATA:([UPB in left +UPB in right]DATA result;FLEX[0]DATA left := in left;FLEX[0]DATA right := in right;

FOR index TOUPB result DO# change the direction of this comparison to change the direction of the sort #IFLWB right >UPB right THEN result[index:]:= left; stop iterationELIFLWB left >UPB left THEN result[index:]:= right; stop iterationELIF left[1]<= right[1]THEN result[index]:= left[1]; left := left[2:]ELSE result[index]:= right[1]; right := right[2:]FIOD;stop iteration: result);

; Split array into Left and Right halfsLeft:=[],Right:=[], Middle := Array.MaxIndex()//2Loop % MiddleRight.Insert(Array.Remove(Middle--+1)),Left.Insert(Array.Remove(1))If(Array.MaxIndex())Right.Insert(Array.Remove(1))

Left:= MergeSort(Left),Right:= MergeSort(Right)

; If all the Right values are greater than all the; Left values, just append Right at the end of Left.If(Left[Left.MaxIndex()]<=Right[1]){Loop % Right.MaxIndex()Left.Insert(Right.Remove(1))ReturnLeft}; Loop until one of the arrays is emptyWhile(Left.MaxIndex()andRight.MaxIndex())Left[1]<=Right[1] ? Array.Insert(Left.Remove(1)) : Array.Insert(Right.Remove(1))

Cobol cannot do recursion, so this version simulates recursion. The working storage is therefore pretty complex, so I have shown the whole program, not just the working procedure division parts.

IDENTIFICATIONDIVISION.PROGRAM-ID. MERGESORT.AUTHOR. DAVE STRATFORD.DATE-WRITTEN. APRIL 2010.INSTALLATION. HEXAGON SYSTEMS LIMITED. ****************************************************************** * MERGESORT * * The Mergesort uses a completely different paradigm, one of * * divideand conquer,to many of the other sorts. The dataset * * is split into smaller sub sets upon which are sorted andthen * * merged together to form the final sorted dataset. * * This version uses the recursive method. Split the datasetin * * half andperform a mergesorton each half. This in turn splits* * each half again and again until each setisjust one or2 items* * long. A setof one item is already sorted so is ignored, a set * * of two is compared and swapped as necessary. The smaller data * * sets are then repeatedly merged together to eventually form the* * full, sorted,set. * * Since cobol cannot do recursion this module only simulates it * * so isnot as fast as a normal recursive version would be. * * Scales very well to larger data sets, its relative complexity * * means it isnot suited to sorting smaller data sets: use an * * Insertion sort instead as the Mergesortis a stable sort. * ******************************************************************

Below are two versions. Both take advantage of built-in Erlang functions, lists:split and list:merge. The multi-process version spawns a new process each time it splits. This was slightly faster on a test system with only two cores, so it may not be the best implementation, however it does illustrate how easy it can be to add multi-threaded/process capabilities to a program.

' While there are elements in the left or right runs...For k AsInteger = iBegin To iEnd - 1' If left run head exists and is <= existing right run head.If i < iMiddle AndAlso (j >= iEnd OrElse a(i) <= a(j))Then b(k) = a(i) i += 1Else b(k) = a(j) j += 1EndIfNextEndSub

This is the standard algorithm, except that in the looping phase of the merge we work backwards through the left and right lists to construct the merged list, to take advantage of the GroovyList.pop() method. However, this results in a partially merged list in reverse sort order; so we then reverse it to put in back into correct order. This could play havoc with the sort stability, but we compensate by picking aggressively from the right list (ties go to the right), rather than aggressively from the left as is done in the standard algorithm.

It is possible to write a version based on tail recursion, similar to that written in Haskel, OCaml or F#.
This version also takes into account stack overflow problems induced by recursion for large lists using closure trampolines:

Splitting in half in the middle like the normal merge sort does would be inefficient on the singly-linked lists used in Haskell (since you would have to do one pass just to determine the length, and then another half-pass to do the splitting). Instead, the algorithm here splits the list in half in a different way -- by alternately assigning elements to one list and the other. That way we (lazily) construct both sublists in parallel as we traverse the original list. Unfortunately, under this way of splitting we cannot do a stable sort.

The standard library's sort function in GHC takes a similar approach to the bottom-up code, the differece being that, instead of starting with lists of size one, which are sorted by default, it detects runs in original list and uses those:

fn mergesort arr =( local left = #() local right = #() local result = #() if arr.count < 2 then return arr else ( local mid = arr.count/2 for i = 1 to mid do ( append left arr[i] ) for i = (mid+1) to arr.count do ( append right arr[i] ) left = mergesort left right = mergesort right if left[left.count] <= right[1] do ( join left right return left ) result = _merge left right return result ))

fn _merge a b =( local result = #() while a.count > 0 and b.count > 0 do ( if a[1] <= b[1] then ( append result a[1] a = for i in 2 to a.count collect a[i] ) else ( append result b[1] b = for i in 2 to b.count collect b[i] ) ) if a.count > 0 do ( join result a ) if b.count > 0 do ( join result b ) return result)

This version of a sort will sort a list of any type for which there is an ordering predicate defined. Both a function form and a predicate form are defined here with the function implemented in terms of the predicate. Some of the ceremony has been elided.

uses "only" one halfsized temporary array for merging, which are set to the right size in before.
small sized fields are sorted via insertion sort.
Only an array of Pointers is sorted, so no complex data transfers are needed.Sort for X,Y or whatever is easy to implement.

function merge(sequence left, sequence right)sequence result = {} while length(left)>0 and length(right)>0 do if left[1]<=right[1] then result = append(result, left[1]) left = left[2..$] else result = append(result, right[1]) right = right[2..$] end if end while return result & left & rightend function

function mergesort(sequence m)sequence left, rightinteger middle if length(m)<=1 then return m end if middle = floor(length(m)/2) left = mergesort(m[1..middle]) right = mergesort(m[middle+1..$]) if left[$]<=right[1] then return left & right elsif right[$]<=left[1] then return right & left end if return merge(left, right)end function

/* Merge A(1:LA) with B(1:LB), putting the result in C B and C may share the same memory, but not with A.*/DECLARE(A(*),B(*),C(*))BYADDRPOINTER;DECLARE(LA,LB)BYVALUENONASGNFIXEDBIN(31);DECLARE(I,J,K)FIXEDBIN(31);DECLARE(SX)CHAR(58)VARBASED(PX);DECLARE(SY)CHAR(58)VARBASED(PY);DECLARE(PX,PY)POINTER;

function MergeSort([object[]]$SortInput){# The base case exits for minimal lists that are sorted by definitionif($SortInput.Length -le1){return$SortInput}

# Divide and conquer[int]$midPoint=$SortInput.Length/2# The @() operators ensure a single result remains typed as an array[object[]]$left=@(MergeSort @($SortInput[0..($midPoint-1)]))[object[]]$right=@(MergeSort @($SortInput[$midPoint..($SortInput.Length-1)]))

# Merge[object[]]$result=@()while(($left.Length -gt0)-and($right.Length -gt0)){if($left[0]-lt$right[0]){$result+=$left[0]# Use an if/else rather than accessing the array range as $array[1..0]if($left.Length -gt1){$left=$left[1..$($left.Length-1)]}else{$left=@()}}else{$result+=$right[0]# Without the if/else, $array[1..0] would return the whole array when $array.Length == 1if($right.Length -gt1){$right=$right[1..$($right.Length-1)]}else{$right=@()}}}

# If we get here, either $left or $right is an empty array (or both are empty!). Since the# rest of the unmerged array is already sorted, we can simply string together what we have.# This line outputs the concatenated result. An explicit 'return' statement is not needed.$result+$left+$right}

privatedef merge(left, right, comparitor) result = []until left.empty? || right.empty?# change the direction of this comparison to change the direction of the sortif comparitor[left.first, right.first]<= 0 result << left.shiftelse result << right.shiftendend result + left + rightendend

merge uses the helper mergei to merge two lists. The mergei takes a stack of the form [mergedlist] [list1] [list2]
it then extracts one element from list2, splits the list1 with it, joins the older merged list, first part of list1 and the element that was used for splitting (taken from list2) into the new merged list. the new list1 is the second part of the split on older list1. new list2 is the list remaining after the element e2 was extracted from it.