forked from zyedidia/generic
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'nchengyeeshen-fifo-queue'
- Loading branch information
Showing
4 changed files
with
356 additions
and
0 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,86 @@ | ||
<!-- Code generated by gomarkdoc. DO NOT EDIT --> | ||
|
||
# queue | ||
|
||
```go | ||
import "github.com/zyedidia/generic/queue" | ||
``` | ||
|
||
Package queue provides an implementation of a First In First Out \(FIFO\) queue\. The FIFO queue is implemented using a doubly\-linked list found in the 'list' package\. | ||
|
||
## Index | ||
|
||
- [type FIFOQueue](<#type-fifoqueue>) | ||
- [func New[T any]() *FIFOQueue[T]](<#func-new>) | ||
- [func (q *FIFOQueue[T]) Dequeue() T](<#func-badrecv-dequeue>) | ||
- [func (q *FIFOQueue[T]) Empty() bool](<#func-badrecv-empty>) | ||
- [func (q *FIFOQueue[T]) Enqueue(value T)](<#func-badrecv-enqueue>) | ||
- [func (q *FIFOQueue[T]) Iter() iter.Iter[T]](<#func-badrecv-iter>) | ||
- [func (q *FIFOQueue[T]) Peek() T](<#func-badrecv-peek>) | ||
|
||
|
||
## type [FIFOQueue](<https://github.com/nchengyeeshen/generic/blob/master/queue/fifo_queue.go#L12-L14>) | ||
|
||
FIFOQueue is a simple First In First Out \(FIFO\) queue\. | ||
|
||
```go | ||
type FIFOQueue[T any] struct { | ||
// contains filtered or unexported fields | ||
} | ||
``` | ||
|
||
### func [New](<https://github.com/nchengyeeshen/generic/blob/master/queue/fifo_queue.go#L17>) | ||
|
||
```go | ||
func New[T any]() *FIFOQueue[T] | ||
``` | ||
|
||
New returns an empty First In First Out \(FIFO\) queue\. | ||
|
||
### func \(\*BADRECV\) [Dequeue](<https://github.com/nchengyeeshen/generic/blob/master/queue/fifo_queue.go#L31>) | ||
|
||
```go | ||
func (q *FIFOQueue[T]) Dequeue() T | ||
``` | ||
|
||
Dequeue removes and returns the item at the front of the queue\. | ||
|
||
A panic occurs if the queue is Empty\. | ||
|
||
### func \(\*BADRECV\) [Empty](<https://github.com/nchengyeeshen/generic/blob/master/queue/fifo_queue.go#L46>) | ||
|
||
```go | ||
func (q *FIFOQueue[T]) Empty() bool | ||
``` | ||
|
||
Empty returns true if the queue is empty\. | ||
|
||
### func \(\*BADRECV\) [Enqueue](<https://github.com/nchengyeeshen/generic/blob/master/queue/fifo_queue.go#L24>) | ||
|
||
```go | ||
func (q *FIFOQueue[T]) Enqueue(value T) | ||
``` | ||
|
||
Enqueue inserts 'value' to the end of the queue\. | ||
|
||
### func \(\*BADRECV\) [Iter](<https://github.com/nchengyeeshen/generic/blob/master/queue/fifo_queue.go#L52>) | ||
|
||
```go | ||
func (q *FIFOQueue[T]) Iter() iter.Iter[T] | ||
``` | ||
|
||
Iter returns a forward iterator\, returning items starting from the front to the back of the queue\. | ||
|
||
### func \(\*BADRECV\) [Peek](<https://github.com/nchengyeeshen/generic/blob/master/queue/fifo_queue.go#L41>) | ||
|
||
```go | ||
func (q *FIFOQueue[T]) Peek() T | ||
``` | ||
|
||
Peek returns the item at the front of the queue without removing it\. | ||
|
||
A panic occurs if the queue is Empty\. | ||
|
||
|
||
|
||
Generated by [gomarkdoc](<https://github.com/princjef/gomarkdoc>) |
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,54 @@ | ||
// Package queue provides an implementation of a First In First Out (FIFO) | ||
// queue. The FIFO queue is implemented using the doubly-linked list from the | ||
// 'list' package. | ||
package queue | ||
|
||
import ( | ||
"github.com/zyedidia/generic/iter" | ||
"github.com/zyedidia/generic/list" | ||
) | ||
|
||
// Queue is a simple First In First Out (FIFO) queue. | ||
type Queue[T any] struct { | ||
list *list.List[T] | ||
} | ||
|
||
// New returns an empty First In First Out (FIFO) queue. | ||
func New[T any]() *Queue[T] { | ||
return &Queue[T]{ | ||
list: list.New[T](), | ||
} | ||
} | ||
|
||
// Enqueue inserts 'value' to the end of the queue. | ||
func (q *Queue[T]) Enqueue(value T) { | ||
q.list.PushBack(value) | ||
} | ||
|
||
// Dequeue removes and returns the item at the front of the queue. | ||
// | ||
// A panic occurs if the queue is Empty. | ||
func (q *Queue[T]) Dequeue() T { | ||
value := q.list.Front.Value | ||
q.list.Remove(q.list.Front) | ||
|
||
return value | ||
} | ||
|
||
// Peek returns the item at the front of the queue without removing it. | ||
// | ||
// A panic occurs if the queue is Empty. | ||
func (q *Queue[T]) Peek() T { | ||
return q.list.Front.Value | ||
} | ||
|
||
// Empty returns true if the queue is empty. | ||
func (q *Queue[T]) Empty() bool { | ||
return q.list.Front == nil | ||
} | ||
|
||
// Iter returns a forward iterator, returning items starting from the front to | ||
// the back of the queue. | ||
func (q *Queue[T]) Iter() iter.Iter[T] { | ||
return q.list.Front.Iter() | ||
} |
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,215 @@ | ||
package queue | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/zyedidia/generic/list" | ||
) | ||
|
||
func TestQueueEmpty(t *testing.T) { | ||
cases := []struct { | ||
name string | ||
queue *Queue[int] | ||
want bool | ||
}{ | ||
{ | ||
name: "empty queue", | ||
queue: emptyQueue(), | ||
want: true, | ||
}, | ||
{ | ||
name: "non-empty queue", | ||
queue: nonEmptyQueue(), | ||
want: false, | ||
}, | ||
} | ||
|
||
for _, c := range cases { | ||
t.Run(c.name, func(t *testing.T) { | ||
got := c.queue.Empty() | ||
|
||
if got != c.want { | ||
t.Errorf("got %v, want %v", got, c.want) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func TestQueuePeek(t *testing.T) { | ||
t.Run("panics on empty queue", func(t *testing.T) { | ||
defer func() { | ||
if err := recover(); err == nil { | ||
t.Error("peeking on empty queue did not panic") | ||
} | ||
}() | ||
|
||
emptyQueue().Peek() | ||
}) | ||
|
||
t.Run("non-empty queue", func(t *testing.T) { | ||
got := nonEmptyQueue().Peek() | ||
want := 1 | ||
|
||
if got != want { | ||
t.Errorf("got %v, want %v", got, want) | ||
} | ||
}) | ||
} | ||
|
||
func TestQueueEnqueue(t *testing.T) { | ||
t.Run("empty queue", func(t *testing.T) { | ||
q := emptyQueue() | ||
|
||
q.Enqueue(1) | ||
|
||
if q.list.Front == nil { | ||
t.Error("front is nil") | ||
} | ||
|
||
if q.list.Front.Value != 1 { | ||
t.Errorf("got %v, want %v for front value", q.list.Front.Value, 1) | ||
} | ||
|
||
if q.list.Back == nil { | ||
t.Error("back is nil") | ||
} | ||
|
||
if q.list.Front != q.list.Back { | ||
t.Error(("front and back are not the same")) | ||
} | ||
}) | ||
|
||
t.Run("non-empty queue", func(t *testing.T) { | ||
q := nonEmptyQueue() | ||
|
||
q.Enqueue(3) | ||
|
||
if q.list.Front.Value != 1 { | ||
t.Errorf("got %v, want %v for front value", q.list.Front.Value, 1) | ||
} | ||
|
||
if q.list.Back == nil { | ||
t.Error("back is nil") | ||
} | ||
|
||
if q.list.Back.Value != 3 { | ||
t.Errorf("got %v, want %v for back value", q.list.Back.Value, 3) | ||
} | ||
}) | ||
} | ||
|
||
func TestQueueDequeue(t *testing.T) { | ||
t.Run("panics on empty queue", func(t *testing.T) { | ||
defer func() { | ||
if err := recover(); err == nil { | ||
t.Error("dequeue on empty queue did not panic") | ||
} | ||
}() | ||
|
||
emptyQueue().Dequeue() | ||
}) | ||
|
||
t.Run("non-empty queue", func(t *testing.T) { | ||
q := nonEmptyQueue() | ||
|
||
// Non-empty after dequeue | ||
got := q.Dequeue() | ||
|
||
if got != 1 { | ||
t.Errorf("got %v, want %v", got, 1) | ||
} | ||
|
||
if q.list.Front.Value == 1 { | ||
t.Error("front of queue is still 1 after dequeue") | ||
} | ||
|
||
if q.Empty() { | ||
t.Error("queue is empty") | ||
} | ||
|
||
// Empty after dequeue | ||
got = q.Dequeue() | ||
|
||
if got != 2 { | ||
t.Errorf("got %v, want %v", got, 2) | ||
} | ||
|
||
if !q.Empty() { | ||
t.Error("queue is not empty") | ||
} | ||
}) | ||
} | ||
|
||
func TestQueueIter(t *testing.T) { | ||
q := nonEmptyQueue() | ||
|
||
i := 1 | ||
q.Iter().For(func(item int) { | ||
if item != i { | ||
t.Errorf("got %v, want %v", item, i) | ||
} | ||
i++ | ||
}) | ||
} | ||
|
||
func ExampleQueue_Enqueue() { | ||
q := New[int]() | ||
q.Enqueue(1) | ||
} | ||
|
||
func ExampleQueue_Peek() { | ||
q := New[int]() | ||
q.Enqueue(1) | ||
|
||
fmt.Println(q.Peek()) | ||
// Output: 1 | ||
} | ||
|
||
func ExampleQueue_Dequeue() { | ||
q := New[int]() | ||
q.Enqueue(1) | ||
|
||
fmt.Println(q.Dequeue()) | ||
// Output: 1 | ||
} | ||
|
||
func ExampleQueue_Iter() { | ||
q := New[int]() | ||
q.Enqueue(1) | ||
q.Enqueue(2) | ||
|
||
q.Iter().For(func(i int) { | ||
fmt.Println(i) | ||
}) | ||
// Output: | ||
// 1 | ||
// 2 | ||
} | ||
|
||
func ExampleQueue_Empty_empty() { | ||
q := New[int]() | ||
|
||
fmt.Println(q.Empty()) | ||
// Output: true | ||
} | ||
|
||
func ExampleQueue_Empty_nonempty() { | ||
q := New[int]() | ||
q.Enqueue(1) | ||
|
||
fmt.Println(q.Empty()) | ||
// Output: false | ||
} | ||
|
||
func emptyQueue() *Queue[int] { | ||
return New[int]() | ||
} | ||
|
||
func nonEmptyQueue() *Queue[int] { | ||
q := New[int]() | ||
q.list.Front = &list.Node[int]{Value: 1} | ||
q.list.Front.Next = &list.Node[int]{Value: 2, Prev: q.list.Front} | ||
q.list.Back = q.list.Front.Next | ||
return q | ||
} |