bag, queue
This commit is contained in:
parent
6f9dc7b91b
commit
a35bb36872
4 changed files with 181 additions and 0 deletions
51
fundamentals/bag/bag.go
Normal file
51
fundamentals/bag/bag.go
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
36
fundamentals/bag/bag_test.go
Normal file
36
fundamentals/bag/bag_test.go
Normal 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")
|
||||||
|
}
|
||||||
|
}
|
59
fundamentals/queue/queue.go
Normal file
59
fundamentals/queue/queue.go
Normal 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
|
||||||
|
}
|
35
fundamentals/queue/queue_test.go
Normal file
35
fundamentals/queue/queue_test.go
Normal 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")
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue