Added constructor function on linked list and stack data structures

This commit is contained in:
Fabio Scotto di Santolo
2023-01-06 11:41:41 +01:00
parent 4b25a6b1c6
commit ac20be21e4
4 changed files with 95 additions and 76 deletions

View File

@@ -70,6 +70,14 @@ type LinkedList[E any] struct {
size int size int
} }
func NewLinkedList[E any](items ...E) *LinkedList[E] {
lst := &LinkedList[E]{}
for _, item := range items {
lst.PushBack(item)
}
return lst
}
func (l *LinkedList[E]) Iterator() Iterator[E] { func (l *LinkedList[E]) Iterator() Iterator[E] {
if l.Empty() { if l.Empty() {
return &emptyListIterator[E]{} return &emptyListIterator[E]{}

View File

@@ -10,9 +10,9 @@ func TestLinkedList_Empty(t *testing.T) {
list *LinkedList[int] list *LinkedList[int]
want bool want bool
}{ }{
{description: "no items in list", list: newList(), want: true}, {description: "no items in list", list: NewLinkedList[int](), want: true},
{description: "one item in list", list: newList(1), want: false}, {description: "one item in list", list: NewLinkedList(1), want: false},
{description: "more items in list", list: newList(1, 2, 3), want: false}, {description: "more items in list", list: NewLinkedList(1, 2, 3), want: false},
} }
for _, tt := range useCases { for _, tt := range useCases {
@@ -29,9 +29,9 @@ func TestLinkedList_Size(t *testing.T) {
list *LinkedList[int] list *LinkedList[int]
want int want int
}{ }{
{description: "no items in list", list: newList(), want: 0}, {description: "no items in list", list: NewLinkedList[int](), want: 0},
{description: "one item in list", list: newList(1), want: 1}, {description: "one item in list", list: NewLinkedList(1), want: 1},
{description: "more items in list", list: newList(1, 2, 3), want: 3}, {description: "more items in list", list: NewLinkedList(1, 2, 3), want: 3},
} }
for _, tt := range useCases { for _, tt := range useCases {
@@ -50,13 +50,13 @@ func TestLinkedList_GetAt(t *testing.T) {
err error err error
want int want int
}{ }{
{description: "get first item", list: newList(1, 2, 3), pos: 0, want: 1, err: nil}, {description: "get first item", list: NewLinkedList(1, 2, 3), pos: 0, want: 1, err: nil},
{description: "get middle item", list: newList(1, 2, 3), pos: 1, want: 2, err: nil}, {description: "get middle item", list: NewLinkedList(1, 2, 3), pos: 1, want: 2, err: nil},
{description: "get last item", list: newList(1, 2, 3), pos: 2, want: 3, err: nil}, {description: "get last item", list: NewLinkedList(1, 2, 3), pos: 2, want: 3, err: nil},
{description: "get last item", list: newList(1, 2, 3), pos: 2, want: 3, err: nil}, {description: "get last item", list: NewLinkedList(1, 2, 3), pos: 2, want: 3, err: nil},
{description: "no items in list return zero value of the type", list: newList(), pos: 0, want: 0, err: ErrEmptyList}, {description: "no items in list return zero value of the type", list: NewLinkedList[int](), pos: 0, want: 0, err: ErrEmptyList},
{description: "get item with negative position", list: newList(1, 2, 3), pos: -1, want: 0, err: ErrPositionNegative}, {description: "get item with negative position", list: NewLinkedList(1, 2, 3), pos: -1, want: 0, err: ErrPositionNegative},
{description: "get item with index out of bound", list: newList(1, 2, 3), pos: 4, want: 0, err: ErrIndexOutOfBound{4, 3}}, {description: "get item with index out of bound", list: NewLinkedList(1, 2, 3), pos: 4, want: 0, err: ErrIndexOutOfBound{4, 3}},
} }
for _, tt := range useCases { for _, tt := range useCases {
@@ -74,9 +74,9 @@ func TestLinkedList_Back(t *testing.T) {
err error err error
want int want int
}{ }{
{description: "no items in list return zero value of the type", list: newList(), want: 0, err: ErrEmptyList}, {description: "no items in list return zero value of the type", list: NewLinkedList[int](), want: 0, err: ErrEmptyList},
{description: "singleton list return first element", list: newList(1), want: 1}, {description: "singleton list return first element", list: NewLinkedList(1), want: 1},
{description: "get last item", list: newList(1, 2, 3), want: 3}, {description: "get last item", list: NewLinkedList(1, 2, 3), want: 3},
} }
for _, tt := range useCases { for _, tt := range useCases {
@@ -94,9 +94,9 @@ func TestLinkedList_Front(t *testing.T) {
err error err error
want int want int
}{ }{
{description: "no items in list return zero value of the type", list: newList(), want: 0, err: ErrEmptyList}, {description: "no items in list return zero value of the type", list: NewLinkedList[int](), want: 0, err: ErrEmptyList},
{description: "singleton list return first element", list: newList(1), want: 1}, {description: "singleton list return first element", list: NewLinkedList(1), want: 1},
{description: "get first item", list: newList(1, 2, 3), want: 1}, {description: "get first item", list: NewLinkedList(1, 2, 3), want: 1},
} }
for _, tt := range useCases { for _, tt := range useCases {
@@ -116,23 +116,23 @@ func TestLinkedList_PushAt(t *testing.T) {
item int item int
}{ }{
{description: "add item in first position in empty list", {description: "add item in first position in empty list",
original: newList(), original: NewLinkedList[int](),
modified: newList(1), modified: NewLinkedList(1),
pos: 0, pos: 0,
item: 1}, item: 1},
{description: "add item in first position in full list", {description: "add item in first position in full list",
original: newList(1, 2, 3), original: NewLinkedList(1, 2, 3),
modified: newList(0, 1, 2, 3), modified: NewLinkedList(0, 1, 2, 3),
pos: 0, pos: 0,
item: 0}, item: 0},
{description: "add item in middle position in full list", {description: "add item in middle position in full list",
original: newList(1, 2, 3), original: NewLinkedList(1, 2, 3),
modified: newList(1, 2, 0, 3), modified: NewLinkedList(1, 2, 0, 3),
pos: 2, pos: 2,
item: 0}, item: 0},
{description: "add item in last position in full list", {description: "add item in last position in full list",
original: newList(1, 2, 3), original: NewLinkedList(1, 2, 3),
modified: newList(1, 2, 3, 0), modified: NewLinkedList(1, 2, 3, 0),
pos: 3, pos: 3,
item: 0}, item: 0},
} }
@@ -154,16 +154,16 @@ func TestLinkedList_PushBack(t *testing.T) {
item int item int
}{ }{
{description: "add item in first position in empty list", {description: "add item in first position in empty list",
original: newList(), original: NewLinkedList[int](),
modified: newList(1), modified: NewLinkedList(1),
item: 1}, item: 1},
{description: "add item in singleton list", {description: "add item in singleton list",
original: newList(1), original: NewLinkedList(1),
modified: newList(1, 0), modified: NewLinkedList(1, 0),
item: 0}, item: 0},
{description: "add item in full list", {description: "add item in full list",
original: newList(1, 2, 3), original: NewLinkedList(1, 2, 3),
modified: newList(1, 2, 3, 0), modified: NewLinkedList(1, 2, 3, 0),
item: 0}, item: 0},
} }
@@ -184,16 +184,16 @@ func TestLinkedList_PushFront(t *testing.T) {
item int item int
}{ }{
{description: "add item in first position in empty list", {description: "add item in first position in empty list",
original: newList(), original: NewLinkedList[int](),
modified: newList(1), modified: NewLinkedList(1),
item: 1}, item: 1},
{description: "add item in singleton list", {description: "add item in singleton list",
original: newList(1), original: NewLinkedList(1),
modified: newList(0, 1), modified: NewLinkedList(0, 1),
item: 0}, item: 0},
{description: "add item in full list", {description: "add item in full list",
original: newList(1, 2, 3), original: NewLinkedList(1, 2, 3),
modified: newList(0, 1, 2, 3), modified: NewLinkedList(0, 1, 2, 3),
item: 0}, item: 0},
} }
@@ -214,33 +214,33 @@ func TestLinkedList_DeleteAt(t *testing.T) {
err error err error
}{ }{
{description: "delete item with negative position", {description: "delete item with negative position",
original: newList(), original: NewLinkedList[int](),
modified: nil, modified: nil,
pos: -1, pos: -1,
err: ErrPositionNegative}, err: ErrPositionNegative},
{description: "delete item in empty list", {description: "delete item in empty list",
original: newList(), original: NewLinkedList[int](),
modified: nil, modified: nil,
pos: 0, pos: 0,
err: ErrEmptyList}, err: ErrEmptyList},
{description: "delete item in position not found", {description: "delete item in position not found",
original: newList(1, 2, 3), original: NewLinkedList(1, 2, 3),
modified: newList(), modified: NewLinkedList[int](),
pos: 5, pos: 5,
err: ErrNodeNotFound}, err: ErrNodeNotFound},
{description: "delete item in first position", {description: "delete item in first position",
original: newList(1, 2, 3), original: NewLinkedList(1, 2, 3),
modified: newList(2, 3), modified: NewLinkedList(2, 3),
pos: 0, pos: 0,
err: nil}, err: nil},
{description: "delete item in middle position", {description: "delete item in middle position",
original: newList(1, 2, 3), original: NewLinkedList(1, 2, 3),
modified: newList(1, 3), modified: NewLinkedList(1, 3),
pos: 1, pos: 1,
err: nil}, err: nil},
{description: "delete item in last position", {description: "delete item in last position",
original: newList(1, 2, 3), original: NewLinkedList(1, 2, 3),
modified: newList(1, 2), modified: NewLinkedList(1, 2),
pos: 2, pos: 2,
err: nil}, err: nil},
} }
@@ -253,14 +253,6 @@ func TestLinkedList_DeleteAt(t *testing.T) {
} }
} }
func newList(items ...int) *LinkedList[int] {
lst := &LinkedList[int]{}
for _, item := range items {
lst.PushBack(item)
}
return lst
}
func compareLists(lst1, lst2 *LinkedList[int]) bool { func compareLists(lst1, lst2 *LinkedList[int]) bool {
for it := lst1.Iterator(); it.HasNext(); { for it := lst1.Iterator(); it.HasNext(); {
i, item1 := it.NextWithIndex() i, item1 := it.NextWithIndex()

View File

@@ -1,6 +1,9 @@
package collection package collection
import "fmt" import (
"fmt"
"strings"
)
var ( var (
// ErrEmptyStack is error when you have an empty stack structure // ErrEmptyStack is error when you have an empty stack structure
@@ -12,6 +15,15 @@ type Stack[E any] struct {
items []E items []E
} }
// NewStack is a constructor function for stack
func NewStack[E any](items ...E) *Stack[E] {
stack := &Stack[E]{}
for _, item := range items {
stack.Push(item)
}
return stack
}
// Size returns the number of items in the stack. // Size returns the number of items in the stack.
func (s *Stack[E]) Size() int { func (s *Stack[E]) Size() int {
return len(s.items) return len(s.items)
@@ -47,3 +59,20 @@ func (s *Stack[E]) Push(item E) error {
s.items = append(s.items, item) s.items = append(s.items, item)
return nil return nil
} }
func (s *Stack[E]) String() string {
var sb strings.Builder
sb.WriteString("[")
for i := 0; i < s.Size(); i++ {
var str string
item := s.items[i]
if i >= s.Size()-1 {
str = fmt.Sprintf("%v", item)
} else {
str = fmt.Sprintf("%v, ", item)
}
sb.WriteString(str)
}
sb.WriteString("]")
return sb.String()
}

View File

@@ -1,9 +1,7 @@
package collection_test package collection
import ( import (
"testing" "testing"
"github.com/asd/pkg/collection"
) )
type pair struct { type pair struct {
@@ -13,22 +11,22 @@ type pair struct {
var staticTests = []struct { var staticTests = []struct {
description string description string
input *collection.Stack[int] input *Stack[int]
empty bool empty bool
size int size int
top pair top pair
}{ }{
{"empty stack", newStack([]int{}), true, 0, pair{0, collection.ErrEmptyStack}}, {"empty stack", NewStack[int](), true, 0, pair{0, ErrEmptyStack}},
{"stack with items", newStack([]int{1, 2, 3}), false, 3, pair{3, nil}}, {"stack with items", NewStack(1, 2, 3), false, 3, pair{3, nil}},
} }
var popTests = []struct { var popTests = []struct {
description string description string
input *collection.Stack[int] input *Stack[int]
item pair item pair
}{ }{
{"empty stack pop item", newStack([]int{}), pair{0, collection.ErrEmptyStack}}, {"empty stack pop item", NewStack[int](), pair{0, ErrEmptyStack}},
{"stack with items pop item", newStack([]int{1, 2, 3}), pair{3, nil}}, {"stack with items pop item", NewStack(1, 2, 3), pair{3, nil}},
} }
var pushTests = []struct { var pushTests = []struct {
@@ -79,7 +77,7 @@ func TestPush(t *testing.T) {
for i, tt := range pushTests { for i, tt := range pushTests {
t.Logf("Test %v: %s\n", i, tt.description) t.Logf("Test %v: %s\n", i, tt.description)
stack := &collection.Stack[int]{} stack := NewStack[int]()
for _, item := range tt.items { for _, item := range tt.items {
stack.Push(item) stack.Push(item)
} }
@@ -89,11 +87,3 @@ func TestPush(t *testing.T) {
} }
} }
} }
func newStack(slice []int) *collection.Stack[int] {
stack := &collection.Stack[int]{}
for _, x := range slice {
stack.Push(x)
}
return stack
}