@@ -0,0 +1,137 @@
|
||||
package tests
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"slices"
|
||||
"testing"
|
||||
|
||||
"datastructures/trees/heap"
|
||||
)
|
||||
|
||||
func TestHeapSortRandomInts(t *testing.T) {
|
||||
input := []int{5, 3, 9, 1, 7, 2, 8, 6, 4}
|
||||
|
||||
sorted := heap.HeapSort(input)
|
||||
|
||||
if !slices.IsSorted(sorted) {
|
||||
t.Errorf("HeapSort = %v, want ascending order", sorted)
|
||||
}
|
||||
if len(sorted) != len(input) {
|
||||
t.Errorf("len = %d, want %d", len(sorted), len(input))
|
||||
}
|
||||
}
|
||||
|
||||
func TestHeapSortAlreadySorted(t *testing.T) {
|
||||
sorted := heap.HeapSort([]int{1, 2, 3, 4, 5})
|
||||
|
||||
want := []int{1, 2, 3, 4, 5}
|
||||
if !slices.Equal(sorted, want) {
|
||||
t.Errorf("HeapSort = %v, want %v", sorted, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHeapSortReversed(t *testing.T) {
|
||||
sorted := heap.HeapSort([]int{5, 4, 3, 2, 1})
|
||||
|
||||
want := []int{1, 2, 3, 4, 5}
|
||||
if !slices.Equal(sorted, want) {
|
||||
t.Errorf("HeapSort = %v, want %v", sorted, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHeapSortSingleElement(t *testing.T) {
|
||||
sorted := heap.HeapSort([]int{42})
|
||||
|
||||
want := []int{42}
|
||||
if !slices.Equal(sorted, want) {
|
||||
t.Errorf("HeapSort = %v, want %v", sorted, want)
|
||||
}
|
||||
}
|
||||
|
||||
// Empty input returns nil rather than an empty slice.
|
||||
func TestHeapSortEmpty(t *testing.T) {
|
||||
sorted := heap.HeapSort([]int{})
|
||||
|
||||
if len(sorted) != 0 {
|
||||
t.Errorf("HeapSort on empty input = %v, want no elements", sorted)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHeapSortKeepsDuplicates(t *testing.T) {
|
||||
input := []int{3, 1, 3, 2, 1, 3}
|
||||
|
||||
sorted := heap.HeapSort(input)
|
||||
|
||||
want := []int{1, 1, 2, 3, 3, 3}
|
||||
if !slices.Equal(sorted, want) {
|
||||
t.Errorf("HeapSort = %v, want %v", sorted, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHeapSortNegativeValues(t *testing.T) {
|
||||
sorted := heap.HeapSort([]int{3, -5, 0, -1, 8, -5})
|
||||
|
||||
want := []int{-5, -5, -1, 0, 3, 8}
|
||||
if !slices.Equal(sorted, want) {
|
||||
t.Errorf("HeapSort = %v, want %v", sorted, want)
|
||||
}
|
||||
}
|
||||
|
||||
// Heapify clones the slice, so the caller's input must come back untouched.
|
||||
func TestHeapSortDoesNotMutateInput(t *testing.T) {
|
||||
input := []int{5, 3, 9, 1, 7}
|
||||
original := slices.Clone(input)
|
||||
|
||||
heap.HeapSort(input)
|
||||
|
||||
if !slices.Equal(input, original) {
|
||||
t.Errorf("input was mutated: got %v, want %v", input, original)
|
||||
}
|
||||
}
|
||||
|
||||
// HeapSort is generic over cmp.Ordered, not just numbers.
|
||||
func TestHeapSortStrings(t *testing.T) {
|
||||
sorted := heap.HeapSort([]string{"pear", "apple", "fig", "banana"})
|
||||
|
||||
want := []string{"apple", "banana", "fig", "pear"}
|
||||
if !slices.Equal(sorted, want) {
|
||||
t.Errorf("HeapSort = %v, want %v", sorted, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHeapSortFloats(t *testing.T) {
|
||||
sorted := heap.HeapSort([]float64{2.5, -1.5, 0.0, 10.25, 2.4})
|
||||
|
||||
want := []float64{-1.5, 0.0, 2.4, 2.5, 10.25}
|
||||
if !slices.Equal(sorted, want) {
|
||||
t.Errorf("HeapSort = %v, want %v", sorted, want)
|
||||
}
|
||||
}
|
||||
|
||||
// Fuzz-ish check against the standard library over many random inputs.
|
||||
func TestHeapSortMatchesSlicesSort(t *testing.T) {
|
||||
random := rand.New(rand.NewSource(1))
|
||||
|
||||
for round := range 200 {
|
||||
size := random.Intn(50)
|
||||
input := make([]int, size)
|
||||
for i := range input {
|
||||
input[i] = random.Intn(100) - 50
|
||||
}
|
||||
|
||||
want := slices.Clone(input)
|
||||
slices.Sort(want)
|
||||
|
||||
got := heap.HeapSort(input)
|
||||
|
||||
if size == 0 {
|
||||
if len(got) != 0 {
|
||||
t.Fatalf("round %d: HeapSort on empty input = %v", round, got)
|
||||
}
|
||||
continue
|
||||
}
|
||||
if !slices.Equal(got, want) {
|
||||
t.Fatalf("round %d: HeapSort(%v) = %v, want %v", round, input, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package heap
|
||||
|
||||
import (
|
||||
"cmp"
|
||||
)
|
||||
|
||||
// HeapSort() -> takes in an array and returns it sorted. O(n log n)
|
||||
func HeapSort[T cmp.Ordered](arg []T) []T {
|
||||
if len(arg) <= 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
heap := NewMinHeap[T]()
|
||||
heap.Heapify(arg)
|
||||
|
||||
sorted := make([]T, 0, len(arg))
|
||||
|
||||
for range heap.Array {
|
||||
|
||||
val, ok := heap.PopMin()
|
||||
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
|
||||
sorted = append(sorted, val)
|
||||
}
|
||||
|
||||
return sorted
|
||||
}
|
||||
@@ -4,31 +4,6 @@ import (
|
||||
"cmp"
|
||||
)
|
||||
|
||||
// HeapSrort() -> takes in an array and returns it sorted. O(n log n)
|
||||
func HeapSrort[T cmp.Ordered](arg []T) []T {
|
||||
if len(arg) <= 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
heap := NewMinHeap[T]()
|
||||
heap.Heapify(arg)
|
||||
|
||||
sorted := make([]T, 0, len(arg))
|
||||
|
||||
for range heap.Array {
|
||||
|
||||
val, ok := heap.PopMin()
|
||||
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
|
||||
sorted = append(sorted, val)
|
||||
}
|
||||
|
||||
return sorted
|
||||
}
|
||||
|
||||
// PriorityQueue
|
||||
type PriorityQueue[T cmp.Ordered] struct {
|
||||
heap MinHeap[T]
|
||||
Reference in New Issue
Block a user