package ds import ( "math/rand" "sort" "testing" ) func TestHeapMinOrder(t *testing.T) { h := NewHeap[int](func(a, b int) bool { return a < b }) for _, v := range []int{5, 3, 8, 1, 4, 7, 9, 2, 6} { h.Push(v) } var got []int for !h.Empty() { v, _ := h.Pop() got = append(got, v) } want := []int{1, 2, 3, 4, 5, 6, 7, 8, 9} for i := range want { if got[i] != want[i] { t.Fatalf("Pop 顺序[%d] = %d, want %d", i, got[i], want[i]) } } } func TestHeapMaxOrder(t *testing.T) { h := NewHeap[int](func(a, b int) bool { return a > b }) // 大顶堆 for _, v := range []int{5, 3, 8, 1, 4} { h.Push(v) } top, _ := h.Peek() if top != 8 { t.Fatalf("大顶堆 Peek = %d, want 8", top) } var got []int for !h.Empty() { v, _ := h.Pop() got = append(got, v) } want := []int{8, 5, 4, 3, 1} for i := range want { if got[i] != want[i] { t.Fatalf("大顶堆 Pop[%d] = %d, want %d", i, got[i], want[i]) } } } func TestHeapInit(t *testing.T) { h := NewHeap[int](func(a, b int) bool { return a < b }) data := []int{9, 5, 2, 7, 1, 8, 3} // Init 后 h 持有 data 的底层数组,Pop 会原地修改它。 // 所以 ref 必须在 Init 之前拷贝,避免被破坏。 ref := make([]int, len(data)) copy(ref, data) sort.Ints(ref) h.Init(data) if top, _ := h.Peek(); top != 1 { t.Fatalf("Init 后 Peek = %d, want 1", top) } var got []int for !h.Empty() { v, _ := h.Pop() got = append(got, v) } for i := range ref { if got[i] != ref[i] { t.Fatalf("Init+Pop[%d] = %d, want %d", i, got[i], ref[i]) } } } func TestHeapEmpty(t *testing.T) { h := NewHeap[int](func(a, b int) bool { return a < b }) if _, ok := h.Pop(); ok { t.Fatal("空堆 Pop 应返回 false") } if _, ok := h.Peek(); ok { t.Fatal("空堆 Peek 应返回 false") } } func TestHeapRandomVsSort(t *testing.T) { // 随机数据:堆弹出顺序应与排序结果一致。 h := NewHeap[int](func(a, b int) bool { return a < b }) rng := rand.New(rand.NewSource(42)) const N = 2000 ref := make([]int, N) for i := 0; i < N; i++ { v := rng.Intn(10000) h.Push(v) ref[i] = v } sort.Ints(ref) for i := 0; i < N; i++ { v, ok := h.Pop() if !ok || v != ref[i] { t.Fatalf("随机测试[%d] = %d,%v, want %d", i, v, ok, ref[i]) } } } func TestHeapString(t *testing.T) { h := NewHeap[string](func(a, b string) bool { return a < b }) for _, s := range []string{"banana", "apple", "cherry"} { h.Push(s) } first, _ := h.Pop() if first != "apple" { t.Fatalf("字符串堆 Pop = %q, want \"apple\"", first) } }