heap sort
This commit is contained in:
		
							parent
							
								
									ebe6a3ab37
								
							
						
					
					
						commit
						d4cbad40c3
					
				
					 4 changed files with 67 additions and 2 deletions
				
			
		
							
								
								
									
										55
									
								
								sorting/heap.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								sorting/heap.go
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,55 @@ | ||||||
|  | package sorting | ||||||
|  | 
 | ||||||
|  | func swap[T any](i, j int, items []T) { | ||||||
|  | 	items[i], items[j] = items[j], items[i] | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func swim[T any](child int, depth int, items []T, less func(T, T) bool) { | ||||||
|  | 	for { | ||||||
|  | 		parent := (child - 1) / 2 | ||||||
|  | 
 | ||||||
|  | 		if child <= 0 || less(items[child], items[parent]) { | ||||||
|  | 			break | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		swap(parent, child, items) | ||||||
|  | 
 | ||||||
|  | 		child = parent | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func sink[T any](parent int, depth int, items []T, less func(T, T) bool) { | ||||||
|  | 	for { | ||||||
|  | 		child := parent*2 + 1 | ||||||
|  | 
 | ||||||
|  | 		if child >= depth { | ||||||
|  | 			break | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if child+1 < depth && less(items[child], items[child+1]) { | ||||||
|  | 			child++ | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if !less(items[parent], items[child]) { | ||||||
|  | 			break | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		swap(parent, child, items) | ||||||
|  | 
 | ||||||
|  | 		parent = child | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func Heap[T any](items []T, less func(T, T) bool) { | ||||||
|  | 	len := len(items) | ||||||
|  | 
 | ||||||
|  | 	for k := len / 2; k >= 0; k-- { | ||||||
|  | 		sink(k, len, items, less) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for len > 0 { | ||||||
|  | 		len-- | ||||||
|  | 		swap(0, len, items) | ||||||
|  | 		sink(0, len, items, less) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -15,8 +15,6 @@ func TestNewIPQ(t *testing.T) { | ||||||
| 	assert.Equal(t, 0, q.Size()) | 	assert.Equal(t, 0, q.Size()) | ||||||
| 	assert.Equal(t, true, q.IsEmpty()) | 	assert.Equal(t, true, q.IsEmpty()) | ||||||
| 	assert.Equal(t, -1, q.TopIndex()) | 	assert.Equal(t, -1, q.TopIndex()) | ||||||
| 	// TODO: maybe should return nil? |  | ||||||
| 	// assert.Equal(t, 0, q.Top()) |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func TestIPQInsert(t *testing.T) { | func TestIPQInsert(t *testing.T) { | ||||||
|  |  | ||||||
|  | @ -1,3 +1,5 @@ | ||||||
| package sorting | package sorting | ||||||
| 
 | 
 | ||||||
|  | // TODO: compare function should receive pointers to slice elements | ||||||
|  | // to prevent unnecessary coping | ||||||
| type SliceSorter[T any] func([]T, func(T, T) bool) | type SliceSorter[T any] func([]T, func(T, T) bool) | ||||||
|  |  | ||||||
|  | @ -73,3 +73,13 @@ func BenchmarkQuick(b *testing.B) { | ||||||
| 		BenchmarkSort(10000, Quick[int]) | 		BenchmarkSort(10000, Quick[int]) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | func TestHeap(t *testing.T) { | ||||||
|  | 	CheckSliceSorter(Heap[int]) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func BenchmarkHeap(b *testing.B) { | ||||||
|  | 	for i := 0; i < b.N; i++ { | ||||||
|  | 		BenchmarkSort(10000, Heap[int]) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue