@@ -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"
|
"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
|
// PriorityQueue
|
||||||
type PriorityQueue[T cmp.Ordered] struct {
|
type PriorityQueue[T cmp.Ordered] struct {
|
||||||
heap MinHeap[T]
|
heap MinHeap[T]
|
||||||
Reference in New Issue
Block a user