finished slice stuff, started queues
parent
21e82bb2b5
commit
337e85e173
@ -0,0 +1,8 @@
|
||||
.PHONY: install_tools
|
||||
install_tools:
|
||||
go install github.com/google/addlicense@latest
|
||||
go install github.com/jordanlewis/gcassert/cmd/gcassert@latest
|
||||
|
||||
.PHONY: addlicense
|
||||
addlicense:
|
||||
addlicense -c "Braydon Kains" -l mit .
|
@ -1,5 +1,5 @@
|
||||
# collections-go
|
||||
|
||||
A dependency-free package of generic Go collection data structures. Compatible with Go 1.18 and above. Strives for the most optimal solutions available with lowest number of allocations.
|
||||
A dependency-free package of generic Go collection data structures. Compatible with Go 1.18 and above. Strives for the most optimal solutions available with lowest number of heap allocations.
|
||||
|
||||
Contributions are not currently open as this project is in active early development.
|
||||
|
@ -1,9 +0,0 @@
|
||||
package collections
|
||||
|
||||
// A UnaryPredicate is a function that takes a single element of type
|
||||
// T and returns a boolean.
|
||||
type UnaryPredicate[T any] func(T) bool
|
||||
|
||||
// A UnaryOperator is a function that takes a single element of type
|
||||
// T and returns an element of type T.
|
||||
type UnaryOperator[T any] func(T) T
|
@ -0,0 +1,124 @@
|
||||
// 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]) AddToEnd(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]) AddToStart(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.AddToEnd(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.AddToStart(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
|
||||
}
|
Loading…
Reference in New Issue