Skip to content

Commit

Permalink
Simplify interface
Browse files Browse the repository at this point in the history
Inline bounds checks are not always necessary and
I'd rather not force a clunkier interface on
users. Just write your own functions:

	func Pop(q *FlatQueue) (int, bool) {
		if q.Len() == 0 {
			return 0, false
		}
		return q.Pop(), true
	}

	func Peek(q *FlatQueue) (int, bool) {
		if q.Len() == 0 {
			return 0, false
		}
		return q.Peek(), true
	}

	func PeekValue(q *FlatQueue) (float64, bool) {
		if q.Len() == 0 {
			return 0, false
		}
		return q.PeekValue(), true
	}
  • Loading branch information
invisiblefunnel committed Sep 19, 2021
1 parent a567c8b commit 0262637
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 88 deletions.
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

A Go port of the [flatqueue](https://github.com/mourner/flatqueue) priority queue library. Push items by identifier (`int`) and value (`float64`).

`Peek`, `PeekValue`, and `Pop` will panic if called on an empty queue. You must check `Len` accordingly.

```go
q := flatqueue.New()

Expand All @@ -12,12 +14,11 @@ for i, item := range items {
var (
id int
value float64
ok bool
)

id, ok = q.Peek() // top item index, ok if not empty
value, ok = q.PeekValue() // top item value, ok if not empty
id, ok = q.Pop() // remove and return the top item index, ok if not empty
id = q.Peek() // top item index
value = q.PeekValue() // top item value
id = q.Pop() // remove and return the top item index

// loop while queue is not empty
for q.Len() > 0 {
Expand Down
22 changes: 6 additions & 16 deletions flatqueue.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,7 @@ func (q *FlatQueue) Push(id int, value float64) {
q.values[pos] = value
}

func (q *FlatQueue) Pop() (int, bool) {
if q.length == 0 {
return 0, false
}

func (q *FlatQueue) Pop() int {
top := q.ids[0]
q.length--

Expand Down Expand Up @@ -91,19 +87,13 @@ func (q *FlatQueue) Pop() (int, bool) {
q.values[pos] = value
}

return top, true
return top
}

func (q *FlatQueue) Peek() (int, bool) {
if q.length == 0 {
return 0, false
}
return q.ids[0], true
func (q *FlatQueue) Peek() int {
return q.ids[0]
}

func (q *FlatQueue) PeekValue() (float64, bool) {
if q.length == 0 {
return 0, false
}
return q.values[0], true
func (q *FlatQueue) PeekValue() float64 {
return q.values[0]
}
114 changes: 46 additions & 68 deletions flatqueue_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,25 +29,18 @@ func testMaintainsPriorityQueue(t *testing.T, n int, q *FlatQueue) {
q.Push(i, v)
}

v, ok := q.PeekValue()
if v != sorted[0] || !ok {
if q.PeekValue() != sorted[0] {
t.Fatal()
}

id, ok := q.Peek()
if data[id] != sorted[0] || !ok {
if data[q.Peek()] != sorted[0] {
t.Fatal()
}

result := make([]float64, n)
i := 0
for q.Len() > 0 {
id, ok := q.Pop()
if !ok {
t.Fatal()
}

result[i] = data[id]
result[i] = data[q.Pop()]
i++
}

Expand Down Expand Up @@ -81,10 +74,6 @@ func testLen(t *testing.T, q *FlatQueue) {
if q.Pop(); q.Len() != 0 {
t.Fatal()
}

if q.Pop(); q.Len() != 0 {
t.Fatal()
}
}

func TestPop(t *testing.T) {
Expand All @@ -93,28 +82,14 @@ func TestPop(t *testing.T) {
}

func testPop(t *testing.T, q *FlatQueue) {
// empty
_, ok := q.Pop()
if ok {
t.Fatal()
}

q.Push(1, 10)
q.Push(2, 11)

id, ok := q.Pop()
if id != 1 || !ok {
t.Fatal()
}

id, ok = q.Pop()
if id != 2 || !ok {
if q.Pop() != 1 {
t.Fatal()
}

// empty
_, ok = q.Pop()
if ok {
if q.Pop() != 2 {
t.Fatal()
}
}
Expand All @@ -127,40 +102,30 @@ func TestPeek(t *testing.T) {
func testPeek(t *testing.T, q *FlatQueue) {
q.Push(1, 10)

id, ok := q.Peek()
if id != 1 || !ok {
if q.Peek() != 1 {
t.Fatal()
}

q.Push(2, 11)

id, ok = q.Peek()
if id != 1 || !ok {
if q.Peek() != 1 {
t.Fatal()
}

q.Push(3, 9)

id, ok = q.Peek()
if id != 3 || !ok {
if q.Peek() != 3 {
t.Fatal()
}

q.Pop()

id, ok = q.Peek()
if id != 1 || !ok {
if q.Peek() != 1 {
t.Fatal()
}

q.Pop()
q.Pop()

// empty
_, ok = q.Peek()
if ok {
t.Fatal()
}
}

func TestPeekValue(t *testing.T) {
Expand All @@ -169,48 +134,32 @@ func TestPeekValue(t *testing.T) {
}

func testPeekValue(t *testing.T, q *FlatQueue) {
// empty
_, ok := q.PeekValue()
if ok {
t.Fatal()
}

q.Push(1, 10)

value, ok := q.PeekValue()
if value != float64(10) || !ok {
if q.PeekValue() != float64(10) {
t.Fatal()
}

q.Push(2, 11)

value, ok = q.PeekValue()
if value != float64(10) || !ok {
if q.PeekValue() != float64(10) {
t.Fatal()
}

q.Push(3, 9)

value, ok = q.PeekValue()
if value != float64(9) || !ok {
if q.PeekValue() != float64(9) {
t.Fatal()
}

q.Pop()

value, ok = q.PeekValue()
if value != float64(10) || !ok {
if q.PeekValue() != float64(10) {
t.Fatal()
}

q.Pop()
q.Pop()

// empty
_, ok = q.PeekValue()
if ok {
t.Fatal()
}
}

func TestEdgeCasesWithFewElements(t *testing.T) {
Expand All @@ -226,17 +175,42 @@ func testEdgeCasesWithFewElements(t *testing.T, q *FlatQueue) {
q.Push(2, 2)
q.Push(3, 1)

id, ok := q.Pop()
if id != 3 || !ok {
if q.Pop() != 3 {
t.Fatal()
}

id, ok = q.Pop()
if id != 2 || !ok {
if q.Pop() != 2 {
t.Fatal()
}
}

func TestPeekEmpty(t *testing.T) {
defer func() {
if recover() == nil {
t.Fatal()
}
}()
New().Peek()
}

func TestPeekValueEmpty(t *testing.T) {
defer func() {
if recover() == nil {
t.Fatal()
}
}()
New().PeekValue()
}

func TestPopEmpty(t *testing.T) {
defer func() {
if recover() == nil {
t.Fatal()
}
}()
New().Pop()
}

func BenchmarkPush(b *testing.B) {
q := New()

Expand All @@ -245,6 +219,7 @@ func BenchmarkPush(b *testing.B) {
values[i] = randFloat64(-1000, 1000)
}

b.ReportAllocs()
b.ResetTimer()

for i := 0; i < b.N; i++ {
Expand All @@ -260,6 +235,7 @@ func BenchmarkPushWithCapacity(b *testing.B) {
values[i] = randFloat64(-1000, 1000)
}

b.ReportAllocs()
b.ResetTimer()

for i := 0; i < b.N; i++ {
Expand All @@ -274,6 +250,7 @@ func BenchmarkPop(b *testing.B) {
q.Push(i, randFloat64(-1000, 1000))
}

b.ReportAllocs()
b.ResetTimer()

for i := 0; i < b.N; i++ {
Expand All @@ -288,6 +265,7 @@ func BenchmarkPopWithCapacity(b *testing.B) {
q.Push(i, randFloat64(-1000, 1000))
}

b.ReportAllocs()
b.ResetTimer()

for i := 0; i < b.N; i++ {
Expand Down

0 comments on commit 0262637

Please sign in to comment.