2021-11-08 21:53:15 +02:00
|
|
|
package queue
|
|
|
|
|
2021-12-15 23:35:58 +02:00
|
|
|
type Queue[T any] interface {
|
|
|
|
Enqueue(T)
|
|
|
|
Dequeue() T
|
2021-11-08 21:53:15 +02:00
|
|
|
Size() int
|
|
|
|
IsEmpty() bool
|
|
|
|
}
|
|
|
|
|
|
|
|
// We use linked list as internal data structure
|
|
|
|
// to get O(1) speed for push and pop opeartions
|
2021-12-15 23:35:58 +02:00
|
|
|
type node[Item any] struct {
|
2021-11-08 21:53:15 +02:00
|
|
|
item Item
|
2021-12-15 23:35:58 +02:00
|
|
|
next *node[Item]
|
2021-11-08 21:53:15 +02:00
|
|
|
}
|
|
|
|
|
2021-12-15 23:35:58 +02:00
|
|
|
type queue[OfType any] struct {
|
2021-11-08 21:53:15 +02:00
|
|
|
size int
|
2021-12-15 23:35:58 +02:00
|
|
|
head *node[OfType]
|
|
|
|
tail *node[OfType]
|
2021-11-08 21:53:15 +02:00
|
|
|
}
|
|
|
|
|
2021-12-15 23:35:58 +02:00
|
|
|
func NewQueue[OfType any]() Queue[OfType] {
|
|
|
|
return &queue[OfType]{}
|
2021-11-08 21:53:15 +02:00
|
|
|
}
|
|
|
|
|
2021-12-15 23:35:58 +02:00
|
|
|
func (q *queue[T]) Enqueue(item T) {
|
2021-11-08 21:53:15 +02:00
|
|
|
oldTail := q.tail
|
2021-12-15 23:35:58 +02:00
|
|
|
q.tail = &node[T]{item: item, next: nil}
|
2021-11-08 21:53:15 +02:00
|
|
|
if q.IsEmpty() {
|
|
|
|
q.head = q.tail
|
|
|
|
} else {
|
|
|
|
oldTail.next = q.tail
|
|
|
|
}
|
|
|
|
q.size++
|
|
|
|
}
|
|
|
|
|
2021-12-15 23:35:58 +02:00
|
|
|
func (q *queue[T]) Dequeue() T {
|
2021-11-08 21:53:15 +02:00
|
|
|
first := q.head
|
|
|
|
q.head = q.head.next
|
|
|
|
if q.IsEmpty() {
|
|
|
|
q.tail = nil
|
|
|
|
}
|
|
|
|
q.size--
|
|
|
|
return first.item
|
|
|
|
}
|
|
|
|
|
2021-12-15 23:35:58 +02:00
|
|
|
func (q *queue[T]) Size() int {
|
2021-11-08 21:53:15 +02:00
|
|
|
return q.size
|
|
|
|
}
|
|
|
|
|
2021-12-15 23:35:58 +02:00
|
|
|
func (q *queue[T]) IsEmpty() bool {
|
2021-11-08 21:53:15 +02:00
|
|
|
return q.head == nil
|
|
|
|
}
|