You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

125 lines
2.8 KiB
Go

// Copyright (c) 2023 Braydon Kains
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package collections
import "errors"
type LLNode[T any] struct {
Value T
Prev *LLNode[T]
Next *LLNode[T]
}
func (head *LLNode[T]) Len() int {
curr := head
n := 0
for curr != nil {
n++
curr = curr.Next
}
return n
}
func (head *LLNode[T]) Range() []T {
llLen := head.Len()
result := make([]T, llLen)
curr := head
for i := 0; i < llLen; i++ {
result[i] = curr.Value
curr = curr.Next
}
return result
}
func (head *LLNode[T]) AddToTail(val T) *LLNode[T] {
curr := head
for curr.Next != nil {
curr = curr.Next
}
node := &LLNode[T]{Value: val, Prev: curr}
curr.Next = node
return node
}
func (head *LLNode[T]) AddToHead(val T) *LLNode[T] {
node := &LLNode[T]{Value: val, Next: head}
head.Prev = node
return node
}
func (n *LLNode[T]) RemoveSelf() {
if n.Prev != nil {
n.Prev.Next = n.Next
}
if n.Next != nil {
n.Next.Prev = n.Prev
}
}
// A FIFO queue.
type Queue[T any] struct {
Head *LLNode[T]
}
func (q *Queue[T]) Enqueue(val T) {
if q.Head == nil {
q.Head = &LLNode[T]{Value: val}
} else {
q.Head.AddToTail(val)
}
}
var ErrQueueEmpty = errors.New("collections: the queue is empty")
func (q *Queue[T]) Dequeue() (T, error) {
if q.Head == nil {
return *new(T), ErrQueueEmpty
}
result := q.Head
q.Head = result.Next
return result.Value, nil
}
// A Stack, aka FILO queue.
type Stack[T any] struct {
Head *LLNode[T]
}
func (s *Stack[T]) Push(val T) {
if s.Head == nil {
s.Head = &LLNode[T]{Value: val}
} else {
node := s.Head.AddToHead(val)
s.Head = node
}
}
var ErrStackEmpty = errors.New("the stack is empty")
func (s *Stack[T]) Pop() (T, error) {
if s.Head == nil {
return *new(T), ErrStackEmpty
}
oldHead := s.Head
s.Head = s.Head.Next
oldHead.RemoveSelf()
return oldHead.Value, nil
}