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, true, q.IsEmpty()) | ||||
| 	assert.Equal(t, -1, q.TopIndex()) | ||||
| 	// TODO: maybe should return nil? | ||||
| 	// assert.Equal(t, 0, q.Top()) | ||||
| } | ||||
| 
 | ||||
| func TestIPQInsert(t *testing.T) { | ||||
|  |  | |||
|  | @ -1,3 +1,5 @@ | |||
| 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) | ||||
|  |  | |||
|  | @ -73,3 +73,13 @@ func BenchmarkQuick(b *testing.B) { | |||
| 		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