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 | package sorting | ||||||
| 
 | 
 | ||||||
| import "sync" | import ( | ||||||
|  | 	"sync" | ||||||
|  | ) | ||||||
| 
 | 
 | ||||||
| func merge[T any](items []T, low, mid, hig int, less func(a, b T) bool, aux []T) { | func merge[T any](items []T, low, mid, hig int, less func(a, b T) bool, aux []T) { | ||||||
| 	i, j := low, mid+1 | 	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 | 	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. | 	// Optimization 3: we can run sorting in parallel. | ||||||
| 	// This is costly optimization because we increase memory | 	// This is costly optimization because we increase memory | ||||||
| 	// usage by creating WaitGroup instances | 	// 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() }() | 	go func() { doSort(items, mid+1, hig, less, aux); wg.Done() }() | ||||||
| 	wg.Wait() | 	wg.Wait() | ||||||
| 
 | 
 | ||||||
| 	// Optimization 1: if two subarrays already sorted |  | ||||||
| 	// we can skip merging them |  | ||||||
| 	if less(items[mid], items[mid+1]) { | 	if less(items[mid], items[mid+1]) { | ||||||
| 		return | 		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)) | 	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]) | 		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