commit 9f3c498f5b97eb6c966a159f7e11f7f7f2180fa2 Author: milarin Date: Fri Jan 20 21:48:46 2023 +0100 initial commit diff --git a/impl_list_array.go b/impl_list_array.go new file mode 100644 index 0000000..954e2a6 --- /dev/null +++ b/impl_list_array.go @@ -0,0 +1,58 @@ +package ds + +type ArrayList[T any] struct { + values []T +} + +var _ List[int] = &ArrayList[int]{} + +func NewArrayList[T any](initCap int) *ArrayList[T] { + return &ArrayList[T]{make([]T, 0, initCap)} +} + +func (s *ArrayList[T]) init() { + if s.values == nil { + s.values = make([]T, 0) + } +} + +func (s *ArrayList[T]) Add(value T) { + s.init() + s.values = append(s.values, value) +} + +func (s *ArrayList[T]) AddAll(values Iterable[T]) { + values.Each(s.Add) +} + +func (s *ArrayList[T]) Get(index int) T { + s.init() + return s.values[index] +} + +func (s *ArrayList[T]) RemoveAt(index int) T { + s.init() + ret := s.values[index] + s.values = append(s.values[:index], s.values[index+1:]...) + return ret +} + +func (s *ArrayList[T]) Clear() { + s.values = make([]T, 0) +} + +func (s *ArrayList[T]) Size() int { + s.init() + return len(s.values) +} + +func (s *ArrayList[T]) Empty() bool { + return s.Size() == 0 +} + +func (s *ArrayList[T]) Each(f func(value T)) { + s.init() + for _, value := range s.values { + f(value) + } +} diff --git a/impl_list_linked.go b/impl_list_linked.go new file mode 100644 index 0000000..c860aaa --- /dev/null +++ b/impl_list_linked.go @@ -0,0 +1,112 @@ +package ds + +type LinkedList[T any] struct { + head *linkedListNode[T] + tail *linkedListNode[T] + length int +} + +var _ List[int] = &LinkedList[int]{} + +func NewLinkedList[T any]() *ArrayList[T] { + return &ArrayList[T]{} +} + +func (l *LinkedList[T]) Add(value T) { + if l.length == 0 { + l.head = &linkedListNode[T]{value: value} + l.tail = l.head + l.length++ + return + } + + newNode := &linkedListNode[T]{ + value: value, + prev: l.tail, + } + l.tail.next = newNode + l.tail = newNode + l.length++ +} + +func (l *LinkedList[T]) AddAll(values Iterable[T]) { + values.Each(l.Add) +} + +func (l *LinkedList[T]) Get(index int) T { + return l.getNode(index).value +} + +func (l *LinkedList[T]) RemoveAt(index int) T { + node := l.getNode(index) + + if node.prev != nil { + node.prev.next = node.next + } else { + l.head = node.next + } + + if node.next != nil { + node.next.prev = node.prev + } else { + l.tail = node.prev + } + + l.length-- + return node.value +} + +func (l *LinkedList[T]) Clear() { + l.head = nil + l.tail = nil + l.length = 0 +} + +func (l *LinkedList[T]) Each(f func(value T)) { + node := l.head + for node != nil { + f(node.value) + node = node.next + } +} + +func (l *LinkedList[T]) Size() int { + return l.length +} + +func (l *LinkedList[T]) Empty() bool { + return l.Size() == 0 +} + +func (l *LinkedList[T]) getNode(index int) *linkedListNode[T] { + if index == 0 { + return l.head + } + + if index == l.length-1 { + return l.tail + } + + if index > l.length/2 { + index = l.length - index + node := l.tail + for index > 0 { + node = node.prev + index-- + } + return node + } + + node := l.head + for index > 0 { + node = node.next + index-- + } + return node +} + +type linkedListNode[T any] struct { + value T + next *linkedListNode[T] + prev *linkedListNode[T] +} diff --git a/impl_queue_array.go b/impl_queue_array.go new file mode 100644 index 0000000..de1a399 --- /dev/null +++ b/impl_queue_array.go @@ -0,0 +1,8 @@ +package ds + +type ArrayQueue[T any] ListQueue[T] + +func NewArrayQueue[T any]() *ArrayQueue[T] { + stack := NewListQueue[T](new(ArrayList[T])) + return (*ArrayQueue[T])(stack) +} diff --git a/impl_queue_linked_list.go b/impl_queue_linked_list.go new file mode 100644 index 0000000..e500260 --- /dev/null +++ b/impl_queue_linked_list.go @@ -0,0 +1,8 @@ +package ds + +type LinkedListQueue[T any] ListQueue[T] + +func NewLinkedListQueue[T any]() *LinkedListQueue[T] { + stack := NewListQueue[T](new(LinkedList[T])) + return (*LinkedListQueue[T])(stack) +} diff --git a/impl_queue_list.go b/impl_queue_list.go new file mode 100644 index 0000000..2b181d8 --- /dev/null +++ b/impl_queue_list.go @@ -0,0 +1,43 @@ +package ds + +type ListQueue[T any] struct { + list List[T] +} + +var _ Queue[int] = &ListQueue[int]{} + +func NewListQueue[T any](list List[T]) *ListQueue[T] { + return &ListQueue[T]{list} +} + +func (s *ListQueue[T]) Enqueue(value T) { + s.list.Add(value) +} + +func (s *ListQueue[T]) Add(value T) { + s.Enqueue(value) +} + +func (s *ListQueue[T]) AddAll(values Iterable[T]) { + values.Each(s.Add) +} + +func (s *ListQueue[T]) Dequeue() T { + return s.list.RemoveAt(0) +} + +func (s *ListQueue[T]) Peek() T { + return s.PeekAt(0) +} + +func (s *ListQueue[T]) PeekAt(index int) T { + return s.list.Get(index) +} + +func (s *ListQueue[T]) Size() int { + return s.list.Size() +} + +func (s *ListQueue[T]) Empty() bool { + return s.Size() == 0 +} diff --git a/impl_set.go b/impl_set.go new file mode 100644 index 0000000..34d433e --- /dev/null +++ b/impl_set.go @@ -0,0 +1,61 @@ +package ds + +type Set[T comparable] struct { + values map[T]struct{} +} + +var _ Coll[int] = &Set[int]{} + +func NewSet[T comparable]() *Set[T] { + return &Set[T]{} +} + +func (s *Set[T]) init() { + if s.values == nil { + s.values = map[T]struct{}{} + } +} + +func (s *Set[T]) Add(value T) { + s.init() + s.values[value] = struct{}{} +} + +func (s *Set[T]) AddAll(values Iterable[T]) { + s.init() + values.Each(s.Add) +} + +func (s *Set[T]) Remove(value T) { + s.init() + delete(s.values, value) +} + +func (s *Set[T]) RemoveAll(values Iterable[T]) { + values.Each(s.Remove) +} + +func (s *Set[T]) Clear() { + s.values = map[T]struct{}{} +} + +func (s *Set[T]) Has(value T) bool { + s.init() + _, ok := s.values[value] + return ok +} + +func (s *Set[T]) Size() int { + s.init() + return len(s.values) +} + +func (s *Set[T]) Empty() bool { + return s.Size() == 0 +} + +func (s *Set[T]) Each(f func(value T)) { + for value := range s.values { + f(value) + } +} diff --git a/impl_stack_array.go b/impl_stack_array.go new file mode 100644 index 0000000..13fbd2a --- /dev/null +++ b/impl_stack_array.go @@ -0,0 +1,8 @@ +package ds + +type ArrayStack[T any] ListStack[T] + +func NewArrayStack[T any]() *ArrayStack[T] { + stack := NewListStack[T](new(ArrayList[T])) + return (*ArrayStack[T])(stack) +} diff --git a/impl_stack_linked_list.go b/impl_stack_linked_list.go new file mode 100644 index 0000000..46698a9 --- /dev/null +++ b/impl_stack_linked_list.go @@ -0,0 +1,8 @@ +package ds + +type LinkedListStack[T any] ListStack[T] + +func NewLinkedListStack[T any]() *ArrayStack[T] { + stack := NewListStack[T](new(LinkedList[T])) + return (*ArrayStack[T])(stack) +} diff --git a/impl_stack_list.go b/impl_stack_list.go new file mode 100644 index 0000000..9a59f4b --- /dev/null +++ b/impl_stack_list.go @@ -0,0 +1,43 @@ +package ds + +type ListStack[T any] struct { + list List[T] +} + +var _ Stack[int] = &ListStack[int]{} + +func NewListStack[T any](list List[T]) *ListStack[T] { + return &ListStack[T]{list} +} + +func (s *ListStack[T]) Push(value T) { + s.list.Add(value) +} + +func (s *ListStack[T]) Add(value T) { + s.Push(value) +} + +func (s *ListStack[T]) AddAll(values Iterable[T]) { + values.Each(s.Add) +} + +func (s *ListStack[T]) Pop() T { + return s.list.RemoveAt(s.list.Size() - 1) +} + +func (s *ListStack[T]) Peek() T { + return s.PeekAt(s.Size() - 1) +} + +func (s *ListStack[T]) PeekAt(index int) T { + return s.list.Get(index) +} + +func (s *ListStack[T]) Size() int { + return s.list.Size() +} + +func (s *ListStack[T]) Empty() bool { + return s.Size() == 0 +} diff --git a/int_coll.go b/int_coll.go new file mode 100644 index 0000000..9b096f7 --- /dev/null +++ b/int_coll.go @@ -0,0 +1,8 @@ +package ds + +type Coll[T any] interface { + Addable[T] + Iterable[T] + Sized + Clearable +} diff --git a/int_list.go b/int_list.go new file mode 100644 index 0000000..ce3c8bc --- /dev/null +++ b/int_list.go @@ -0,0 +1,7 @@ +package ds + +type List[T any] interface { + Coll[T] + Indexable[int, T] + IndexedRemovable[int, T] +} diff --git a/int_map.go b/int_map.go new file mode 100644 index 0000000..0ffdd02 --- /dev/null +++ b/int_map.go @@ -0,0 +1 @@ +// TODO \ No newline at end of file diff --git a/int_queue.go b/int_queue.go new file mode 100644 index 0000000..921e02a --- /dev/null +++ b/int_queue.go @@ -0,0 +1,12 @@ +package ds + +type Queue[T any] interface { + Addable[T] + Sized + + Enqueue(value T) + Dequeue() T + + Peek() T + PeekAt(index int) T +} diff --git a/int_stack.go b/int_stack.go new file mode 100644 index 0000000..86afb80 --- /dev/null +++ b/int_stack.go @@ -0,0 +1,12 @@ +package ds + +type Stack[T any] interface { + Addable[T] + Sized + + Push(value T) + Pop() T + + Peek() T + PeekAt(index int) T +} diff --git a/int_tree.go b/int_tree.go new file mode 100644 index 0000000..0ffdd02 --- /dev/null +++ b/int_tree.go @@ -0,0 +1 @@ +// TODO \ No newline at end of file diff --git a/interfaces.go b/interfaces.go new file mode 100644 index 0000000..d959027 --- /dev/null +++ b/interfaces.go @@ -0,0 +1,36 @@ +package ds + +type Addable[T any] interface { + Add(value T) + AddAll(values Iterable[T]) +} + +type Retrievable[T comparable] interface { + Has(value T) bool +} + +type Indexable[K comparable, T any] interface { + Get(index K) T +} + +type IndexedRemovable[K comparable, T any] interface { + RemoveAt(index K) T +} + +type ComparingRemovable[T any] interface { + Remove(value T) + RemoveAll(values Iterable[T]) +} + +type Clearable interface { + Clear() +} + +type Sized interface { + Size() int + Empty() bool +} + +type Iterable[T any] interface { + Each(f func(value T)) +}