github.com/searKing/golang/go@v1.2.117/exp/slices/heap.go (about) 1 // Copyright 2023 The searKing Author. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package slices 6 7 import ( 8 "cmp" 9 ) 10 11 // An MinHeap is a min-heap of slices. 12 type MinHeap[E cmp.Ordered] []E 13 14 func (h MinHeap[E]) Len() int { return len(h) } 15 func (h MinHeap[E]) Less(i, j int) bool { return h[i] < h[j] } 16 func (h MinHeap[E]) Swap(i, j int) { h[i], h[j] = h[j], h[i] } 17 18 func (h *MinHeap[E]) Push(x any) { 19 // Push and Pop use pointer receivers because they modify the slice's length, 20 // not just its contents. 21 *h = append(*h, x.(E)) 22 } 23 24 func (h *MinHeap[E]) Pop() any { 25 old := *h 26 n := len(old) 27 x := old[n-1] 28 *h = old[0 : n-1] 29 return x 30 } 31 32 // An MaxHeap is a max-heap of slices. 33 type MaxHeap[E cmp.Ordered] []E 34 35 func (h MaxHeap[E]) Len() int { return len(h) } 36 func (h MaxHeap[E]) Less(i, j int) bool { return h[i] > h[j] } 37 func (h MaxHeap[E]) Swap(i, j int) { h[i], h[j] = h[j], h[i] } 38 39 func (h *MaxHeap[E]) Push(x any) { 40 // Push and Pop use pointer receivers because they modify the slice's length, 41 // not just its contents. 42 *h = append(*h, x.(E)) 43 } 44 45 func (h *MaxHeap[E]) Pop() any { 46 old := *h 47 n := len(old) 48 x := old[n-1] 49 *h = old[0 : n-1] 50 return x 51 } 52 53 type Heap[S ~[]E, E any] struct { 54 S S 55 56 Comparator func(v1 E, v2 E) int 57 } 58 59 func NewHeapMin[S ~[]E, E cmp.Ordered](s S) *Heap[S, E] { 60 return &Heap[S, E]{ 61 S: s, 62 Comparator: cmp.Compare[E], 63 } 64 } 65 66 func NewHeapMax[S ~[]E, E cmp.Ordered](s S) *Heap[S, E] { 67 return &Heap[S, E]{ 68 S: s, 69 Comparator: func(v1 E, v2 E) int { 70 return cmp.Compare[E](v2, v1) 71 }, 72 } 73 } 74 75 func NewHeapFunc[S ~[]E, E any](s S, cmp func(a E, b E) int) *Heap[S, E] { 76 return &Heap[S, E]{ 77 S: s, 78 Comparator: cmp, 79 } 80 } 81 82 func (h Heap[S, E]) Len() int { return len(h.S) } 83 84 func (h Heap[S, E]) Less(i, j int) bool { 85 if h.Comparator == nil { // nop, don't sort 86 return true 87 } 88 return h.Comparator(h.S[i], h.S[j]) < 0 89 } 90 91 func (h Heap[S, E]) Swap(i, j int) { h.S[i], h.S[j] = h.S[j], h.S[i] } 92 93 func (h *Heap[S, E]) Push(x any) { // add x as element Len() 94 // Push and Pop use pointer receivers because they modify the slice's length, 95 // not just its contents. 96 h.S = append(h.S, x.(E)) 97 } 98 99 func (h *Heap[S, E]) Pop() any { // remove and return element Len() - 1. 100 old := h.S 101 n := len(old) 102 x := old[n-1] 103 h.S = old[0 : n-1] 104 return x 105 }