Merge pull request #203 from emirpasic/development

Implements PriorityQueue and CircularBuffer
pull/205/head v1.18.0
Emir Pasic 2 years ago committed by GitHub
commit 773505cfec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -39,6 +39,8 @@ Implementation of various data structures and algorithms in Go.
- [Queues](#queues)
- [LinkedListQueue](#linkedlistqueue)
- [ArrayQueue](#arrayqueue)
- [CircularBuffer](#circularbuffer)
- [PriorityQueue](#priorityqueue)
- [Functions](#functions)
- [Comparator](#comparator)
- [Iterator](#iterator)
@ -67,40 +69,42 @@ type Container interface {
Size() int
Clear()
Values() []interface{}
String() string
String() string
}
```
Containers are either ordered or unordered. All ordered containers provide [stateful iterators](#iterator) and some of them allow [enumerable functions](#enumerable).
| **Data** | **Structure** | **Ordered** | **[Iterator](#iterator)** | **[Enumerable](#enumerable)** | **Referenced by** |
| :--- | :--- | :---: | :---: | :---: | :---: |
| **Data** | **Structure** | **Ordered** | **[Iterator](#iterator)** | **[Enumerable](#enumerable)** | **Referenced by** |
| :--- |:--------------------------------------| :---: | :---: | :---: | :---: |
| [Lists](#lists) |
| | [ArrayList](#arraylist) | yes | yes* | yes | index |
| | [ArrayList](#arraylist) | yes | yes* | yes | index |
| | [SinglyLinkedList](#singlylinkedlist) | yes | yes | yes | index |
| | [DoublyLinkedList](#doublylinkedlist) | yes | yes* | yes | index |
| [Sets](#sets) |
| | [HashSet](#hashset) | no | no | no | index |
| | [TreeSet](#treeset) | yes | yes* | yes | index |
| | [LinkedHashSet](#linkedhashset) | yes | yes* | yes | index |
| | [HashSet](#hashset) | no | no | no | index |
| | [TreeSet](#treeset) | yes | yes* | yes | index |
| | [LinkedHashSet](#linkedhashset) | yes | yes* | yes | index |
| [Stacks](#stacks) |
| | [LinkedListStack](#linkedliststack) | yes | yes | no | index |
| | [ArrayStack](#arraystack) | yes | yes* | no | index |
| | [LinkedListStack](#linkedliststack) | yes | yes | no | index |
| | [ArrayStack](#arraystack) | yes | yes* | no | index |
| [Maps](#maps) |
| | [HashMap](#hashmap) | no | no | no | key |
| | [TreeMap](#treemap) | yes | yes* | yes | key |
| | [LinkedHashMap](#linkedhashmap) | yes | yes* | yes | key |
| | [HashBidiMap](#hashbidimap) | no | no | no | key* |
| | [TreeBidiMap](#treebidimap) | yes | yes* | yes | key* |
| | [HashMap](#hashmap) | no | no | no | key |
| | [TreeMap](#treemap) | yes | yes* | yes | key |
| | [LinkedHashMap](#linkedhashmap) | yes | yes* | yes | key |
| | [HashBidiMap](#hashbidimap) | no | no | no | key* |
| | [TreeBidiMap](#treebidimap) | yes | yes* | yes | key* |
| [Trees](#trees) |
| | [RedBlackTree](#redblacktree) | yes | yes* | no | key |
| | [AVLTree](#avltree) | yes | yes* | no | key |
| | [BTree](#btree) | yes | yes* | no | key |
| | [BinaryHeap](#binaryheap) | yes | yes* | no | index |
| | [RedBlackTree](#redblacktree) | yes | yes* | no | key |
| | [AVLTree](#avltree) | yes | yes* | no | key |
| | [BTree](#btree) | yes | yes* | no | key |
| | [BinaryHeap](#binaryheap) | yes | yes* | no | index |
| [Queues](#queues) |
| | [LinkedListQueue](#linkedlistqueue) | yes | yes | no | index |
| | [ArrayQueue](#arrayqueue) | yes | yes* | no | index |
| | | | <sub><sup>*reversible</sup></sub> | | <sub><sup>*bidirectional</sup></sub> |
| | [LinkedListQueue](#linkedlistqueue) | yes | yes | no | index |
| | [ArrayQueue](#arrayqueue) | yes | yes* | no | index |
| | [CircularBuffer](#circularbuffer) | yes | yes* | no | index |
| | [PriorityQueue](#priorityqueue) | yes | yes* | no | index |
| | | | <sub><sup>*reversible</sup></sub> | | <sub><sup>*bidirectional</sup></sub> |
### Lists
@ -949,6 +953,88 @@ func main() {
}
```
#### CircularBuffer
A circular buffer, circular [queue](#queues), cyclic buffer or ring buffer is a data structure that uses a single, fixed-size buffer as if it were connected end-to-end. This structure lends itself easily to buffering data streams.
<p align="center"><img src="https://upload.wikimedia.org/wikipedia/commons/thumb/f/fd/Circular_Buffer_Animation.gif/400px-Circular_Buffer_Animation.gif" width="300px" height="300px" /></p>
Implements [Queue](#queues), [ReverseIteratorWithIndex](#iteratorwithindex), [JSONSerializer](#jsonserializer) and [JSONDeserializer](#jsondeserializer) interfaces.
```go
package main
import cb "github.com/emirpasic/gods/queues/circularbuffer"
// CircularBufferExample to demonstrate basic usage of CircularBuffer
func main() {
queue := cb.New(3) // empty (max size is 3)
queue.Enqueue(1) // 1
queue.Enqueue(2) // 1, 2
queue.Enqueue(3) // 1, 2, 3
_ = queue.Values() // 1, 2, 3
queue.Enqueue(3) // 4, 2, 3
_, _ = queue.Peek() // 4,true
_, _ = queue.Dequeue() // 4, true
_, _ = queue.Dequeue() // 2, true
_, _ = queue.Dequeue() // 3, true
_, _ = queue.Dequeue() // nil, false (nothing to deque)
queue.Enqueue(1) // 1
queue.Clear() // empty
queue.Empty() // true
_ = queue.Size() // 0
}
```
#### PriorityQueue
A priority queue is a special type of [queue](#queues) in which each element is associated with a priority value. And, elements are served on the basis of their priority. That is, higher priority elements are served first. However, if elements with the same priority occur, they are served according to their order in the queue.
Implements [Queue](#queues), [ReverseIteratorWithIndex](#iteratorwithindex), [JSONSerializer](#jsonserializer) and [JSONDeserializer](#jsondeserializer) interfaces.
```go
package main
import (
pq "github.com/emirpasic/gods/queues/priorityqueue"
"github.com/emirpasic/gods/utils"
)
// Element is an entry in the priority queue
type Element struct {
name string
priority int
}
// Comparator function (sort by element's priority value in descending order)
func byPriority(a, b interface{}) int {
priorityA := a.(Element).priority
priorityB := b.(Element).priority
return -utils.IntComparator(priorityA, priorityB) // "-" descending order
}
// PriorityQueueExample to demonstrate basic usage of BinaryHeap
func main() {
a := Element{name: "a", priority: 1}
b := Element{name: "b", priority: 2}
c := Element{name: "c", priority: 3}
queue := pq.NewWith(byPriority) // empty
queue.Enqueue(a) // {a 1}
queue.Enqueue(c) // {c 3}, {a 1}
queue.Enqueue(b) // {c 3}, {b 2}, {a 1}
_ = queue.Values() // [{c 3} {b 2} {a 1}]
_, _ = queue.Peek() // {c 3} true
_, _ = queue.Dequeue() // {c 3} true
_, _ = queue.Dequeue() // {b 2} true
_, _ = queue.Dequeue() // {a 1} true
_, _ = queue.Dequeue() // <nil> false (nothing to dequeue)
queue.Clear() // empty
_ = queue.Empty() // true
_ = queue.Size() // 0
}
```
## Functions
Various helper functions used throughout the library.

@ -0,0 +1,26 @@
// Copyright (c) 2015, Emir Pasic. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import cb "github.com/emirpasic/gods/queues/circularbuffer"
// CircularBufferExample to demonstrate basic usage of CircularBuffer
func main() {
queue := cb.New(3) // empty (max size is 3)
queue.Enqueue(1) // 1
queue.Enqueue(2) // 1, 2
queue.Enqueue(3) // 1, 2, 3
_ = queue.Values() // 1, 2, 3
queue.Enqueue(3) // 4, 2, 3
_, _ = queue.Peek() // 4,true
_, _ = queue.Dequeue() // 4, true
_, _ = queue.Dequeue() // 2, true
_, _ = queue.Dequeue() // 3, true
_, _ = queue.Dequeue() // nil, false (nothing to deque)
queue.Enqueue(1) // 1
queue.Clear() // empty
queue.Empty() // true
_ = queue.Size() // 0
}

@ -0,0 +1,44 @@
// Copyright (c) 2015, Emir Pasic. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
pq "github.com/emirpasic/gods/queues/priorityqueue"
"github.com/emirpasic/gods/utils"
)
// Element is an entry in the priority queue
type Element struct {
name string
priority int
}
// Comparator function (sort by element's priority value in descending order)
func byPriority(a, b interface{}) int {
priorityA := a.(Element).priority
priorityB := b.(Element).priority
return -utils.IntComparator(priorityA, priorityB) // "-" descending order
}
// PriorityQueueExample to demonstrate basic usage of BinaryHeap
func main() {
a := Element{name: "a", priority: 1}
b := Element{name: "b", priority: 2}
c := Element{name: "c", priority: 3}
queue := pq.NewWith(byPriority) // empty
queue.Enqueue(a) // {a 1}
queue.Enqueue(c) // {c 3}, {a 1}
queue.Enqueue(b) // {c 3}, {b 2}, {a 1}
_ = queue.Values() // [{c 3} {b 2} {a 1}]
_, _ = queue.Peek() // {c 3} true
_, _ = queue.Dequeue() // {c 3} true
_, _ = queue.Dequeue() // {b 2} true
_, _ = queue.Dequeue() // {a 1} true
_, _ = queue.Dequeue() // <nil> false (nothing to dequeue)
queue.Clear() // empty
_ = queue.Empty() // true
_ = queue.Size() // 0
}

@ -0,0 +1,153 @@
// Copyright (c) 2021, Emir Pasic. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package circularbuffer implements the circular buffer.
//
// In computer science, a circular buffer, circular queue, cyclic buffer or ring buffer is a data structure that uses a single, fixed-size buffer as if it were connected end-to-end. This structure lends itself easily to buffering data streams.
//
// Structure is not thread safe.
//
// Reference: https://en.wikipedia.org/wiki/Circular_buffer
package circularbuffer
import (
"fmt"
"strings"
"github.com/emirpasic/gods/queues"
)
// Assert Queue implementation
var _ queues.Queue = (*Queue)(nil)
// Queue holds values in a slice.
type Queue struct {
values []interface{}
start int
end int
full bool
maxSize int
size int
}
// New instantiates a new empty queue with the specified size of maximum number of elements that it can hold.
// This max size of the buffer cannot be changed.
func New(maxSize int) *Queue {
if maxSize < 1 {
panic("Invalid maxSize, should be at least 1")
}
queue := &Queue{maxSize: maxSize}
queue.Clear()
return queue
}
// Enqueue adds a value to the end of the queue
func (queue *Queue) Enqueue(value interface{}) {
if queue.Full() {
queue.Dequeue()
}
queue.values[queue.end] = value
queue.end = queue.end + 1
if queue.end >= queue.maxSize {
queue.end = 0
}
if queue.end == queue.start {
queue.full = true
}
queue.size = queue.calculateSize()
}
// Dequeue removes first element of the queue and returns it, or nil if queue is empty.
// Second return parameter is true, unless the queue was empty and there was nothing to dequeue.
func (queue *Queue) Dequeue() (value interface{}, ok bool) {
if queue.Empty() {
return nil, false
}
value, ok = queue.values[queue.start], true
if value != nil {
queue.values[queue.start] = nil
queue.start = queue.start + 1
if queue.start >= queue.maxSize {
queue.start = 0
}
queue.full = false
}
queue.size = queue.size - 1
return
}
// Peek returns first element of the queue without removing it, or nil if queue is empty.
// Second return parameter is true, unless the queue was empty and there was nothing to peek.
func (queue *Queue) Peek() (value interface{}, ok bool) {
if queue.Empty() {
return nil, false
}
return queue.values[queue.start], true
}
// Empty returns true if queue does not contain any elements.
func (queue *Queue) Empty() bool {
return queue.Size() == 0
}
// Full returns true if the queue is full, i.e. has reached the maximum number of elements that it can hold.
func (queue *Queue) Full() bool {
return queue.Size() == queue.maxSize
}
// Size returns number of elements within the queue.
func (queue *Queue) Size() int {
return queue.size
}
// Clear removes all elements from the queue.
func (queue *Queue) Clear() {
queue.values = make([]interface{}, queue.maxSize, queue.maxSize)
queue.start = 0
queue.end = 0
queue.full = false
queue.size = 0
}
// Values returns all elements in the queue (FIFO order).
func (queue *Queue) Values() []interface{} {
values := make([]interface{}, queue.Size(), queue.Size())
for i := 0; i < queue.Size(); i++ {
values[i] = queue.values[(queue.start+i)%queue.maxSize]
}
return values
}
// String returns a string representation of container
func (queue *Queue) String() string {
str := "CircularBuffer\n"
var values []string
for _, value := range queue.Values() {
values = append(values, fmt.Sprintf("%v", value))
}
str += strings.Join(values, ", ")
return str
}
// Check that the index is within bounds of the list
func (queue *Queue) withinRange(index int) bool {
return index >= 0 && index < queue.size
}
func (queue *Queue) calculateSize() int {
if queue.end < queue.start {
return queue.maxSize - queue.start + queue.end
} else if queue.end == queue.start {
if queue.full {
return queue.maxSize
}
return 0
}
return queue.end - queue.start
}

@ -0,0 +1,629 @@
// Copyright (c) 2015, Emir Pasic. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package circularbuffer
import (
"encoding/json"
"fmt"
"strings"
"testing"
)
func TestQueueEnqueue(t *testing.T) {
queue := New(3)
if actualValue := queue.Empty(); actualValue != true {
t.Errorf("Got %v expected %v", actualValue, true)
}
queue.Enqueue(1)
queue.Enqueue(2)
queue.Enqueue(3)
if actualValue := queue.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 := queue.Empty(); actualValue != false {
t.Errorf("Got %v expected %v", actualValue, false)
}
if actualValue := queue.Size(); actualValue != 3 {
t.Errorf("Got %v expected %v", actualValue, 3)
}
if actualValue, ok := queue.Peek(); actualValue != 1 || !ok {
t.Errorf("Got %v expected %v", actualValue, 1)
}
}
func TestQueuePeek(t *testing.T) {
queue := New(3)
if actualValue, ok := queue.Peek(); actualValue != nil || ok {
t.Errorf("Got %v expected %v", actualValue, nil)
}
queue.Enqueue(1)
queue.Enqueue(2)
queue.Enqueue(3)
if actualValue, ok := queue.Peek(); actualValue != 1 || !ok {
t.Errorf("Got %v expected %v", actualValue, 1)
}
}
func TestQueueDequeue(t *testing.T) {
assert := func(actualValue interface{}, expectedValue interface{}) {
if actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
}
queue := New(3)
assert(queue.Empty(), true)
assert(queue.Empty(), true)
assert(queue.Full(), false)
assert(queue.Size(), 0)
queue.Enqueue(1)
assert(queue.Size(), 1)
queue.Enqueue(2)
assert(queue.Size(), 2)
queue.Enqueue(3)
assert(queue.Size(), 3)
assert(queue.Empty(), false)
assert(queue.Full(), true)
queue.Dequeue()
assert(queue.Size(), 2)
if actualValue, ok := queue.Peek(); actualValue != 2 || !ok {
t.Errorf("Got %v expected %v", actualValue, 2)
}
assert(queue.Size(), 2)
if actualValue, ok := queue.Dequeue(); actualValue != 2 || !ok {
t.Errorf("Got %v expected %v", actualValue, 2)
}
assert(queue.Size(), 1)
if actualValue, ok := queue.Dequeue(); actualValue != 3 || !ok {
t.Errorf("Got %v expected %v", actualValue, 3)
}
assert(queue.Size(), 0)
assert(queue.Empty(), true)
assert(queue.Full(), false)
if actualValue, ok := queue.Dequeue(); actualValue != nil || ok {
t.Errorf("Got %v expected %v", actualValue, nil)
}
assert(queue.Size(), 0)
assert(queue.Empty(), true)
assert(queue.Full(), false)
assert(len(queue.Values()), 0)
}
func TestQueueDequeueFull(t *testing.T) {
assert := func(actualValue interface{}, expectedValue interface{}) {
if actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
}
queue := New(2)
assert(queue.Empty(), true)
assert(queue.Full(), false)
assert(queue.Size(), 0)
queue.Enqueue(1)
assert(queue.Size(), 1)
queue.Enqueue(2)
assert(queue.Size(), 2)
assert(queue.Full(), true)
if actualValue, ok := queue.Peek(); actualValue != 1 || !ok {
t.Errorf("Got %v expected %v", actualValue, 2)
}
queue.Enqueue(3) // overwrites 1
assert(queue.Size(), 2)
if actualValue, ok := queue.Dequeue(); actualValue != 2 || !ok {
t.Errorf("Got %v expected %v", actualValue, 2)
}
if actualValue, expectedValue := queue.Size(), 1; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
if actualValue, ok := queue.Peek(); actualValue != 3 || !ok {
t.Errorf("Got %v expected %v", actualValue, 3)
}
if actualValue, expectedValue := queue.Size(), 1; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
if actualValue, ok := queue.Dequeue(); actualValue != 3 || !ok {
t.Errorf("Got %v expected %v", actualValue, 3)
}
assert(queue.Size(), 0)
if actualValue, ok := queue.Dequeue(); actualValue != nil || ok {
t.Errorf("Got %v expected %v", actualValue, nil)
}
assert(queue.Empty(), true)
assert(queue.Full(), false)
assert(len(queue.Values()), 0)
}
func TestQueueIteratorOnEmpty(t *testing.T) {
queue := New(3)
it := queue.Iterator()
for it.Next() {
t.Errorf("Shouldn't iterate on empty queue")
}
}
func TestQueueIteratorNext(t *testing.T) {
queue := New(3)
queue.Enqueue("a")
queue.Enqueue("b")
queue.Enqueue("c")
it := queue.Iterator()
count := 0
for it.Next() {
count++
index := it.Index()
value := it.Value()
switch index {
case 0:
if actualValue, expectedValue := value, "a"; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
case 1:
if actualValue, expectedValue := value, "b"; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
case 2:
if actualValue, expectedValue := value, "c"; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
default:
t.Errorf("Too many")
}
if actualValue, expectedValue := index, count-1; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
}
if actualValue, expectedValue := count, 3; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
queue.Clear()
it = queue.Iterator()
for it.Next() {
t.Errorf("Shouldn't iterate on empty queue")
}
}
func TestQueueIteratorPrev(t *testing.T) {
queue := New(3)
queue.Enqueue("a")
queue.Enqueue("b")
queue.Enqueue("c")
it := queue.Iterator()
for it.Next() {
}
count := 0
for it.Prev() {
count++
index := it.Index()
value := it.Value()
switch index {
case 0:
if actualValue, expectedValue := value, "a"; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
case 1:
if actualValue, expectedValue := value, "b"; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
case 2:
if actualValue, expectedValue := value, "c"; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
default:
t.Errorf("Too many")
}
if actualValue, expectedValue := index, 3-count; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
}
if actualValue, expectedValue := count, 3; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
}
func TestQueueIteratorBegin(t *testing.T) {
queue := New(3)
it := queue.Iterator()
it.Begin()
queue.Enqueue("a")
queue.Enqueue("b")
queue.Enqueue("c")
for it.Next() {
}
it.Begin()
it.Next()
if index, value := it.Index(), it.Value(); index != 0 || value != "a" {
t.Errorf("Got %v,%v expected %v,%v", index, value, 0, "a")
}
}
func TestQueueIteratorEnd(t *testing.T) {
queue := New(3)
it := queue.Iterator()
if index := it.Index(); index != -1 {
t.Errorf("Got %v expected %v", index, -1)
}
it.End()
if index := it.Index(); index != 0 {
t.Errorf("Got %v expected %v", index, 0)
}
queue.Enqueue("a")
queue.Enqueue("b")
queue.Enqueue("c")
it.End()
if index := it.Index(); index != queue.Size() {
t.Errorf("Got %v expected %v", index, queue.Size())
}
it.Prev()
if index, value := it.Index(), it.Value(); index != queue.Size()-1 || value != "c" {
t.Errorf("Got %v,%v expected %v,%v", index, value, queue.Size()-1, "c")
}
}
func TestQueueIteratorFirst(t *testing.T) {
queue := New(3)
it := queue.Iterator()
if actualValue, expectedValue := it.First(), false; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
queue.Enqueue("a")
queue.Enqueue("b")
queue.Enqueue("c")
if actualValue, expectedValue := it.First(), true; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
if index, value := it.Index(), it.Value(); index != 0 || value != "a" {
t.Errorf("Got %v,%v expected %v,%v", index, value, 0, "a")
}
}
func TestQueueIteratorLast(t *testing.T) {
queue := New(3)
it := queue.Iterator()
if actualValue, expectedValue := it.Last(), false; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
queue.Enqueue("a")
queue.Enqueue("b")
queue.Enqueue("c")
if actualValue, expectedValue := it.Last(), true; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
if index, value := it.Index(), it.Value(); index != 2 || value != "c" {
t.Errorf("Got %v,%v expected %v,%v", index, value, 2, "c")
}
}
func TestQueueIteratorNextTo(t *testing.T) {
// Sample seek function, i.e. string starting with "b"
seek := func(index int, value interface{}) bool {
return strings.HasSuffix(value.(string), "b")
}
// NextTo (empty)
{
queue := New(3)
it := queue.Iterator()
for it.NextTo(seek) {
t.Errorf("Shouldn't iterate on empty queue")
}
}
// NextTo (not found)
{
queue := New(3)
queue.Enqueue("xx")
queue.Enqueue("yy")
it := queue.Iterator()
for it.NextTo(seek) {
t.Errorf("Shouldn't iterate on empty queue")
}
}
// NextTo (found)
{
queue := New(3)
queue.Enqueue("aa")
queue.Enqueue("bb")
queue.Enqueue("cc")
it := queue.Iterator()
it.Begin()
if !it.NextTo(seek) {
t.Errorf("Shouldn't iterate on empty queue")
}
if index, value := it.Index(), it.Value(); index != 1 || value.(string) != "bb" {
t.Errorf("Got %v,%v expected %v,%v", index, value, 1, "bb")
}
if !it.Next() {
t.Errorf("Should go to first element")
}
if index, value := it.Index(), it.Value(); index != 2 || value.(string) != "cc" {
t.Errorf("Got %v,%v expected %v,%v", index, value, 2, "cc")
}
if it.Next() {
t.Errorf("Should not go past last element")
}
}
}
func TestQueueIteratorPrevTo(t *testing.T) {
// Sample seek function, i.e. string starting with "b"
seek := func(index int, value interface{}) bool {
return strings.HasSuffix(value.(string), "b")
}
// PrevTo (empty)
{
queue := New(3)
it := queue.Iterator()
it.End()
for it.PrevTo(seek) {
t.Errorf("Shouldn't iterate on empty queue")
}
}
// PrevTo (not found)
{
queue := New(3)
queue.Enqueue("xx")
queue.Enqueue("yy")
it := queue.Iterator()
it.End()
for it.PrevTo(seek) {
t.Errorf("Shouldn't iterate on empty queue")
}
}
// PrevTo (found)
{
queue := New(3)
queue.Enqueue("aa")
queue.Enqueue("bb")
queue.Enqueue("cc")
it := queue.Iterator()
it.End()
if !it.PrevTo(seek) {
t.Errorf("Shouldn't iterate on empty queue")
}
if index, value := it.Index(), it.Value(); index != 1 || value.(string) != "bb" {
t.Errorf("Got %v,%v expected %v,%v", index, value, 1, "bb")
}
if !it.Prev() {
t.Errorf("Should go to first element")
}
if index, value := it.Index(), it.Value(); index != 0 || value.(string) != "aa" {
t.Errorf("Got %v,%v expected %v,%v", index, value, 0, "aa")
}
if it.Prev() {
t.Errorf("Should not go before first element")
}
}
}
func TestQueueIterator(t *testing.T) {
assert := func(actualValue interface{}, expectedValue interface{}) {
if actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
}
queue := New(2)
queue.Enqueue("a")
queue.Enqueue("b")
queue.Enqueue("c") // overwrites "a"
it := queue.Iterator()
if actualIndex, expectedIndex := it.Index(), -1; actualIndex != expectedIndex {
t.Errorf("Got %v expected %v", actualIndex, expectedIndex)
}
assert(it.Next(), true)
if actualValue, actualIndex, expectedValue, expectedIndex := it.Value(), it.Index(), "b", 0; actualValue != expectedValue || actualIndex != expectedIndex {
t.Errorf("Got %v expected %v, Got %v expected %v", actualValue, expectedValue, actualIndex, expectedIndex)
}
assert(it.Next(), true)
if actualValue, actualIndex, expectedValue, expectedIndex := it.Value(), it.Index(), "c", 1; actualValue != expectedValue || actualIndex != expectedIndex {
t.Errorf("Got %v expected %v, Got %v expected %v", actualValue, expectedValue, actualIndex, expectedIndex)
}
assert(it.Next(), false)
if actualIndex, expectedIndex := it.Index(), 2; actualIndex != expectedIndex {
t.Errorf("Got %v expected %v", actualIndex, expectedIndex)
}
assert(it.Next(), false)
assert(it.Prev(), true)
if actualValue, actualIndex, expectedValue, expectedIndex := it.Value(), it.Index(), "c", 1; actualValue != expectedValue || actualIndex != expectedIndex {
t.Errorf("Got %v expected %v, Got %v expected %v", actualValue, expectedValue, actualIndex, expectedIndex)
}
assert(it.Prev(), true)
if actualValue, actualIndex, expectedValue, expectedIndex := it.Value(), it.Index(), "b", 0; actualValue != expectedValue || actualIndex != expectedIndex {
t.Errorf("Got %v expected %v, Got %v expected %v", actualValue, expectedValue, actualIndex, expectedIndex)
}
assert(it.Prev(), false)
if actualIndex, expectedIndex := it.Index(), -1; actualIndex != expectedIndex {
t.Errorf("Got %v expected %v", actualIndex, expectedIndex)
}
}
func TestQueueSerialization(t *testing.T) {
queue := New(3)
queue.Enqueue("a")
queue.Enqueue("b")
queue.Enqueue("c")
var err error
assert := func() {
if actualValue, expectedValue := fmt.Sprintf("%s%s%s", queue.Values()...), "abc"; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
if actualValue, expectedValue := queue.Size(), 3; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
if err != nil {
t.Errorf("Got error %v", err)
}
}
assert()
bytes, err := queue.ToJSON()
assert()
err = queue.FromJSON(bytes)
assert()
bytes, err = json.Marshal([]interface{}{"a", "b", "c", queue})
if err != nil {
t.Errorf("Got error %v", err)
}
err = json.Unmarshal([]byte(`[1,2,3]`), &queue)
if err != nil {
t.Errorf("Got error %v", err)
}
}
func TestQueueString(t *testing.T) {
c := New(3)
c.Enqueue(1)
if !strings.HasPrefix(c.String(), "CircularBuffer") {
t.Errorf("String should start with container name")
}
}
func benchmarkEnqueue(b *testing.B, queue *Queue, size int) {
for i := 0; i < b.N; i++ {
for n := 0; n < size; n++ {
queue.Enqueue(n)
}
}
}
func benchmarkDequeue(b *testing.B, queue *Queue, size int) {
for i := 0; i < b.N; i++ {
for n := 0; n < size; n++ {
queue.Dequeue()
}
}
}
func BenchmarkArrayQueueDequeue100(b *testing.B) {
b.StopTimer()
size := 100
queue := New(3)
for n := 0; n < size; n++ {
queue.Enqueue(n)
}
b.StartTimer()
benchmarkDequeue(b, queue, size)
}
func BenchmarkArrayQueueDequeue1000(b *testing.B) {
b.StopTimer()
size := 1000
queue := New(3)
for n := 0; n < size; n++ {
queue.Enqueue(n)
}
b.StartTimer()
benchmarkDequeue(b, queue, size)
}
func BenchmarkArrayQueueDequeue10000(b *testing.B) {
b.StopTimer()
size := 10000
queue := New(3)
for n := 0; n < size; n++ {
queue.Enqueue(n)
}
b.StartTimer()
benchmarkDequeue(b, queue, size)
}
func BenchmarkArrayQueueDequeue100000(b *testing.B) {
b.StopTimer()
size := 100000
queue := New(3)
for n := 0; n < size; n++ {
queue.Enqueue(n)
}
b.StartTimer()
benchmarkDequeue(b, queue, size)
}
func BenchmarkArrayQueueEnqueue100(b *testing.B) {
b.StopTimer()
size := 100
queue := New(3)
b.StartTimer()
benchmarkEnqueue(b, queue, size)
}
func BenchmarkArrayQueueEnqueue1000(b *testing.B) {
b.StopTimer()
size := 1000
queue := New(3)
for n := 0; n < size; n++ {
queue.Enqueue(n)
}
b.StartTimer()
benchmarkEnqueue(b, queue, size)
}
func BenchmarkArrayQueueEnqueue10000(b *testing.B) {
b.StopTimer()
size := 10000
queue := New(3)
for n := 0; n < size; n++ {
queue.Enqueue(n)
}
b.StartTimer()
benchmarkEnqueue(b, queue, size)
}
func BenchmarkArrayQueueEnqueue100000(b *testing.B) {
b.StopTimer()
size := 100000
queue := New(3)
for n := 0; n < size; n++ {
queue.Enqueue(n)
}
b.StartTimer()
benchmarkEnqueue(b, queue, size)
}

@ -0,0 +1,112 @@
// Copyright (c) 2021, Emir Pasic. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package circularbuffer
import "github.com/emirpasic/gods/containers"
// Assert Iterator implementation
var _ containers.ReverseIteratorWithIndex = (*Iterator)(nil)
// Iterator returns a stateful iterator whose values can be fetched by an index.
type Iterator struct {
queue *Queue
index int
}
// Iterator returns a stateful iterator whose values can be fetched by an index.
func (queue *Queue) Iterator() Iterator {
return Iterator{queue: queue, index: -1}
}
// Next moves the iterator to the next element and returns true if there was a next element in the container.
// If Next() returns true, then next element's index and value can be retrieved by Index() and Value().
// If Next() was called for the first time, then it will point the iterator to the first element if it exists.
// Modifies the state of the iterator.
func (iterator *Iterator) Next() bool {
if iterator.index < iterator.queue.size {
iterator.index++
}
return iterator.queue.withinRange(iterator.index)
}
// Prev moves the iterator to the previous element and returns true if there was a previous element in the container.
// If Prev() returns true, then previous element's index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
func (iterator *Iterator) Prev() bool {
if iterator.index >= 0 {
iterator.index--
}
return iterator.queue.withinRange(iterator.index)
}
// Value returns the current element's value.
// Does not modify the state of the iterator.
func (iterator *Iterator) Value() interface{} {
index := (iterator.index + iterator.queue.start) % iterator.queue.maxSize
value := iterator.queue.values[index]
return value
}
// Index returns the current element's index.
// Does not modify the state of the iterator.
func (iterator *Iterator) Index() int {
return iterator.index
}
// Begin resets the iterator to its initial state (one-before-first)
// Call Next() to fetch the first element if any.
func (iterator *Iterator) Begin() {
iterator.index = -1
}
// End moves the iterator past the last element (one-past-the-end).
// Call Prev() to fetch the last element if any.
func (iterator *Iterator) End() {
iterator.index = iterator.queue.size
}
// First moves the iterator to the first element and returns true if there was a first element in the container.
// If First() returns true, then first element's index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
func (iterator *Iterator) First() bool {
iterator.Begin()
return iterator.Next()
}
// Last moves the iterator to the last element and returns true if there was a last element in the container.
// If Last() returns true, then last element's index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
func (iterator *Iterator) Last() bool {
iterator.End()
return iterator.Prev()
}
// NextTo moves the iterator to the next element from current position that satisfies the condition given by the
// passed function, and returns true if there was a next element in the container.
// If NextTo() returns true, then next element's index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
func (iterator *Iterator) NextTo(f func(index int, value interface{}) bool) bool {
for iterator.Next() {
index, value := iterator.Index(), iterator.Value()
if f(index, value) {
return true
}
}
return false
}
// PrevTo moves the iterator to the previous element from current position that satisfies the condition given by the
// passed function, and returns true if there was a next element in the container.
// If PrevTo() returns true, then next element's index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
func (iterator *Iterator) PrevTo(f func(index int, value interface{}) bool) bool {
for iterator.Prev() {
index, value := iterator.Index(), iterator.Value()
if f(index, value) {
return true
}
}
return false
}

@ -0,0 +1,41 @@
// Copyright (c) 2015, Emir Pasic. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package circularbuffer
import (
"encoding/json"
"github.com/emirpasic/gods/containers"
)
// Assert Serialization implementation
var _ containers.JSONSerializer = (*Queue)(nil)
var _ containers.JSONDeserializer = (*Queue)(nil)
// ToJSON outputs the JSON representation of queue's elements.
func (queue *Queue) ToJSON() ([]byte, error) {
return json.Marshal(queue.values[:queue.maxSize])
}
// FromJSON populates list's elements from the input JSON representation.
func (queue *Queue) FromJSON(data []byte) error {
var values []interface{}
err := json.Unmarshal(data, &values)
if err == nil {
for _, value := range values {
queue.Enqueue(value)
}
}
return err
}
// UnmarshalJSON @implements json.Unmarshaler
func (queue *Queue) UnmarshalJSON(bytes []byte) error {
return queue.FromJSON(bytes)
}
// MarshalJSON @implements json.Marshaler
func (queue *Queue) MarshalJSON() ([]byte, error) {
return queue.ToJSON()
}

@ -0,0 +1,92 @@
// Copyright (c) 2015, Emir Pasic. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package priorityqueue
import (
"github.com/emirpasic/gods/containers"
"github.com/emirpasic/gods/trees/binaryheap"
)
// Assert Iterator implementation
var _ containers.ReverseIteratorWithIndex = (*Iterator)(nil)
// Iterator returns a stateful iterator whose values can be fetched by an index.
type Iterator struct {
iterator binaryheap.Iterator
}
// Iterator returns a stateful iterator whose values can be fetched by an index.
func (queue *Queue) Iterator() Iterator {
return Iterator{iterator: queue.heap.Iterator()}
}
// Next moves the iterator to the next element and returns true if there was a next element in the container.
// If Next() returns true, then next element's index and value can be retrieved by Index() and Value().
// If Next() was called for the first time, then it will point the iterator to the first element if it exists.
// Modifies the state of the iterator.
func (iterator *Iterator) Next() bool {
return iterator.iterator.Next()
}
// Prev moves the iterator to the previous element and returns true if there was a previous element in the container.
// If Prev() returns true, then previous element's index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
func (iterator *Iterator) Prev() bool {
return iterator.iterator.Prev()
}
// Value returns the current element's value.
// Does not modify the state of the iterator.
func (iterator *Iterator) Value() interface{} {
return iterator.iterator.Value()
}
// Index returns the current element's index.
// Does not modify the state of the iterator.
func (iterator *Iterator) Index() int {
return iterator.iterator.Index()
}
// Begin resets the iterator to its initial state (one-before-first)
// Call Next() to fetch the first element if any.
func (iterator *Iterator) Begin() {
iterator.iterator.Begin()
}
// End moves the iterator past the last element (one-past-the-end).
// Call Prev() to fetch the last element if any.
func (iterator *Iterator) End() {
iterator.iterator.End()
}
// First moves the iterator to the first element and returns true if there was a first element in the container.
// If First() returns true, then first element's index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
func (iterator *Iterator) First() bool {
return iterator.iterator.First()
}
// Last moves the iterator to the last element and returns true if there was a last element in the container.
// If Last() returns true, then last element's index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
func (iterator *Iterator) Last() bool {
return iterator.iterator.Last()
}
// NextTo moves the iterator to the next element from current position that satisfies the condition given by the
// passed function, and returns true if there was a next element in the container.
// If NextTo() returns true, then next element's index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
func (iterator *Iterator) NextTo(f func(index int, value interface{}) bool) bool {
return iterator.iterator.NextTo(f)
}
// PrevTo moves the iterator to the previous element from current position that satisfies the condition given by the
// passed function, and returns true if there was a next element in the container.
// If PrevTo() returns true, then next element's index and value can be retrieved by Index() and Value().
// Modifies the state of the iterator.
func (iterator *Iterator) PrevTo(f func(index int, value interface{}) bool) bool {
return iterator.iterator.PrevTo(f)
}

@ -0,0 +1,86 @@
// Copyright (c) 2015, Emir Pasic. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package priorityqueue implements a priority queue backed by binary queue.
//
// An unbounded priority queue based on a priority queue.
// The elements of the priority queue are ordered by a comparator provided at queue construction time.
//
// The heap of this queue is the least/smallest element with respect to the specified ordering.
// If multiple elements are tied for least value, the heap is one of those elements arbitrarily.
//
// Structure is not thread safe.
//
// References: https://en.wikipedia.org/wiki/Priority_queue
package priorityqueue
import (
"fmt"
"github.com/emirpasic/gods/queues"
"github.com/emirpasic/gods/trees/binaryheap"
"github.com/emirpasic/gods/utils"
"strings"
)
// Assert Queue implementation
var _ queues.Queue = (*Queue)(nil)
// Queue holds elements in an array-list
type Queue struct {
heap *binaryheap.Heap
Comparator utils.Comparator
}
// NewWith instantiates a new empty queue with the custom comparator.
func NewWith(comparator utils.Comparator) *Queue {
return &Queue{heap: binaryheap.NewWith(comparator), Comparator: comparator}
}
// Enqueue adds a value to the end of the queue
func (queue *Queue) Enqueue(value interface{}) {
queue.heap.Push(value)
}
// Dequeue removes first element of the queue and returns it, or nil if queue is empty.
// Second return parameter is true, unless the queue was empty and there was nothing to dequeue.
func (queue *Queue) Dequeue() (value interface{}, ok bool) {
return queue.heap.Pop()
}
// Peek returns top element on the queue without removing it, or nil if queue is empty.
// Second return parameter is true, unless the queue was empty and there was nothing to peek.
func (queue *Queue) Peek() (value interface{}, ok bool) {
return queue.heap.Peek()
}
// Empty returns true if queue does not contain any elements.
func (queue *Queue) Empty() bool {
return queue.heap.Empty()
}
// Size returns number of elements within the queue.
func (queue *Queue) Size() int {
return queue.heap.Size()
}
// Clear removes all elements from the queue.
func (queue *Queue) Clear() {
queue.heap.Clear()
}
// Values returns all elements in the queue.
func (queue *Queue) Values() []interface{} {
return queue.heap.Values()
}
// String returns a string representation of container
func (queue *Queue) String() string {
str := "PriorityQueue\n"
values := make([]string, queue.heap.Size(), queue.heap.Size())
for index, value := range queue.heap.Values() {
values[index] = fmt.Sprintf("%v", value)
}
str += strings.Join(values, ", ")
return str
}

@ -0,0 +1,575 @@
// Copyright (c) 2015, Emir Pasic. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package priorityqueue
import (
"encoding/json"
"fmt"
"github.com/emirpasic/gods/utils"
"math/rand"
"strings"
"testing"
)
type Element struct {
priority int
name string
}
func (element Element) String() string {
return fmt.Sprintf("{%v %v}", element.priority, element.name)
}
// Comparator function (sort by priority value in descending order)
func byPriority(a, b interface{}) int {
return -utils.IntComparator( // Note "-" for descending order
a.(Element).priority,
b.(Element).priority,
)
}
func TestBinaryQueueEnqueue(t *testing.T) {
queue := NewWith(byPriority)
if actualValue := queue.Empty(); actualValue != true {
t.Errorf("Got %v expected %v", actualValue, true)
}
a := Element{name: "a", priority: 1}
c := Element{name: "c", priority: 3}
b := Element{name: "b", priority: 2}
queue.Enqueue(a)
queue.Enqueue(c)
queue.Enqueue(b)
it := queue.Iterator()
count := 0
for it.Next() {
count++
index := it.Index()
value := it.Value()
switch index {
case 0:
if actualValue, expectedValue := value.(Element).name, "c"; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
case 1:
if actualValue, expectedValue := value.(Element).name, "b"; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
case 2:
if actualValue, expectedValue := value.(Element).name, "a"; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
default:
t.Errorf("Too many")
}
if actualValue, expectedValue := index, count-1; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
}
if actualValue := queue.Values(); actualValue[0].(Element).name != "c" || actualValue[1].(Element).name != "b" || actualValue[2].(Element).name != "a" {
t.Errorf("Got %v expected %v", actualValue, `[{3 c} {2 b} {1 a}]`)
}
}
func TestBinaryQueueEnqueueBulk(t *testing.T) {
queue := NewWith(utils.IntComparator)
queue.Enqueue(15)
queue.Enqueue(20)
queue.Enqueue(3)
queue.Enqueue(1)
queue.Enqueue(2)
if actualValue, ok := queue.Dequeue(); actualValue != 1 || !ok {
t.Errorf("Got %v expected %v", actualValue, 1)
}
if actualValue, ok := queue.Dequeue(); actualValue != 2 || !ok {
t.Errorf("Got %v expected %v", actualValue, 2)
}
if actualValue, ok := queue.Dequeue(); actualValue != 3 || !ok {
t.Errorf("Got %v expected %v", actualValue, 3)
}
if actualValue, ok := queue.Dequeue(); actualValue != 15 || !ok {
t.Errorf("Got %v expected %v", actualValue, 15)
}
if actualValue, ok := queue.Dequeue(); actualValue != 20 || !ok {
t.Errorf("Got %v expected %v", actualValue, 20)
}
queue.Clear()
if actualValue := queue.Empty(); !actualValue {
t.Errorf("Got %v expected %v", actualValue, true)
}
}
func TestBinaryQueueDequeue(t *testing.T) {
queue := NewWith(utils.IntComparator)
if actualValue := queue.Empty(); actualValue != true {
t.Errorf("Got %v expected %v", actualValue, true)
}
queue.Enqueue(3)
queue.Enqueue(2)
queue.Enqueue(1)
queue.Dequeue() // removes 1
if actualValue, ok := queue.Dequeue(); actualValue != 2 || !ok {
t.Errorf("Got %v expected %v", actualValue, 2)
}
if actualValue, ok := queue.Dequeue(); actualValue != 3 || !ok {
t.Errorf("Got %v expected %v", actualValue, 3)
}
if actualValue, ok := queue.Dequeue(); actualValue != nil || ok {
t.Errorf("Got %v expected %v", actualValue, nil)
}
if actualValue := queue.Empty(); actualValue != true {
t.Errorf("Got %v expected %v", actualValue, true)
}
if actualValue := queue.Values(); len(actualValue) != 0 {
t.Errorf("Got %v expected %v", actualValue, "[]")
}
}
func TestBinaryQueueRandom(t *testing.T) {
queue := NewWith(utils.IntComparator)
rand.Seed(3)
for i := 0; i < 10000; i++ {
r := int(rand.Int31n(30))
queue.Enqueue(r)
}
prev, _ := queue.Dequeue()
for !queue.Empty() {
curr, _ := queue.Dequeue()
if prev.(int) > curr.(int) {
t.Errorf("Queue property invalidated. prev: %v current: %v", prev, curr)
}
prev = curr
}
}
func TestBinaryQueueIteratorOnEmpty(t *testing.T) {
queue := NewWith(utils.IntComparator)
it := queue.Iterator()
for it.Next() {
t.Errorf("Shouldn't iterate on empty queue")
}
}
func TestBinaryQueueIteratorNext(t *testing.T) {
queue := NewWith(utils.IntComparator)
queue.Enqueue(3)
queue.Enqueue(2)
queue.Enqueue(1)
it := queue.Iterator()
count := 0
for it.Next() {
count++
index := it.Index()
value := it.Value()
switch index {
case 0:
if actualValue, expectedValue := value, 1; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
case 1:
if actualValue, expectedValue := value, 2; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
case 2:
if actualValue, expectedValue := value, 3; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
default:
t.Errorf("Too many")
}
if actualValue, expectedValue := index, count-1; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
}
if actualValue, expectedValue := count, 3; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
}
func TestBinaryQueueIteratorPrev(t *testing.T) {
queue := NewWith(utils.IntComparator)
queue.Enqueue(3)
queue.Enqueue(2)
queue.Enqueue(1)
it := queue.Iterator()
for it.Next() {
}
count := 0
for it.Prev() {
count++
index := it.Index()
value := it.Value()
switch index {
case 0:
if actualValue, expectedValue := value, 1; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
case 1:
if actualValue, expectedValue := value, 2; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
case 2:
if actualValue, expectedValue := value, 3; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
default:
t.Errorf("Too many")
}
if actualValue, expectedValue := index, 3-count; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
}
if actualValue, expectedValue := count, 3; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
}
func TestBinaryQueueIteratorBegin(t *testing.T) {
queue := NewWith(utils.IntComparator)
it := queue.Iterator()
it.Begin()
queue.Enqueue(2)
queue.Enqueue(3)
queue.Enqueue(1)
for it.Next() {
}
it.Begin()
it.Next()
if index, value := it.Index(), it.Value(); index != 0 || value != 1 {
t.Errorf("Got %v,%v expected %v,%v", index, value, 0, 1)
}
}
func TestBinaryQueueIteratorEnd(t *testing.T) {
queue := NewWith(utils.IntComparator)
it := queue.Iterator()
if index := it.Index(); index != -1 {
t.Errorf("Got %v expected %v", index, -1)
}
it.End()
if index := it.Index(); index != 0 {
t.Errorf("Got %v expected %v", index, 0)
}
queue.Enqueue(3)
queue.Enqueue(2)
queue.Enqueue(1)
it.End()
if index := it.Index(); index != queue.Size() {
t.Errorf("Got %v expected %v", index, queue.Size())
}
it.Prev()
if index, value := it.Index(), it.Value(); index != queue.Size()-1 || value != 3 {
t.Errorf("Got %v,%v expected %v,%v", index, value, queue.Size()-1, 3)
}
}
func TestBinaryQueueIteratorFirst(t *testing.T) {
queue := NewWith(utils.IntComparator)
it := queue.Iterator()
if actualValue, expectedValue := it.First(), false; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
queue.Enqueue(3) // [3]
queue.Enqueue(2) // [2,3]
queue.Enqueue(1) // [1,3,2](2 swapped with 1, hence last)
if actualValue, expectedValue := it.First(), true; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
if index, value := it.Index(), it.Value(); index != 0 || value != 1 {
t.Errorf("Got %v,%v expected %v,%v", index, value, 0, 1)
}
}
func TestBinaryQueueIteratorLast(t *testing.T) {
tree := NewWith(utils.IntComparator)
it := tree.Iterator()
if actualValue, expectedValue := it.Last(), false; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
tree.Enqueue(2)
tree.Enqueue(3)
tree.Enqueue(1)
if actualValue, expectedValue := it.Last(), true; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
if index, value := it.Index(), it.Value(); index != 2 || value != 3 {
t.Errorf("Got %v,%v expected %v,%v", index, value, 2, 3)
}
}
func TestBinaryQueueIteratorNextTo(t *testing.T) {
// Sample seek function, i.e. string starting with "b"
seek := func(index int, value interface{}) bool {
return strings.HasSuffix(value.(string), "b")
}
// NextTo (empty)
{
tree := NewWith(utils.StringComparator)
it := tree.Iterator()
for it.NextTo(seek) {
t.Errorf("Shouldn't iterate on empty list")
}
}
// NextTo (not found)
{
tree := NewWith(utils.StringComparator)
tree.Enqueue("xx")
tree.Enqueue("yy")
it := tree.Iterator()
for it.NextTo(seek) {
t.Errorf("Shouldn't iterate on empty list")
}
}
// NextTo (found)
{
tree := NewWith(utils.StringComparator)
tree.Enqueue("aa")
tree.Enqueue("bb")
tree.Enqueue("cc")
it := tree.Iterator()
it.Begin()
if !it.NextTo(seek) {
t.Errorf("Shouldn't iterate on empty list")
}
if index, value := it.Index(), it.Value(); index != 1 || value.(string) != "bb" {
t.Errorf("Got %v,%v expected %v,%v", index, value, 1, "bb")
}
if !it.Next() {
t.Errorf("Should go to first element")
}
if index, value := it.Index(), it.Value(); index != 2 || value.(string) != "cc" {
t.Errorf("Got %v,%v expected %v,%v", index, value, 2, "cc")
}
if it.Next() {
t.Errorf("Should not go past last element")
}
}
}
func TestBinaryQueueIteratorPrevTo(t *testing.T) {
// Sample seek function, i.e. string starting with "b"
seek := func(index int, value interface{}) bool {
return strings.HasSuffix(value.(string), "b")
}
// PrevTo (empty)
{
tree := NewWith(utils.StringComparator)
it := tree.Iterator()
it.End()
for it.PrevTo(seek) {
t.Errorf("Shouldn't iterate on empty list")
}
}
// PrevTo (not found)
{
tree := NewWith(utils.StringComparator)
tree.Enqueue("xx")
tree.Enqueue("yy")
it := tree.Iterator()
it.End()
for it.PrevTo(seek) {
t.Errorf("Shouldn't iterate on empty list")
}
}
// PrevTo (found)
{
tree := NewWith(utils.StringComparator)
tree.Enqueue("aa")
tree.Enqueue("bb")
tree.Enqueue("cc")
it := tree.Iterator()
it.End()
if !it.PrevTo(seek) {
t.Errorf("Shouldn't iterate on empty list")
}
if index, value := it.Index(), it.Value(); index != 1 || value.(string) != "bb" {
t.Errorf("Got %v,%v expected %v,%v", index, value, 1, "bb")
}
if !it.Prev() {
t.Errorf("Should go to first element")
}
if index, value := it.Index(), it.Value(); index != 0 || value.(string) != "aa" {
t.Errorf("Got %v,%v expected %v,%v", index, value, 0, "aa")
}
if it.Prev() {
t.Errorf("Should not go before first element")
}
}
}
func TestBinaryQueueSerialization(t *testing.T) {
queue := NewWith(utils.StringComparator)
queue.Enqueue("c")
queue.Enqueue("b")
queue.Enqueue("a")
var err error
assert := func() {
if actualValue := queue.Values(); actualValue[0].(string) != "a" || actualValue[1].(string) != "b" || actualValue[2].(string) != "c" {
t.Errorf("Got %v expected %v", actualValue, "[1,3,2]")
}
if actualValue := queue.Size(); actualValue != 3 {
t.Errorf("Got %v expected %v", actualValue, 3)
}
if actualValue, ok := queue.Peek(); actualValue != "a" || !ok {
t.Errorf("Got %v expected %v", actualValue, "a")
}
if err != nil {
t.Errorf("Got error %v", err)
}
}
assert()
bytes, err := queue.ToJSON()
assert()
err = queue.FromJSON(bytes)
assert()
bytes, err = json.Marshal([]interface{}{"a", "b", "c", queue})
if err != nil {
t.Errorf("Got error %v", err)
}
err = json.Unmarshal([]byte(`[1,2,3]`), &queue)
if err != nil {
t.Errorf("Got error %v", err)
}
}
func TestBTreeString(t *testing.T) {
c := NewWith(byPriority)
c.Enqueue(1)
if !strings.HasPrefix(c.String(), "PriorityQueue") {
t.Errorf("String should start with container name")
}
}
func benchmarkEnqueue(b *testing.B, queue *Queue, size int) {
for i := 0; i < b.N; i++ {
for n := 0; n < size; n++ {
queue.Enqueue(n)
}
}
}
func benchmarkDequeue(b *testing.B, queue *Queue, size int) {
for i := 0; i < b.N; i++ {
for n := 0; n < size; n++ {
queue.Dequeue()
}
}
}
func BenchmarkBinaryQueueDequeue100(b *testing.B) {
b.StopTimer()
size := 100
queue := NewWith(byPriority)
for n := 0; n < size; n++ {
queue.Enqueue(n)
}
b.StartTimer()
benchmarkDequeue(b, queue, size)
}
func BenchmarkBinaryQueueDequeue1000(b *testing.B) {
b.StopTimer()
size := 1000
queue := NewWith(byPriority)
for n := 0; n < size; n++ {
queue.Enqueue(n)
}
b.StartTimer()
benchmarkDequeue(b, queue, size)
}
func BenchmarkBinaryQueueDequeue10000(b *testing.B) {
b.StopTimer()
size := 10000
queue := NewWith(byPriority)
for n := 0; n < size; n++ {
queue.Enqueue(n)
}
b.StartTimer()
benchmarkDequeue(b, queue, size)
}
func BenchmarkBinaryQueueDequeue100000(b *testing.B) {
b.StopTimer()
size := 100000
queue := NewWith(byPriority)
for n := 0; n < size; n++ {
queue.Enqueue(n)
}
b.StartTimer()
benchmarkDequeue(b, queue, size)
}
func BenchmarkBinaryQueueEnqueue100(b *testing.B) {
b.StopTimer()
size := 100
queue := NewWith(byPriority)
b.StartTimer()
benchmarkEnqueue(b, queue, size)
}
func BenchmarkBinaryQueueEnqueue1000(b *testing.B) {
b.StopTimer()
size := 1000
queue := NewWith(byPriority)
for n := 0; n < size; n++ {
queue.Enqueue(n)
}
b.StartTimer()
benchmarkEnqueue(b, queue, size)
}
func BenchmarkBinaryQueueEnqueue10000(b *testing.B) {
b.StopTimer()
size := 10000
queue := NewWith(byPriority)
for n := 0; n < size; n++ {
queue.Enqueue(n)
}
b.StartTimer()
benchmarkEnqueue(b, queue, size)
}
func BenchmarkBinaryQueueEnqueue100000(b *testing.B) {
b.StopTimer()
size := 100000
queue := NewWith(byPriority)
for n := 0; n < size; n++ {
queue.Enqueue(n)
}
b.StartTimer()
benchmarkEnqueue(b, queue, size)
}

@ -0,0 +1,33 @@
// Copyright (c) 2015, Emir Pasic. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package priorityqueue
import (
"github.com/emirpasic/gods/containers"
)
// Assert Serialization implementation
var _ containers.JSONSerializer = (*Queue)(nil)
var _ containers.JSONDeserializer = (*Queue)(nil)
// ToJSON outputs the JSON representation of the queue.
func (queue *Queue) ToJSON() ([]byte, error) {
return queue.heap.ToJSON()
}
// FromJSON populates the queue from the input JSON representation.
func (queue *Queue) FromJSON(data []byte) error {
return queue.heap.FromJSON(data)
}
// UnmarshalJSON @implements json.Unmarshaler
func (queue *Queue) UnmarshalJSON(bytes []byte) error {
return queue.FromJSON(bytes)
}
// MarshalJSON @implements json.Marshaler
func (queue *Queue) MarshalJSON() ([]byte, error) {
return queue.ToJSON()
}

@ -97,15 +97,19 @@ func (heap *Heap) Clear() {
// Values returns all elements in the heap.
func (heap *Heap) Values() []interface{} {
return heap.list.Values()
values := make([]interface{}, heap.list.Size(), heap.list.Size())
for it := heap.Iterator(); it.Next(); {
values[it.Index()] = it.Value()
}
return values
}
// String returns a string representation of container
func (heap *Heap) String() string {
str := "BinaryHeap\n"
values := []string{}
for _, value := range heap.list.Values() {
values = append(values, fmt.Sprintf("%v", value))
for it := heap.Iterator(); it.Next(); {
values = append(values, fmt.Sprintf("%v", it.Value()))
}
str += strings.Join(values, ", ")
return str

@ -18,11 +18,11 @@ func TestBinaryHeapPush(t *testing.T) {
t.Errorf("Got %v expected %v", actualValue, true)
}
heap.Push(3) // [3]
heap.Push(2) // [2,3]
heap.Push(1) // [1,3,2](2 swapped with 1, hence last)
heap.Push(3)
heap.Push(2)
heap.Push(1)
if actualValue := heap.Values(); actualValue[0].(int) != 1 || actualValue[1].(int) != 3 || actualValue[2].(int) != 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 := heap.Empty(); actualValue != false {
@ -56,10 +56,10 @@ func TestBinaryHeapPop(t *testing.T) {
t.Errorf("Got %v expected %v", actualValue, true)
}
heap.Push(3) // [3]
heap.Push(2) // [2,3]
heap.Push(1) // [1,3,2](2 swapped with 1, hence last)
heap.Pop() // [3,2]
heap.Push(3)
heap.Push(2)
heap.Push(1)
heap.Pop()
if actualValue, ok := heap.Peek(); actualValue != 2 || !ok {
t.Errorf("Got %v expected %v", actualValue, 2)
@ -110,9 +110,9 @@ func TestBinaryHeapIteratorOnEmpty(t *testing.T) {
func TestBinaryHeapIteratorNext(t *testing.T) {
heap := NewWithIntComparator()
heap.Push(3) // [3]
heap.Push(2) // [2,3]
heap.Push(1) // [1,3,2](2 swapped with 1, hence last)
heap.Push(3)
heap.Push(2)
heap.Push(1)
it := heap.Iterator()
count := 0
@ -126,11 +126,11 @@ func TestBinaryHeapIteratorNext(t *testing.T) {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
case 1:
if actualValue, expectedValue := value, 3; actualValue != expectedValue {
if actualValue, expectedValue := value, 2; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
case 2:
if actualValue, expectedValue := value, 2; actualValue != expectedValue {
if actualValue, expectedValue := value, 3; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
default:
@ -147,9 +147,9 @@ func TestBinaryHeapIteratorNext(t *testing.T) {
func TestBinaryHeapIteratorPrev(t *testing.T) {
heap := NewWithIntComparator()
heap.Push(3) // [3]
heap.Push(2) // [2,3]
heap.Push(1) // [1,3,2](2 swapped with 1, hence last)
heap.Push(3)
heap.Push(2)
heap.Push(1)
it := heap.Iterator()
for it.Next() {
@ -165,11 +165,11 @@ func TestBinaryHeapIteratorPrev(t *testing.T) {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
case 1:
if actualValue, expectedValue := value, 3; actualValue != expectedValue {
if actualValue, expectedValue := value, 2; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
case 2:
if actualValue, expectedValue := value, 2; actualValue != expectedValue {
if actualValue, expectedValue := value, 3; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
default:
@ -213,17 +213,17 @@ func TestBinaryHeapIteratorEnd(t *testing.T) {
t.Errorf("Got %v expected %v", index, 0)
}
heap.Push(3) // [3]
heap.Push(2) // [2,3]
heap.Push(1) // [1,3,2](2 swapped with 1, hence last)
heap.Push(3)
heap.Push(2)
heap.Push(1)
it.End()
if index := it.Index(); index != heap.Size() {
t.Errorf("Got %v expected %v", index, heap.Size())
}
it.Prev()
if index, value := it.Index(), it.Value(); index != heap.Size()-1 || value != 2 {
t.Errorf("Got %v,%v expected %v,%v", index, value, heap.Size()-1, 2)
if index, value := it.Index(), it.Value(); index != heap.Size()-1 || value != 3 {
t.Errorf("Got %v,%v expected %v,%v", index, value, heap.Size()-1, 3)
}
}
@ -233,9 +233,9 @@ func TestBinaryHeapIteratorFirst(t *testing.T) {
if actualValue, expectedValue := it.First(), false; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
heap.Push(3) // [3]
heap.Push(2) // [2,3]
heap.Push(1) // [1,3,2](2 swapped with 1, hence last)
heap.Push(3)
heap.Push(2)
heap.Push(1)
if actualValue, expectedValue := it.First(), true; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
@ -252,12 +252,12 @@ func TestBinaryHeapIteratorLast(t *testing.T) {
}
tree.Push(2)
tree.Push(3)
tree.Push(1) // [1,3,2](2 swapped with 1, hence last)
tree.Push(1)
if actualValue, expectedValue := it.Last(), true; actualValue != expectedValue {
t.Errorf("Got %v expected %v", actualValue, expectedValue)
}
if index, value := it.Index(), it.Value(); index != 2 || value != 2 {
t.Errorf("Got %v,%v expected %v,%v", index, value, 2, 2)
if index, value := it.Index(), it.Value(); index != 2 || value != 3 {
t.Errorf("Got %v,%v expected %v,%v", index, value, 2, 3)
}
}
@ -370,13 +370,13 @@ func TestBinaryHeapIteratorPrevTo(t *testing.T) {
func TestBinaryHeapSerialization(t *testing.T) {
heap := NewWithStringComparator()
heap.Push("c") // ["c"]
heap.Push("b") // ["b","c"]
heap.Push("a") // ["a","c","b"]("b" swapped with "a", hence last)
heap.Push("c")
heap.Push("b")
heap.Push("a")
var err error
assert := func() {
if actualValue := heap.Values(); actualValue[0].(string) != "a" || actualValue[1].(string) != "c" || actualValue[2].(string) != "b" {
if actualValue := heap.Values(); actualValue[0].(string) != "a" || actualValue[1].(string) != "b" || actualValue[2].(string) != "c" {
t.Errorf("Got %v expected %v", actualValue, "[1,3,2]")
}
if actualValue := heap.Size(); actualValue != 3 {

@ -4,7 +4,9 @@
package binaryheap
import "github.com/emirpasic/gods/containers"
import (
"github.com/emirpasic/gods/containers"
)
// Assert Iterator implementation
var _ containers.ReverseIteratorWithIndex = (*Iterator)(nil)
@ -44,7 +46,19 @@ func (iterator *Iterator) Prev() bool {
// Value returns the current element's value.
// Does not modify the state of the iterator.
func (iterator *Iterator) Value() interface{} {
value, _ := iterator.heap.list.Get(iterator.index)
start, end := evaluateRange(iterator.index)
if end > iterator.heap.Size() {
end = iterator.heap.Size()
}
tmpHeap := NewWith(iterator.heap.Comparator)
for n := start; n < end; n++ {
value, _ := iterator.heap.list.Get(n)
tmpHeap.Push(value)
}
for n := 0; n < iterator.index-start; n++ {
tmpHeap.Pop()
}
value, _ := tmpHeap.Pop()
return value
}
@ -109,3 +123,21 @@ func (iterator *Iterator) PrevTo(f func(index int, value interface{}) bool) bool
}
return false
}
// numOfBits counts the number of bits of an int
func numOfBits(n int) uint {
var count uint
for n != 0 {
count++
n >>= 1
}
return count
}
// evaluateRange evaluates the index range [start,end) of same level nodes in the heap as the index
func evaluateRange(index int) (start int, end int) {
bits := numOfBits(index+1) - 1
start = 1<<bits - 1
end = start + 1<<bits
return
}

Loading…
Cancel
Save