diff --git a/datastructure/node.go b/datastructure/node.go index db3b5d4..2442cd5 100644 --- a/datastructure/node.go +++ b/datastructure/node.go @@ -15,7 +15,7 @@ func NewLinkNode[T any](value T) *LinkNode[T] { // StackNode is a node in stack, which have a Value and Pre points to previous node in the stack. type StackNode[T any] struct { Value T - Pre *StackNode[T] + Next *StackNode[T] } // NewStackNode return a StackNode pointer diff --git a/datastructure/stackarray.go b/datastructure/stackarray.go index a4efde0..5c6dca8 100644 --- a/datastructure/stackarray.go +++ b/datastructure/stackarray.go @@ -2,7 +2,7 @@ package datastructure import "errors" -// StackArray is a linear table, implemented with slice +// StackArray implements stack with slice type StackArray[T any] struct { data []T length int diff --git a/datastructure/stacklink.go b/datastructure/stacklink.go new file mode 100644 index 0000000..221c83b --- /dev/null +++ b/datastructure/stacklink.go @@ -0,0 +1,92 @@ +package datastructure + +import ( + "errors" + "fmt" +) + +// StackLink is a linear table, implemented with slice +type StackLink[T any] struct { + top *StackNode[T] + length int +} + +// NewStackLink return a empty StackLink pointer +func NewStackLink[T any]() *StackLink[T] { + return &StackLink[T]{top: nil, length: 0} +} + +// Data return stack data +func (s *StackLink[T]) Data() []T { + res := []T{} + current := s.top + + for current != nil { + res = append(res, current.Value) + current = current.Next + } + return res +} + +// Length return length of stack data +func (s *StackLink[T]) Length() int { + return s.length +} + +// IsEmpty checks if stack is empty or not +func (s *StackLink[T]) IsEmpty() bool { + return s.length == 0 +} + +// Push element into stack +func (s *StackLink[T]) Push(value T) { + newNode := NewStackNode(value) + top := s.top + if top == nil { + s.top = newNode + } else { + newNode.Next = top + s.top = newNode + } + + s.length++ +} + +// Pop delete the top element of stack then return it, if stack is empty, return nil and error +func (s *StackLink[T]) Pop() (*T, error) { + if s.IsEmpty() { + return nil, errors.New("stack is empty") + } + + top := s.top + s.top = s.top.Next + s.length-- + + return &top.Value, nil +} + +// Peak return the top element of stack then return it +func (s *StackLink[T]) Peak() (*T, error) { + if s.IsEmpty() { + return nil, errors.New("stack is empty") + } + return &s.top.Value, nil +} + +// EmptyStack clear the stack data +func (s *StackLink[T]) EmptyStack() { + s.top = nil + s.length = 0 +} + +// Print all nodes info of stack link +func (s *StackLink[T]) Print() { + current := s.top + info := "[ " + for current != nil { + info += fmt.Sprintf("%+v, ", current) + current = current.Next + } + info += " ]" + fmt.Println(info) +} diff --git a/datastructure/stacklink_test.go b/datastructure/stacklink_test.go new file mode 100644 index 0000000..e7573f8 --- /dev/null +++ b/datastructure/stacklink_test.go @@ -0,0 +1,80 @@ +package datastructure + +import ( + "testing" + + "github.com/duke-git/lancet/internal" +) + +func TestStackLink_Push(t *testing.T) { + assert := internal.NewAssert(t, "TestStackLink_Push") + + stack := NewStackLink[int]() + stack.Push(1) + stack.Push(2) + stack.Push(3) + + stack.Print() + + expected := []int{3, 2, 1} + values := stack.Data() + length := stack.Length() + + assert.Equal(expected, values) + assert.Equal(3, length) +} + +func TestStackLink_Pop(t *testing.T) { + assert := internal.NewAssert(t, "TestStackLink_Pop") + + stack := NewStackLink[int]() + topItem, err := stack.Pop() + assert.IsNotNil(err) + + stack.Push(1) + stack.Push(2) + stack.Push(3) + + topItem, err = stack.Pop() + assert.IsNil(err) + assert.Equal(3, *topItem) + + expected := []int{2, 1} + stack.Print() + assert.Equal(expected, stack.Data()) +} + +func TestStackLink_Peak(t *testing.T) { + assert := internal.NewAssert(t, "TestStackLink_Peak") + + stack := NewStackLink[int]() + topItem, err := stack.Peak() + assert.IsNotNil(err) + + stack.Push(1) + stack.Push(2) + stack.Push(3) + + topItem, err = stack.Peak() + assert.IsNil(err) + assert.Equal(3, *topItem) + + expected := []int{3, 2, 1} + assert.Equal(expected, stack.Data()) +} + +func TestStackLink_Empty(t *testing.T) { + assert := internal.NewAssert(t, "TestStackLink_Empty") + + stack := NewStackLink[int]() + assert.Equal(true, stack.IsEmpty()) + assert.Equal(0, stack.Length()) + + stack.Push(1) + assert.Equal(false, stack.IsEmpty()) + assert.Equal(1, stack.Length()) + + stack.EmptyStack() + assert.Equal(true, stack.IsEmpty()) + assert.Equal(0, stack.Length()) +}