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…
	
	Add table
		
		Reference in a new issue