bag, queue

This commit is contained in:
Gregory 2021-11-08 21:53:15 +02:00
parent 6f9dc7b91b
commit a35bb36872
4 changed files with 181 additions and 0 deletions

51
fundamentals/bag/bag.go Normal file
View file

@ -0,0 +1,51 @@
package bag
// "Generic" item.
// When type parameters will land this type became
// type Item[T any] T
type Item interface{}
type Bag interface {
Add(Item)
Size() int
IsEmpty() bool
ForEach(func(Item))
}
// We use linked list as internal data structure
// to get O(1) speed for Add operation
type node struct {
item Item
next *node
}
type bag struct {
size int
head *node
}
func NewBag() Bag {
return &bag{}
}
func (b *bag) Add(item Item) {
next := b.head
b.head = &node{item, next}
b.size++
}
func (b *bag) Size() int {
return b.size
}
func (b *bag) IsEmpty() bool {
return b.size == 0
}
// As for now Go doesn't have iterators.
// But we can simulate them with ForEach method
func (b *bag) ForEach(f func(Item)) {
for current := b.head; current != nil; current = current.next {
f(current.item)
}
}

View file

@ -0,0 +1,36 @@
package bag
import (
"log"
"testing"
)
func TestSimple(t *testing.T) {
bag := NewBag()
sum := 0
bag.Add(1)
bag.Add(2)
bag.Add(3)
bag.ForEach(func(i Item) { sum += i.(int) })
if sum != 6 {
log.Fatal("wrong items in bag")
}
}
func TestEmpty(t *testing.T) {
bag := NewBag()
sum := 0
if bag.Size() != 0 || !bag.IsEmpty() {
log.Fatal("bag should be empty")
}
bag.ForEach(func(i Item) { sum += i.(int) })
if sum != 0 {
log.Fatal("wrong items in bag")
}
}

View file

@ -0,0 +1,59 @@
package queue
// "Generic" item.
// When type parameters will land this type became
// type Item[T any] T
type Item interface{}
type Queue interface {
Enqueue(Item)
Dequeue() Item
Size() int
IsEmpty() bool
}
// We use linked list as internal data structure
// to get O(1) speed for push and pop opeartions
type node struct {
item Item
next *node
}
type queue struct {
size int
head *node
tail *node
}
func NewQueue() Queue {
return &queue{}
}
func (q *queue) Enqueue(item Item) {
oldTail := q.tail
q.tail = &node{item: item, next: nil}
if q.IsEmpty() {
q.head = q.tail
} else {
oldTail.next = q.tail
}
q.size++
}
func (q *queue) Dequeue() Item {
first := q.head
q.head = q.head.next
if q.IsEmpty() {
q.tail = nil
}
q.size--
return first.item
}
func (q *queue) Size() int {
return q.size
}
func (q *queue) IsEmpty() bool {
return q.head == nil
}

View file

@ -0,0 +1,35 @@
package queue
import (
"log"
"testing"
)
func TestSimple(t *testing.T) {
queue := NewQueue()
queue.Enqueue(10)
queue.Enqueue(20)
queue.Enqueue(30)
first, second := queue.Dequeue().(int), queue.Dequeue().(int)
if first != 10 && second != 20 {
log.Fatal("wrong order")
}
}
func TestSize(t *testing.T) {
queue := NewQueue()
if queue.Size() != 0 {
log.Fatal("empty queue should have size 0")
}
queue.Enqueue(10)
queue.Enqueue(20)
queue.Enqueue(30)
if queue.Size() != 3 {
log.Fatal("wrong size")
}
}