bottom up merge sort
This commit is contained in:
parent
2ea8b8e388
commit
4431b6638f
2 changed files with 72 additions and 3 deletions
|
@ -1,6 +1,8 @@
|
|||
package sorting
|
||||
|
||||
import "sync"
|
||||
import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
func merge[T any](items []T, low, mid, hig int, less func(a, b T) bool, aux []T) {
|
||||
i, j := low, mid+1
|
||||
|
@ -42,6 +44,30 @@ func doSort[T any](items []T, low, hig int, less func(a, b T) bool, aux []T) {
|
|||
|
||||
mid := low + (hig-low)/2
|
||||
|
||||
doSort(items, low, mid, less, aux)
|
||||
doSort(items, mid+1, hig, less, aux)
|
||||
|
||||
// Optimization 1: if two subarrays already sorted
|
||||
// we can skip merging them
|
||||
if less(items[mid], items[mid+1]) {
|
||||
return
|
||||
}
|
||||
|
||||
merge(items, low, mid, hig, less, aux)
|
||||
}
|
||||
|
||||
func doParallelSort[T any](items []T, low, hig int, less func(a, b T) bool, aux []T) {
|
||||
if hig <= low {
|
||||
return
|
||||
}
|
||||
|
||||
if hig-low <= 15 {
|
||||
Insertion(items[low:hig+1], less)
|
||||
return
|
||||
}
|
||||
|
||||
mid := low + (hig-low)/2
|
||||
|
||||
// Optimization 3: we can run sorting in parallel.
|
||||
// This is costly optimization because we increase memory
|
||||
// usage by creating WaitGroup instances
|
||||
|
@ -51,8 +77,6 @@ func doSort[T any](items []T, low, hig int, less func(a, b T) bool, aux []T) {
|
|||
go func() { doSort(items, mid+1, hig, less, aux); wg.Done() }()
|
||||
wg.Wait()
|
||||
|
||||
// Optimization 1: if two subarrays already sorted
|
||||
// we can skip merging them
|
||||
if less(items[mid], items[mid+1]) {
|
||||
return
|
||||
}
|
||||
|
@ -66,3 +90,28 @@ func Merge[T any](items []T, less func(a, b T) bool) {
|
|||
|
||||
doSort(items, 0, len-1, less, make([]T, len))
|
||||
}
|
||||
|
||||
func ParallelMerge[T any](items []T, less func(a, b T) bool) {
|
||||
|
||||
len := len(items)
|
||||
|
||||
doParallelSort(items, 0, len-1, less, make([]T, len))
|
||||
}
|
||||
|
||||
func BottomUpMerge[T any](items []T, less func(a, b T) bool) {
|
||||
|
||||
len := len(items)
|
||||
aux := make([]T, len)
|
||||
min := func(x, y int) int {
|
||||
if x < y {
|
||||
return x
|
||||
}
|
||||
return y
|
||||
}
|
||||
|
||||
for sz := 1; sz < len; sz = sz + sz {
|
||||
for low := 0; low < len-sz; low += sz + sz {
|
||||
merge(items, low, low+sz-1, min(low+sz+sz-1, len-1), less, aux)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,3 +43,23 @@ func BenchmarkMerge(b *testing.B) {
|
|||
BenchmarkSort(10000, Merge[int])
|
||||
}
|
||||
}
|
||||
|
||||
func TestParallelMerge(t *testing.T) {
|
||||
CheckSliceSorter(ParallelMerge[int])
|
||||
}
|
||||
|
||||
func BenchmarkParallelMerge(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
BenchmarkSort(10000, ParallelMerge[int])
|
||||
}
|
||||
}
|
||||
|
||||
func TestBottomUpMerge(t *testing.T) {
|
||||
CheckSliceSorter(BottomUpMerge[int])
|
||||
}
|
||||
|
||||
func BenchmarkBottomUpMerge(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
BenchmarkSort(10000, BottomUpMerge[int])
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue