Change queues and stacks

- Make chain element private
- Remove JSON Marshaller from stack and queue
- Remove access to top chain element
This commit is contained in:
Melody Becker 2025-04-24 15:52:43 +02:00
parent 9870d87d41
commit 09de0a19e1
Signed by: mstar
SSH key fingerprint: SHA256:9VAo09aaVNTWKzPW7Hq2LW+ox9OdwmTSHRoD4mlz1yI
3 changed files with 18 additions and 52 deletions

View file

@ -1,15 +1,15 @@
package containers package containers
type ChainElem[T any] struct { type chainElem[T any] struct {
Elem *T Elem *T
Next *ChainElem[T] Next *chainElem[T]
} }
// reachable checks if you can reach elem l when starting from elem f. // reachable checks if you can reach elem l when starting from elem f.
// It detects loops and returns false if it runs into one. // It detects loops and returns false if it runs into one.
func reachable[T any](f, l *ChainElem[T]) bool { func reachable[T any](f, l *chainElem[T]) bool {
// Map to keep track of nodes already visited // Map to keep track of nodes already visited
checks := make(map[*ChainElem[T]]bool) checks := make(map[*chainElem[T]]bool)
for w := f; w != l; w = w.Next { for w := f; w != l; w = w.Next {
if w == nil { if w == nil {
return false return false
@ -26,8 +26,8 @@ func reachable[T any](f, l *ChainElem[T]) bool {
} }
// emptyElem creates a new ChainElem[T] with empty values. // emptyElem creates a new ChainElem[T] with empty values.
func emptyElem[T any]() *ChainElem[T] { func emptyElem[T any]() *chainElem[T] {
return &ChainElem[T]{ return &chainElem[T]{
Elem: nil, Elem: nil,
Next: nil, Next: nil,
} }

View file

@ -1,13 +1,15 @@
package containers package containers
import ( import (
"encoding/json"
"errors" "errors"
) )
var ErrInvalidQueue = errors.New("invalid queue")
var ErrEmptyQueue = errors.New("empty queue")
type Queue[T any] struct { type Queue[T any] struct {
head *ChainElem[T] head *chainElem[T]
tail *ChainElem[T] tail *chainElem[T]
} }
// isValid checks if the queue is still valid. // isValid checks if the queue is still valid.
@ -25,7 +27,7 @@ func (q *Queue[T]) IsEmpty() bool {
// Push adds a new element to the end of the queue. // Push adds a new element to the end of the queue.
func (q *Queue[T]) Push(elem *T) error { func (q *Queue[T]) Push(elem *T) error {
if !q.isValid() { if !q.isValid() {
return errors.New("invalid queue") return ErrInvalidQueue
} }
e := emptyElem[T]() e := emptyElem[T]()
@ -40,10 +42,10 @@ func (q *Queue[T]) Push(elem *T) error {
// It errors out if there is no element or the queue is invalid. // It errors out if there is no element or the queue is invalid.
func (q *Queue[T]) Pop() (*T, error) { func (q *Queue[T]) Pop() (*T, error) {
if !q.isValid() { if !q.isValid() {
return nil, errors.New("invalid queue") return nil, ErrInvalidQueue
} }
if q.IsEmpty() { if q.IsEmpty() {
return nil, errors.New("empty queue") return nil, ErrEmptyQueue
} }
Elem := q.head.Elem Elem := q.head.Elem
q.head = q.head.Next q.head = q.head.Next
@ -54,38 +56,14 @@ func (q *Queue[T]) Pop() (*T, error) {
// It errors out if there is no element or the queue is invalid. // It errors out if there is no element or the queue is invalid.
func (q *Queue[T]) Top() (*T, error) { func (q *Queue[T]) Top() (*T, error) {
if !q.isValid() { if !q.isValid() {
return nil, errors.New("queue invalid") return nil, ErrInvalidQueue
} }
if q.IsEmpty() { if q.IsEmpty() {
return nil, errors.New("queue empty") return nil, ErrEmptyQueue
} }
return q.head.Elem, nil 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] { func BuildQueue[T any]() *Queue[T] {
empty := emptyElem[T]() empty := emptyElem[T]()
return &Queue[T]{ return &Queue[T]{

View file

@ -1,13 +1,12 @@
package containers package containers
import ( import (
"encoding/json"
"errors" "errors"
) )
type Stack[T any] struct { type Stack[T any] struct {
top *ChainElem[T] top *chainElem[T]
bottom *ChainElem[T] bottom *chainElem[T]
} }
// isValid checks if the stack is valid. // isValid checks if the stack is valid.
@ -61,17 +60,6 @@ func (s *Stack[T]) Top() (*T, error) {
return s.top.Elem, nil return s.top.Elem, nil
} }
// MarshalJSON is used by json.Marshal to create a json representation.
func (s *Stack[T]) MarshalJSON() ([]byte, error) {
if !s.isValid() {
return nil, errors.New("queue invalid")
}
if s.IsEmpty() {
return nil, errors.New("queue empty")
}
return json.Marshal(s.top)
}
func BuildStack[T any]() *Stack[T] { func BuildStack[T any]() *Stack[T] {
empty := emptyElem[T]() empty := emptyElem[T]()
return &Stack[T]{ return &Stack[T]{