summaryrefslogtreecommitdiff
path: root/libgo/go/container/heap/heap.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/container/heap/heap.go')
-rw-r--r--libgo/go/container/heap/heap.go102
1 files changed, 102 insertions, 0 deletions
diff --git a/libgo/go/container/heap/heap.go b/libgo/go/container/heap/heap.go
new file mode 100644
index 000000000..4435a57c4
--- /dev/null
+++ b/libgo/go/container/heap/heap.go
@@ -0,0 +1,102 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This package provides heap operations for any type that implements
+// heap.Interface.
+//
+package heap
+
+import "sort"
+
+// Any type that implements heap.Interface may be used as a
+// min-heap with the following invariants (established after
+// Init has been called):
+//
+// !h.Less(j, i) for 0 <= i < h.Len() and j = 2*i+1 or 2*i+2 and j < h.Len()
+//
+type Interface interface {
+ sort.Interface
+ Push(x interface{})
+ Pop() interface{}
+}
+
+
+// A heaper must be initialized before any of the heap operations
+// can be used. Init is idempotent with respect to the heap invariants
+// and may be called whenever the heap invariants may have been invalidated.
+// Its complexity is O(n) where n = h.Len().
+//
+func Init(h Interface) {
+ // heapify
+ n := h.Len()
+ for i := n/2 - 1; i >= 0; i-- {
+ down(h, i, n)
+ }
+}
+
+
+// Push pushes the element x onto the heap. The complexity is
+// O(log(n)) where n = h.Len().
+//
+func Push(h Interface, x interface{}) {
+ h.Push(x)
+ up(h, h.Len()-1)
+}
+
+
+// Pop removes the minimum element (according to Less) from the heap
+// and returns it. The complexity is O(log(n)) where n = h.Len().
+// Same as Remove(h, 0).
+//
+func Pop(h Interface) interface{} {
+ n := h.Len() - 1
+ h.Swap(0, n)
+ down(h, 0, n)
+ return h.Pop()
+}
+
+
+// Remove removes the element at index i from the heap.
+// The complexity is O(log(n)) where n = h.Len().
+//
+func Remove(h Interface, i int) interface{} {
+ n := h.Len() - 1
+ if n != i {
+ h.Swap(i, n)
+ down(h, i, n)
+ up(h, i)
+ }
+ return h.Pop()
+}
+
+
+func up(h Interface, j int) {
+ for {
+ i := (j - 1) / 2 // parent
+ if i == j || h.Less(i, j) {
+ break
+ }
+ h.Swap(i, j)
+ j = i
+ }
+}
+
+
+func down(h Interface, i, n int) {
+ for {
+ j1 := 2*i + 1
+ if j1 >= n {
+ break
+ }
+ j := j1 // left child
+ if j2 := j1 + 1; j2 < n && !h.Less(j1, j2) {
+ j = j2 // = 2*i + 2 // right child
+ }
+ if h.Less(i, j) {
+ break
+ }
+ h.Swap(i, j)
+ i = j
+ }
+}