2023-08-18 15:13:53 +00:00
|
|
|
package containers
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
|
|
|
"errors"
|
|
|
|
)
|
|
|
|
|
|
|
|
type Queue[T any] struct {
|
|
|
|
head *ChainElem[T]
|
|
|
|
tail *ChainElem[T]
|
|
|
|
}
|
|
|
|
|
|
|
|
// isValid checks if the queue is still valid.
|
|
|
|
func (q *Queue[T]) isValid() bool {
|
|
|
|
return q.head != nil &&
|
|
|
|
q.tail != nil &&
|
|
|
|
reachable(q.head, q.tail)
|
|
|
|
}
|
|
|
|
|
|
|
|
// IsEmpty checks if the queue is empty.
|
|
|
|
func (q *Queue[T]) IsEmpty() bool {
|
|
|
|
return q.head == q.tail
|
|
|
|
}
|
|
|
|
|
|
|
|
// Push adds a new element to the end of the queue.
|
|
|
|
func (q *Queue[T]) Push(elem *T) error {
|
|
|
|
if !q.isValid() {
|
|
|
|
return errors.New("invalid queue")
|
|
|
|
}
|
|
|
|
|
|
|
|
e := emptyElem[T]()
|
|
|
|
q.tail.Elem = elem
|
|
|
|
q.tail.Next = e
|
|
|
|
q.tail = e
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Pop removes the first element of the queue.
|
|
|
|
// It errors out if there is no element or the queue is invalid.
|
|
|
|
func (q *Queue[T]) Pop() (*T, error) {
|
|
|
|
if !q.isValid() {
|
|
|
|
return nil, errors.New("invalid queue")
|
|
|
|
}
|
|
|
|
if q.IsEmpty() {
|
|
|
|
return nil, errors.New("empty queue")
|
|
|
|
}
|
|
|
|
Elem := q.head.Elem
|
|
|
|
q.head = q.head.Next
|
|
|
|
return Elem, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// Top returns the first element of the queue without removing it.
|
|
|
|
// It errors out if there is no element or the queue is invalid.
|
|
|
|
func (q *Queue[T]) Top() (*T, error) {
|
|
|
|
if !q.isValid() {
|
|
|
|
return nil, errors.New("queue invalid")
|
|
|
|
}
|
|
|
|
if q.IsEmpty() {
|
|
|
|
return nil, errors.New("queue empty")
|
|
|
|
}
|
|
|
|
return q.head.Elem, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// HeadElem returns the first ChainElem of the queue without removing it.
|
|
|
|
// It errors out if there is no element or the queue is invalid.
|
|
|
|
func (q *Queue[T]) HeadElem() (*ChainElem[T], error) {
|
|
|
|
if !q.isValid() {
|
|
|
|
return nil, errors.New("queue invalid")
|
|
|
|
}
|
|
|
|
if q.IsEmpty() {
|
|
|
|
return nil, errors.New("queue empty")
|
|
|
|
}
|
|
|
|
return q.head, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// MarshalJSON is used for generating json data when using json.Marshal.
|
|
|
|
func (q *Queue[T]) MarshalJSON() ([]byte, error) {
|
|
|
|
if !q.isValid() {
|
|
|
|
return nil, errors.New("queue invalid")
|
|
|
|
}
|
|
|
|
if q.IsEmpty() {
|
|
|
|
return nil, errors.New("queue empty")
|
|
|
|
}
|
|
|
|
|
|
|
|
return json.Marshal(q.head)
|
|
|
|
}
|
|
|
|
|
|
|
|
func BuildQueue[T any]() *Queue[T] {
|
|
|
|
empty := emptyElem[T]()
|
|
|
|
return &Queue[T]{
|
|
|
|
head: empty,
|
|
|
|
tail: empty,
|
|
|
|
}
|
|
|
|
}
|