Added constructor function on linked list and stack data structures
This commit is contained in:
@@ -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]{}
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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()
|
||||||
|
}
|
||||||
|
|||||||
@@ -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
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user