Skip to content

Commit

Permalink
Implement in-place Merge sort algorithm
Browse files Browse the repository at this point in the history
  • Loading branch information
mrekucci committed Nov 18, 2015
1 parent 149686a commit 687b93f
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 0 deletions.
46 changes: 46 additions & 0 deletions sorting/algorithm.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,52 @@ func HeapSort(data sort.Interface) {
}
}

// move moves the largest element in data[s:e+1] into the position e.
// It has O(n) time complexity (n=e-s) and O(1) additional space is needed.
func move(data sort.Interface, s, e int) {
for i := s; i < e; i++ {
if data.Less(i+1, i) {
data.Swap(i+1, i)
}
}
}

// merge combines sorted data[p:q+1] and data[q+1:r+1] together.
func merge(data sort.Interface, p, q, r int) {
for i := p; i <= q; i++ {
if data.Less(q+1, i) {
data.Swap(q+1, i)
move(data, q+1, r)
}
}
}

// mergeSortFn is a recursive function that sorts data[l:r+1].
func mergeSortFn(ints sort.Interface, p, r int) {
switch cnt := r - p; {
case cnt == 1: // Two elements left.
if ints.Less(r, p) {
ints.Swap(p, r)
}
case cnt > 1:
q := p + (r-p)/2
mergeSortFn(ints, p, q) // Divide.
mergeSortFn(ints, q+1, r) // Divide.
merge(ints, p, q, r) // Combine and Conquer.
}
}

// MergeSort (in-place version) sorts given data and has next properties:
//
// - Not stable
// - O(1) extra space
// - O(n*lg(n)) time worst case
// - Adaptive (not for reverse sorted)
//
func MergeSort(data sort.Interface) {
mergeSortFn(data, 0, data.Len()-1)
}

// median moves the median of data[a], data[b], data[c] into data[b].
// Selecting a median helps avoid to cause worst-case behavior on already
// sorted (or reverse-sorted) data, and gives a better estimate of the optimal
Expand Down
16 changes: 16 additions & 0 deletions sorting/algorithm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ func TestBubbleSort(t *testing.T) { testSortFn(t, BubbleSort, "BubbleSort") }
func TestSelectionSort(t *testing.T) { testSortFn(t, SelectionSort, "SelectionSort") }
func TestInsertionSort(t *testing.T) { testSortFn(t, InsertionSort, "InsertionSort") }
func TestHeapSort(t *testing.T) { testSortFn(t, HeapSort, "HeapSort") }
func TestMergeSort(t *testing.T) { testSortFn(t, MergeSort, "MergeSort") }
func TestQuickSort(t *testing.T) { testSortFn(t, QuickSort, "QuickSort") }

