-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #203 from emirpasic/development
Implements PriorityQueue and CircularBuffer
- Loading branch information
Showing
14 changed files
with
1,972 additions
and
59 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
} |
Oops, something went wrong.