1
0
mirror of https://github.com/golang/go synced 2024-11-12 09:50:21 -07:00

heap algorithm

R=rsc
DELTA=196  (194 added, 0 deleted, 2 changed)
OCL=34234
CL=34263
This commit is contained in:
Robert Griesemer 2009-09-02 12:54:38 -07:00
parent e10ca39d04
commit 115c62de8d
5 changed files with 196 additions and 2 deletions

View File

@ -3,10 +3,11 @@ base64.install: bytes.install io.install os.install strconv.install
big.install:
bignum.install: fmt.install
bufio.install: io.install os.install strconv.install utf8.install
bytes.install: os.install utf8.install
bytes.install: os.install unicode.install utf8.install
compress/flate.install: bufio.install io.install os.install strconv.install
compress/gzip.install: bufio.install compress/flate.install hash.install hash/crc32.install io.install os.install
compress/zlib.install: bufio.install compress/flate.install hash.install hash/adler32.install io.install os.install
container/heap.install: sort.install
container/list.install:
container/ring.install:
container/vector.install:
@ -53,7 +54,7 @@ rpc.install: bufio.install fmt.install gob.install http.install io.install log.i
runtime.install:
sort.install:
strconv.install: bytes.install math.install os.install unicode.install utf8.install
strings.install: utf8.install
strings.install: unicode.install utf8.install
sync.install:
syscall.install: sync.install
tabwriter.install: bytes.install container/vector.install io.install os.install utf8.install

View File

@ -21,6 +21,7 @@ DIRS=\
compress/flate\
compress/gzip\
compress/zlib\
container/heap\
container/list\
container/ring\
container/vector\

View File

@ -0,0 +1,11 @@
# 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.
include $(GOROOT)/src/Make.$(GOARCH)
TARG=container/heap
GOFILES=\
heap.go\
include $(GOROOT)/src/Make.pkg

View File

@ -0,0 +1,82 @@
// 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
// HeapInterface.
//
package heap
import "sort"
// Any type that implements HeapInterface may be used as a
// heap with the following invariants (established after Init
// has been called):
//
// h.Less(i, j) for 0 <= i < h.Len() and j = 2*i+1 or 2*i+2 and j < h.Len()
//
type HeapInterface interface {
sort.SortInterface;
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*log(n)) where n = h.Len().
//
func Init(h HeapInterface) {
sort.Sort(h);
}
// Push pushes the element x onto the heap. The complexity is
// O(log(n)) where n = h.Len().
//
func Push(h HeapInterface, 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().
//
func Pop(h HeapInterface) interface{} {
n := h.Len()-1;
h.Swap(0, n);
down(h, 0, n);
return h.Pop();
}
func up(h HeapInterface, j int) {
for {
i := (j-1)/2;
if i == j || h.Less(i, j) {
break;
}
h.Swap(i, j);
j = i;
}
}
func down(h HeapInterface, i, n int) {
for {
j := 2*i + 1;
if j >= n {
break;
}
if j1 := j+1; j1 < n && !h.Less(j, j1) {
j = j1; // = 2*i + 2
}
if h.Less(i, j) {
break;
}
h.Swap(i, j);
i = j;
}
}

View File

@ -0,0 +1,99 @@
// 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.
package heap
import (
"testing";
"container/vector";
)
type myHeap struct {
vector.IntVector;
}
func newHeap() *myHeap {
var h myHeap;
h.IntVector.Init(0);
return &h;
}
func (h *myHeap) verify(t *testing.T, i int) {
n := h.Len();
j1 := 2*i + 1;
j2 := 2*i + 2;
if j1 < n {
if h.Less(j1, i) {
t.Errorf("heap invariant invalidated [%d] = %d > [%d] = %d", i, h.At(i), j1, h.At(j1));
return;
}
h.verify(t, j1);
}
if j2 < n {
if h.Less(j2, i) {
t.Errorf("heap invariant invalidated [%d] = %d > [%d] = %d", i, h.At(i), j1, h.At(j2));
return;
}
h.verify(t, j2);
}
}
func (h *myHeap) Push(x interface{}) {
h.IntVector.Push(x.(int));
}
func (h *myHeap) Pop() interface{} {
return h.IntVector.Pop();
}
func TestInit(t *testing.T) {
h := newHeap();
for i := 20; i > 0; i-- {
h.Push(i);
}
Init(h);
h.verify(t, 0);
for i := 1; h.Len() > 0; i++ {
x := Pop(h).(int);
h.verify(t, 0);
if x != i {
t.Errorf("%d.th pop got %d; want %d", i, x, i);
}
}
}
func Test(t *testing.T) {
h := newHeap();
h.verify(t, 0);
for i := 20; i > 10; i-- {
h.Push(i);
}
Init(h);
h.verify(t, 0);
for i := 10; i > 0; i-- {
Push(h, i);
h.verify(t, 0);
}
for i := 1; h.Len() > 0; i++ {
x := Pop(h).(int);
if i < 20 {
Push(h, 20+i);
}
h.verify(t, 0);
if x != i {
t.Errorf("%d.th pop got %d; want %d", i, x, i);
}
}
}