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