Skip to content

Commit dddf9df

Browse files
committed
Merge branch 'nchengyeeshen-fifo-queue'
2 parents 13c2e08 + bbe2e03 commit dddf9df

File tree

4 files changed

+356
-0
lines changed

4 files changed

+356
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ information about each data structure.
2424
for arrays of bytes, but this rope is generic.
2525
* [`stack`](./stack): a LIFO stack.
2626
* [`trie`](./trie): a ternary search trie.
27+
* [`queue`](./queue): a First In First Out (FIFO) queue.
2728

2829
The package also includes support for iterators, in the `iter` subpackage.
2930
Most data structures provide an iterator API, which can be used with some

queue/README.md

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
<!-- Code generated by gomarkdoc. DO NOT EDIT -->
2+
3+
# queue
4+
5+
```go
6+
import "github.com/zyedidia/generic/queue"
7+
```
8+
9+
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\.
10+
11+
## Index
12+
13+
- [type FIFOQueue](<#type-fifoqueue>)
14+
- [func New[T any]() *FIFOQueue[T]](<#func-new>)
15+
- [func (q *FIFOQueue[T]) Dequeue() T](<#func-badrecv-dequeue>)
16+
- [func (q *FIFOQueue[T]) Empty() bool](<#func-badrecv-empty>)
17+
- [func (q *FIFOQueue[T]) Enqueue(value T)](<#func-badrecv-enqueue>)
18+
- [func (q *FIFOQueue[T]) Iter() iter.Iter[T]](<#func-badrecv-iter>)
19+
- [func (q *FIFOQueue[T]) Peek() T](<#func-badrecv-peek>)
20+
21+
22+
## type [FIFOQueue](<https://github.com/nchengyeeshen/generic/blob/master/queue/fifo_queue.go#L12-L14>)
23+
24+
FIFOQueue is a simple First In First Out \(FIFO\) queue\.
25+
26+
```go
27+
type FIFOQueue[T any] struct {
28+
// contains filtered or unexported fields
29+
}
30+
```
31+
32+
### func [New](<https://github.com/nchengyeeshen/generic/blob/master/queue/fifo_queue.go#L17>)
33+
34+
```go
35+
func New[T any]() *FIFOQueue[T]
36+
```
37+
38+
New returns an empty First In First Out \(FIFO\) queue\.
39+
40+
### func \(\*BADRECV\) [Dequeue](<https://github.com/nchengyeeshen/generic/blob/master/queue/fifo_queue.go#L31>)
41+
42+
```go
43+
func (q *FIFOQueue[T]) Dequeue() T
44+
```
45+
46+
Dequeue removes and returns the item at the front of the queue\.
47+
48+
A panic occurs if the queue is Empty\.
49+
50+
### func \(\*BADRECV\) [Empty](<https://github.com/nchengyeeshen/generic/blob/master/queue/fifo_queue.go#L46>)
51+
52+
```go
53+
func (q *FIFOQueue[T]) Empty() bool
54+
```
55+
56+
Empty returns true if the queue is empty\.
57+
58+
### func \(\*BADRECV\) [Enqueue](<https://github.com/nchengyeeshen/generic/blob/master/queue/fifo_queue.go#L24>)
59+
60+
```go
61+
func (q *FIFOQueue[T]) Enqueue(value T)
62+
```
63+
64+
Enqueue inserts 'value' to the end of the queue\.
65+
66+
### func \(\*BADRECV\) [Iter](<https://github.com/nchengyeeshen/generic/blob/master/queue/fifo_queue.go#L52>)
67+
68+
```go
69+
func (q *FIFOQueue[T]) Iter() iter.Iter[T]
70+
```
71+
72+
Iter returns a forward iterator\, returning items starting from the front to the back of the queue\.
73+
74+
### func \(\*BADRECV\) [Peek](<https://github.com/nchengyeeshen/generic/blob/master/queue/fifo_queue.go#L41>)
75+
76+
```go
77+
func (q *FIFOQueue[T]) Peek() T
78+
```
79+
80+
Peek returns the item at the front of the queue without removing it\.
81+
82+
A panic occurs if the queue is Empty\.
83+
84+
85+
86+
Generated by [gomarkdoc](<https://github.com/princjef/gomarkdoc>)

queue/queue.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// Package queue provides an implementation of a First In First Out (FIFO)
2+
// queue. The FIFO queue is implemented using the doubly-linked list from the
3+
// 'list' package.
4+
package queue
5+
6+
import (
7+
"github.com/zyedidia/generic/iter"
8+
"github.com/zyedidia/generic/list"
9+
)
10+
11+
// Queue is a simple First In First Out (FIFO) queue.
12+
type Queue[T any] struct {
13+
list *list.List[T]
14+
}
15+
16+
// New returns an empty First In First Out (FIFO) queue.
17+
func New[T any]() *Queue[T] {
18+
return &Queue[T]{
19+
list: list.New[T](),
20+
}
21+
}
22+
23+
// Enqueue inserts 'value' to the end of the queue.
24+
func (q *Queue[T]) Enqueue(value T) {
25+
q.list.PushBack(value)
26+
}
27+
28+
// Dequeue removes and returns the item at the front of the queue.
29+
//
30+
// A panic occurs if the queue is Empty.
31+
func (q *Queue[T]) Dequeue() T {
32+
value := q.list.Front.Value
33+
q.list.Remove(q.list.Front)
34+
35+
return value
36+
}
37+
38+
// Peek returns the item at the front of the queue without removing it.
39+
//
40+
// A panic occurs if the queue is Empty.
41+
func (q *Queue[T]) Peek() T {
42+
return q.list.Front.Value
43+
}
44+
45+
// Empty returns true if the queue is empty.
46+
func (q *Queue[T]) Empty() bool {
47+
return q.list.Front == nil
48+
}
49+
50+
// Iter returns a forward iterator, returning items starting from the front to
51+
// the back of the queue.
52+
func (q *Queue[T]) Iter() iter.Iter[T] {
53+
return q.list.Front.Iter()
54+
}

queue/queue_test.go

Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
package queue
2+
3+
import (
4+
"fmt"
5+
"testing"
6+
7+
"github.com/zyedidia/generic/list"
8+
)
9+
10+
func TestQueueEmpty(t *testing.T) {
11+
cases := []struct {
12+
name string
13+
queue *Queue[int]
14+
want bool
15+
}{
16+
{
17+
name: "empty queue",
18+
queue: emptyQueue(),
19+
want: true,
20+
},
21+
{
22+
name: "non-empty queue",
23+
queue: nonEmptyQueue(),
24+
want: false,
25+
},
26+
}
27+
28+
for _, c := range cases {
29+
t.Run(c.name, func(t *testing.T) {
30+
got := c.queue.Empty()
31+
32+
if got != c.want {
33+
t.Errorf("got %v, want %v", got, c.want)
34+
}
35+
})
36+
}
37+
}
38+
39+
func TestQueuePeek(t *testing.T) {
40+
t.Run("panics on empty queue", func(t *testing.T) {
41+
defer func() {
42+
if err := recover(); err == nil {
43+
t.Error("peeking on empty queue did not panic")
44+
}
45+
}()
46+
47+
emptyQueue().Peek()
48+
})
49+
50+
t.Run("non-empty queue", func(t *testing.T) {
51+
got := nonEmptyQueue().Peek()
52+
want := 1
53+
54+
if got != want {
55+
t.Errorf("got %v, want %v", got, want)
56+
}
57+
})
58+
}
59+
60+
func TestQueueEnqueue(t *testing.T) {
61+
t.Run("empty queue", func(t *testing.T) {
62+
q := emptyQueue()
63+
64+
q.Enqueue(1)
65+
66+
if q.list.Front == nil {
67+
t.Error("front is nil")
68+
}
69+
70+
if q.list.Front.Value != 1 {
71+
t.Errorf("got %v, want %v for front value", q.list.Front.Value, 1)
72+
}
73+
74+
if q.list.Back == nil {
75+
t.Error("back is nil")
76+
}
77+
78+
if q.list.Front != q.list.Back {
79+
t.Error(("front and back are not the same"))
80+
}
81+
})
82+
83+
t.Run("non-empty queue", func(t *testing.T) {
84+
q := nonEmptyQueue()
85+
86+
q.Enqueue(3)
87+
88+
if q.list.Front.Value != 1 {
89+
t.Errorf("got %v, want %v for front value", q.list.Front.Value, 1)
90+
}
91+
92+
if q.list.Back == nil {
93+
t.Error("back is nil")
94+
}
95+
96+
if q.list.Back.Value != 3 {
97+
t.Errorf("got %v, want %v for back value", q.list.Back.Value, 3)
98+
}
99+
})
100+
}
101+
102+
func TestQueueDequeue(t *testing.T) {
103+
t.Run("panics on empty queue", func(t *testing.T) {
104+
defer func() {
105+
if err := recover(); err == nil {
106+
t.Error("dequeue on empty queue did not panic")
107+
}
108+
}()
109+
110+
emptyQueue().Dequeue()
111+
})
112+
113+
t.Run("non-empty queue", func(t *testing.T) {
114+
q := nonEmptyQueue()
115+
116+
// Non-empty after dequeue
117+
got := q.Dequeue()
118+
119+
if got != 1 {
120+
t.Errorf("got %v, want %v", got, 1)
121+
}
122+
123+
if q.list.Front.Value == 1 {
124+
t.Error("front of queue is still 1 after dequeue")
125+
}
126+
127+
if q.Empty() {
128+
t.Error("queue is empty")
129+
}
130+
131+
// Empty after dequeue
132+
got = q.Dequeue()
133+
134+
if got != 2 {
135+
t.Errorf("got %v, want %v", got, 2)
136+
}
137+
138+
if !q.Empty() {
139+
t.Error("queue is not empty")
140+
}
141+
})
142+
}
143+
144+
func TestQueueIter(t *testing.T) {
145+
q := nonEmptyQueue()
146+
147+
i := 1
148+
q.Iter().For(func(item int) {
149+
if item != i {
150+
t.Errorf("got %v, want %v", item, i)
151+
}
152+
i++
153+
})
154+
}
155+
156+
func ExampleQueue_Enqueue() {
157+
q := New[int]()
158+
q.Enqueue(1)
159+
}
160+
161+
func ExampleQueue_Peek() {
162+
q := New[int]()
163+
q.Enqueue(1)
164+
165+
fmt.Println(q.Peek())
166+
// Output: 1
167+
}
168+
169+
func ExampleQueue_Dequeue() {
170+
q := New[int]()
171+
q.Enqueue(1)
172+
173+
fmt.Println(q.Dequeue())
174+
// Output: 1
175+
}
176+
177+
func ExampleQueue_Iter() {
178+
q := New[int]()
179+
q.Enqueue(1)
180+
q.Enqueue(2)
181+
182+
q.Iter().For(func(i int) {
183+
fmt.Println(i)
184+
})
185+
// Output:
186+
// 1
187+
// 2
188+
}
189+
190+
func ExampleQueue_Empty_empty() {
191+
q := New[int]()
192+
193+
fmt.Println(q.Empty())
194+
// Output: true
195+
}
196+
197+
func ExampleQueue_Empty_nonempty() {
198+
q := New[int]()
199+
q.Enqueue(1)
200+
201+
fmt.Println(q.Empty())
202+
// Output: false
203+
}
204+
205+
func emptyQueue() *Queue[int] {
206+
return New[int]()
207+
}
208+
209+
func nonEmptyQueue() *Queue[int] {
210+
q := New[int]()
211+
q.list.Front = &list.Node[int]{Value: 1}
212+
q.list.Front.Next = &list.Node[int]{Value: 2, Prev: q.list.Front}
213+
q.list.Back = q.list.Front.Next
214+
return q
215+
}

0 commit comments

Comments
 (0)