From 4ea857183a71ac609dba19c2de618768ca748a22 Mon Sep 17 00:00:00 2001 From: Emir Pasic Date: Wed, 7 Sep 2016 03:51:19 +0200 Subject: [PATCH] - optimization to bulk insert into heap as per @cristaloleg suggestion #32 --- README.md | 4 +--- trees/binaryheap/binaryheap.go | 28 ++++++++++++++++++++++------ trees/binaryheap/binaryheap_test.go | 13 +++++++++++++ 3 files changed, 36 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 0534ddf..e1bdca6 100644 --- a/README.md +++ b/README.md @@ -710,9 +710,7 @@ func main() { return -utils.IntComparator(a, b) } heap = binaryheap.NewWith(inverseIntComparator) // empty (min-heap) - heap.Push(2) // 2 - heap.Push(3) // 3, 2 - heap.Push(1) // 3, 2, 1 + heap.Push(2, 3, 1) // 3, 2, 1 (bulk optimized) heap.Values() // 3, 2, 1 } ``` diff --git a/trees/binaryheap/binaryheap.go b/trees/binaryheap/binaryheap.go index 0ba9284..70b28cf 100644 --- a/trees/binaryheap/binaryheap.go +++ b/trees/binaryheap/binaryheap.go @@ -45,9 +45,20 @@ func NewWithStringComparator() *Heap { } // Push adds a value onto the heap and bubbles it up accordingly. -func (heap *Heap) Push(value interface{}) { - heap.list.Add(value) - heap.bubbleUp() +func (heap *Heap) Push(values ...interface{}) { + if len(values) == 1 { + heap.list.Add(values[0]) + heap.bubbleUp() + } else { + // Reference: https://en.wikipedia.org/wiki/Binary_heap#Building_a_heap + for _, value := range values { + heap.list.Add(value) + } + size := heap.list.Size()/2 + 1 + for i := size; i >= 0; i-- { + heap.bubbleDownIndex(i) + } + } } // Pop removes top element on heap and returns it, or nil if heap is empty. @@ -101,10 +112,15 @@ func (heap *Heap) String() string { return str } -// Performs the "bubble down" operation. This is to place the element that is at the -// root of the heap in its correct place so that the heap maintains the min/max-heap order property. +// Performs the "bubble down" operation. This is to place the element that is at the root +// of the heap in its correct place so that the heap maintains the min/max-heap order property. func (heap *Heap) bubbleDown() { - index := 0 + heap.bubbleDownIndex(0) +} + +// Performs the "bubble down" operation. This is to place the element that is at the index +// of the heap in its correct place so that the heap maintains the min/max-heap order property. +func (heap *Heap) bubbleDownIndex(index int) { size := heap.list.Size() for leftIndex := index<<1 + 1; leftIndex < size; leftIndex = index<<1 + 1 { rightIndex := index<<1 + 2 diff --git a/trees/binaryheap/binaryheap_test.go b/trees/binaryheap/binaryheap_test.go index 36ce9f9..a20d647 100644 --- a/trees/binaryheap/binaryheap_test.go +++ b/trees/binaryheap/binaryheap_test.go @@ -34,6 +34,19 @@ func TestBinaryHeapPush(t *testing.T) { } } +func TestBinaryHeapPushBulk(t *testing.T) { + heap := NewWithIntComparator() + + heap.Push(15, 20, 3, 1, 2) + + if actualValue := heap.Values(); actualValue[0].(int) != 1 || actualValue[1].(int) != 2 || actualValue[2].(int) != 3 { + t.Errorf("Got %v expected %v", actualValue, "[1,2,3]") + } + if actualValue, ok := heap.Pop(); actualValue != 1 || !ok { + t.Errorf("Got %v expected %v", actualValue, 1) + } +} + func TestBinaryHeapPop(t *testing.T) { heap := NewWithIntComparator()