heap sort

This commit is contained in:
Gregory 2022-01-03 23:07:11 +02:00
parent ebe6a3ab37
commit d4cbad40c3
4 changed files with 67 additions and 2 deletions

55
sorting/heap.go Normal file
View 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)
}
}

View file

@ -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) {

View file

@ -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)

View file

@ -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])
}
}