Skip to content

Commit cff8a71

Browse files
committed
container/heap: use sort.Interface where possible
Functions heap.Pop(), heap.Push() and heap.Remove() use type heap.Interface. This type is equal to sort.Interface, with Push() and Pop() methods added. This is necessary, because these functions affect the size of the resulting heap. Functions heap.Fix() and heap.Init() are different. They may compare and swap elements in the underlying container, but never alter its size. It is therefore possible to just use sort.Interface. This would make these functions a lot more pleasant to use in situations where you know the number of elements in the heap is fixed. Consider the case where you use these functions to merge the results of n infinitely long monotonically increasing sequences. For example, logs received from multiple sources that need to be turned into a single stream of events sorted by time. This can now be implemented as follows: type Value ... type Sequence <-chan Value type PeekedSequence struct { First Value Remainder Sequence } type SequenceHeap []PeekedSequence func (h SequenceHeap) Len() int { return len(h) } func (h SequenceHeap) Less(i, j int) bool { return h[i].First < h[j].First } func (h SequenceHeap) Swap(i, j int) { h[i], h[j] = h[j], h[i] } func MergeSequences(sequences []Sequence, out chan<- Value) { h := make(SequenceHeap, 0, len(sequences)) for _, s := range sequences { h = append(h, PeekedSequence{ First: <-s, Remainder: s, }) } heap.Init(h) for { out <- h[0].First h[0].First = <-h[0].Remainder heap.Fix(h, 0) } } Before this change was made, SequenceHeap had to provide Pop() and Push() methods that are known to be unused.
1 parent 7fd62ba commit cff8a71

File tree

1 file changed

+4
-4
lines changed

1 file changed

+4
-4
lines changed

src/container/heap/heap.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ type Interface interface {
3838
// Init is idempotent with respect to the heap invariants
3939
// and may be called whenever the heap invariants may have been invalidated.
4040
// The complexity is O(n) where n = h.Len().
41-
func Init(h Interface) {
41+
func Init(h sort.Interface) {
4242
// heapify
4343
n := h.Len()
4444
for i := n/2 - 1; i >= 0; i-- {
@@ -80,13 +80,13 @@ func Remove(h Interface, i int) any {
8080
// Changing the value of the element at index i and then calling Fix is equivalent to,
8181
// but less expensive than, calling [Remove](h, i) followed by a Push of the new value.
8282
// The complexity is O(log n) where n = h.Len().
83-
func Fix(h Interface, i int) {
83+
func Fix(h sort.Interface, i int) {
8484
if !down(h, i, h.Len()) {
8585
up(h, i)
8686
}
8787
}
8888

89-
func up(h Interface, j int) {
89+
func up(h sort.Interface, j int) {
9090
for {
9191
i := (j - 1) / 2 // parent
9292
if i == j || !h.Less(j, i) {
@@ -97,7 +97,7 @@ func up(h Interface, j int) {
9797
}
9898
}
9999

100-
func down(h Interface, i0, n int) bool {
100+
func down(h sort.Interface, i0, n int) bool {
101101
i := i0
102102
for {
103103
j1 := 2*i + 1

0 commit comments

Comments
 (0)