func benchRandom(b *testing.B, fn sortFn, size int) {
Expand Down Expand Up @@ -119,78 +120,93 @@ func BenchmarkBubbleSortRandom1e1(b *testing.B) { benchRandom(b, BubbleSort,
func BenchmarkSelectionSortRandom1e1(b *testing.B) { benchRandom(b, SelectionSort, 1e1) }
func BenchmarkInsertionSortRandom1e1(b *testing.B) { benchRandom(b, InsertionSort, 1e1) }
func BenchmarkHeapSortRandom1e1(b *testing.B) { benchRandom(b, HeapSort, 1e1) }
func BenchmarkMergeSortRandom1e1(b *testing.B) { benchRandom(b, MergeSort, 1e1) }
func BenchmarkQuickSortRandom1e1(b *testing.B) { benchRandom(b, QuickSort, 1e1) }
func BenchmarkBubbleSortRandom1e2(b *testing.B) { benchRandom(b, BubbleSort, 1e2) }
func BenchmarkSelectionSortRandom1e2(b *testing.B) { benchRandom(b, SelectionSort, 1e2) }
func BenchmarkInsertionSortRandom1e2(b *testing.B) { benchRandom(b, InsertionSort, 1e2) }
func BenchmarkHeapSortRandom1e2(b *testing.B) { benchRandom(b, HeapSort, 1e2) }
func BenchmarkMergeSortRandom1e2(b *testing.B) { benchRandom(b, MergeSort, 1e2) }
func BenchmarkQuickSortRandom1e2(b *testing.B) { benchRandom(b, QuickSort, 1e2) }
func BenchmarkBubbleSortRandom1e3(b *testing.B) { benchRandom(b, BubbleSort, 1e3) }
func BenchmarkSelectionSortRandom1e3(b *testing.B) { benchRandom(b, SelectionSort, 1e3) }
func BenchmarkInsertionSortRandom1e3(b *testing.B) { benchRandom(b, InsertionSort, 1e3) }
func BenchmarkHeapSortRandom1e3(b *testing.B) { benchRandom(b, HeapSort, 1e3) }
func BenchmarkMergeSortRandom1e3(b *testing.B) { benchRandom(b, MergeSort, 1e3) }
func BenchmarkQuickSortRandom1e3(b *testing.B) { benchRandom(b, QuickSort, 1e3) }

func BenchmarkBubbleSortFewUnique1e1(b *testing.B) { benchFewUnique(b, BubbleSort, 1e1) }
func BenchmarkSelectionSortFewUnique1e1(b *testing.B) { benchFewUnique(b, SelectionSort, 1e1) }
func BenchmarkInsertionSortFewUnique1e1(b *testing.B) { benchFewUnique(b, InsertionSort, 1e1) }
func BenchmarkHeapSortFewUnique1e1(b *testing.B) { benchFewUnique(b, HeapSort, 1e1) }
func BenchmarkMergeSortFewUnique1e1(b *testing.B) { benchFewUnique(b, MergeSort, 1e1) }
func BenchmarkQuickSortFewUnique1e1(b *testing.B) { benchFewUnique(b, QuickSort, 1e1) }
func BenchmarkBubbleSortFewUnique1e2(b *testing.B) { benchFewUnique(b, BubbleSort, 1e2) }
func BenchmarkSelectionSortFewUnique1e2(b *testing.B) { benchFewUnique(b, SelectionSort, 1e2) }
func BenchmarkInsertionSortFewUnique1e2(b *testing.B) { benchFewUnique(b, InsertionSort, 1e2) }
func BenchmarkHeapSortFewUnique1e2(b *testing.B) { benchFewUnique(b, HeapSort, 1e2) }
func BenchmarkMergeSortFewUnique1e2(b *testing.B) { benchFewUnique(b, MergeSort, 1e2) }
func BenchmarkQuickSortFewUnique1e2(b *testing.B) { benchFewUnique(b, QuickSort, 1e2) }
func BenchmarkBubbleSortFewUnique1e3(b *testing.B) { benchFewUnique(b, BubbleSort, 1e3) }
func BenchmarkSelectionSortFewUnique1e3(b *testing.B) { benchFewUnique(b, SelectionSort, 1e3) }
func BenchmarkInsertionSortFewUnique1e3(b *testing.B) { benchFewUnique(b, InsertionSort, 1e3) }
func BenchmarkHeapSortFewUnique1e3(b *testing.B) { benchFewUnique(b, HeapSort, 1e3) }
func BenchmarkMergeSortFewUnique1e3(b *testing.B) { benchFewUnique(b, MergeSort, 1e3) }
func BenchmarkQuickSortFewUnique1e3(b *testing.B) { benchFewUnique(b, QuickSort, 1e3) }

func BenchmarkBubbleSortNearlySorted1e1(b *testing.B) { benchNearlySorted(b, BubbleSort, 1e1) }
func BenchmarkSelectionSortNearlySorted1e1(b *testing.B) { benchNearlySorted(b, SelectionSort, 1e1) }
func BenchmarkInsertionSortNearlySorted1e1(b *testing.B) { benchNearlySorted(b, InsertionSort, 1e1) }
func BenchmarkHeapSortNearlySorted1e1(b *testing.B) { benchNearlySorted(b, HeapSort, 1e1) }
func BenchmarkMergeSortNearlySorted1e1(b *testing.B) { benchNearlySorted(b, MergeSort, 1e1) }
func BenchmarkQuickSortNearlySorted1e1(b *testing.B) { benchNearlySorted(b, QuickSort, 1e1) }
func BenchmarkBubbleSortNearlySorted1e2(b *testing.B) { benchNearlySorted(b, BubbleSort, 1e2) }
func BenchmarkSelectionSortNearlySorted1e2(b *testing.B) { benchNearlySorted(b, SelectionSort, 1e2) }
func BenchmarkInsertionSortNearlySorted1e2(b *testing.B) { benchNearlySorted(b, InsertionSort, 1e2) }
func BenchmarkHeapSortNearlySorted1e2(b *testing.B) { benchNearlySorted(b, HeapSort, 1e2) }
func BenchmarkMergeSortNearlySorted1e2(b *testing.B) { benchNearlySorted(b, MergeSort, 1e2) }
func BenchmarkQuickSortNearlySorted1e2(b *testing.B) { benchNearlySorted(b, QuickSort, 1e2) }
func BenchmarkBubbleSortNearlySorted1e3(b *testing.B) { benchNearlySorted(b, BubbleSort, 1e3) }
func BenchmarkSelectionSortNearlySorted1e3(b *testing.B) { benchNearlySorted(b, SelectionSort, 1e3) }
func BenchmarkInsertionSortNearlySorted1e3(b *testing.B) { benchNearlySorted(b, InsertionSort, 1e3) }
func BenchmarkHeapSortNearlySorted1e3(b *testing.B) { benchNearlySorted(b, HeapSort, 1e3) }
func BenchmarkMergeSortNearlySorted1e3(b *testing.B) { benchNearlySorted(b, MergeSort, 1e3) }
func BenchmarkQuickSortNearlySorted1e3(b *testing.B) { benchNearlySorted(b, QuickSort, 1e3) }

func BenchmarkBubbleSortSorted1e1(b *testing.B) { benchSorted(b, BubbleSort, 1e1) }
func BenchmarkSelectionSortSorted1e1(b *testing.B) { benchSorted(b, SelectionSort, 1e1) }
func BenchmarkInsertionSortSorted1e1(b *testing.B) { benchSorted(b, InsertionSort, 1e1) }
func BenchmarkHeapSortSorted1e1(b *testing.B) { benchSorted(b, HeapSort, 1e1) }
func BenchmarkMergeSortSorted1e1(b *testing.B) { benchSorted(b, MergeSort, 1e1) }
func BenchmarkQuickSortSorted1e1(b *testing.B) { benchSorted(b, QuickSort, 1e1) }
func BenchmarkBubbleSortSorted1e2(b *testing.B) { benchSorted(b, BubbleSort, 1e2) }
func BenchmarkSelectionSortSorted1e2(b *testing.B) { benchSorted(b, SelectionSort, 1e2) }
func BenchmarkInsertionSortSorted1e2(b *testing.B) { benchSorted(b, InsertionSort, 1e2) }
func BenchmarkHeapSortSorted1e2(b *testing.B) { benchSorted(b, HeapSort, 1e2) }
func BenchmarkMergeSortSorted1e2(b *testing.B) { benchSorted(b, MergeSort, 1e2) }
func BenchmarkQuickSortSorted1e2(b *testing.B) { benchSorted(b, QuickSort, 1e2) }
func BenchmarkBubbleSortSorted1e3(b *testing.B) { benchSorted(b, BubbleSort, 1e3) }
func BenchmarkSelectionSortSorted1e3(b *testing.B) { benchSorted(b, SelectionSort, 1e3) }
func BenchmarkInsertionSortSorted1e3(b *testing.B) { benchSorted(b, InsertionSort, 1e3) }
func BenchmarkHeapSortSorted1e3(b *testing.B) { benchSorted(b, HeapSort, 1e3) }
func BenchmarkMergeSortSorted1e3(b *testing.B) { benchSorted(b, MergeSort, 1e3) }
func BenchmarkQuickSortSorted1e3(b *testing.B) { benchSorted(b, QuickSort, 1e3) }

func BenchmarkBubbleSortReversed1e1(b *testing.B) { benchReversed(b, BubbleSort, 1e1) }
func BenchmarkSelectionSortReversed1e1(b *testing.B) { benchReversed(b, SelectionSort, 1e1) }
func BenchmarkInsertionSortReversed1e1(b *testing.B) { benchReversed(b, InsertionSort, 1e1) }
func BenchmarkHeapSortReversed1e1(b *testing.B) { benchReversed(b, HeapSort, 1e1) }
func BenchmarkMergeSortReversed1e1(b *testing.B) { benchReversed(b, MergeSort, 1e1) }
func BenchmarkQuickSortReversed1e1(b *testing.B) { benchReversed(b, QuickSort, 1e1) }
func BenchmarkBubbleSortReversed1e2(b *testing.B) { benchReversed(b, BubbleSort, 1e2) }
func BenchmarkSelectionSortReversed1e2(b *testing.B) { benchReversed(b, SelectionSort, 1e2) }
func BenchmarkInsertionSortReversed1e2(b *testing.B) { benchReversed(b, InsertionSort, 1e2) }
func BenchmarkHeapSortReversed1e2(b *testing.B) { benchReversed(b, HeapSort, 1e2) }
func BenchmarkMergeSortReversed1e2(b *testing.B) { benchReversed(b, MergeSort, 1e2) }
func BenchmarkQuickSortReversed1e2(b *testing.B) { benchReversed(b, QuickSort, 1e2) }
func BenchmarkBubbleSortReversed1e3(b *testing.B) { benchReversed(b, BubbleSort, 1e3) }
func BenchmarkSelectionSortReversed1e3(b *testing.B) { benchReversed(b, SelectionSort, 1e3) }
func BenchmarkInsertionSortReversed1e3(b *testing.B) { benchReversed(b, InsertionSort, 1e3) }
func BenchmarkHeapSortReversed1e3(b *testing.B) { benchReversed(b, HeapSort, 1e3) }
func BenchmarkMergeSortReversed1e3(b *testing.B) { benchReversed(b, MergeSort, 1e3) }
func BenchmarkQuickSortReversed1e3(b *testing.B) { benchReversed(b, QuickSort, 1e3) }

0 comments on commit 687b93f

Please sign in to comment.