From 797e47363f2f7322b19505a4fa68b1e9832a03f1 Mon Sep 17 00:00:00 2001 From: dudaodong Date: Thu, 10 Feb 2022 11:50:03 +0800 Subject: [PATCH] rename: rename StackArray -> ArrayStack, StackLink -> LinkedStack --- datastructure/arraystack.go | 62 +++++++++++++++++++++ datastructure/arraystack_test.go | 77 ++++++++++++++++++++++++++ datastructure/linkedstack.go | 92 +++++++++++++++++++++++++++++++ datastructure/linkedstack_test.go | 80 +++++++++++++++++++++++++++ 4 files changed, 311 insertions(+) create mode 100644 datastructure/arraystack.go create mode 100644 datastructure/arraystack_test.go create mode 100644 datastructure/linkedstack.go create mode 100644 datastructure/linkedstack_test.go diff --git a/datastructure/arraystack.go b/datastructure/arraystack.go new file mode 100644 index 0000000..87d5560 --- /dev/null +++ b/datastructure/arraystack.go @@ -0,0 +1,62 @@ +package datastructure + +import "errors" + +// ArrayStack implements stack with slice +type ArrayStack[T any] struct { + data []T + length int +} + +// NewArrayStack return a empty ArrayStack pointer +func NewArrayStack[T any]() *ArrayStack[T] { + return &ArrayStack[T]{data: []T{}, length: 0} +} + +// Data return stack data +func (s *ArrayStack[T]) Data() []T { + return s.data +} + +// Length return length of stack data +func (s *ArrayStack[T]) Length() int { + return s.length +} + +// IsEmpty checks if stack is empty or not +func (s *ArrayStack[T]) IsEmpty() bool { + return s.length == 0 +} + +// Push element into stack +func (s *ArrayStack[T]) Push(value T) { + s.data = append([]T{value}, s.data...) + s.length++ +} + +// Pop delete the top element of stack then return it, if stack is empty, return nil and error +func (s *ArrayStack[T]) Pop() (*T, error) { + if s.IsEmpty() { + return nil, errors.New("stack is empty") + } + + topItem := s.data[0] + s.data = s.data[1:] + s.length-- + + return &topItem, nil +} + +// Peak return the top element of stack then return it +func (s *ArrayStack[T]) Peak() (*T, error) { + if s.IsEmpty() { + return nil, errors.New("stack is empty") + } + return &s.data[0], nil +} + +// EmptyStack clear the stack data +func (s *ArrayStack[T]) EmptyStack() { + s.data = []T{} + s.length = 0 +} diff --git a/datastructure/arraystack_test.go b/datastructure/arraystack_test.go new file mode 100644 index 0000000..8fe6196 --- /dev/null +++ b/datastructure/arraystack_test.go @@ -0,0 +1,77 @@ +package datastructure + +import ( + "testing" + + "github.com/duke-git/lancet/internal" +) + +func TestArrayStack_Push(t *testing.T) { + assert := internal.NewAssert(t, "TestArrayStack_Push") + + stack := NewArrayStack[int]() + stack.Push(1) + stack.Push(2) + stack.Push(3) + + expected := []int{3, 2, 1} + values := stack.Data() + length := stack.Length() + + assert.Equal(expected, values) + assert.Equal(3, length) +} + +func TestArrayStack_Pop(t *testing.T) { + assert := internal.NewAssert(t, "TestArrayStack_Pop") + + stack := NewArrayStack[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} + assert.Equal(expected, stack.Data()) +} + +func TestArrayStack_Peak(t *testing.T) { + assert := internal.NewAssert(t, "TestArrayStack_Peak") + + stack := NewArrayStack[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 TestArrayStack_Empty(t *testing.T) { + assert := internal.NewAssert(t, "TestArrayStack_Empty") + + stack := NewArrayStack[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()) +} diff --git a/datastructure/linkedstack.go b/datastructure/linkedstack.go new file mode 100644 index 0000000..e575f20 --- /dev/null +++ b/datastructure/linkedstack.go @@ -0,0 +1,92 @@ +package datastructure + +import ( + "errors" + "fmt" +) + +// LinkedStack implements stack with link list +type LinkedStack[T any] struct { + top *StackNode[T] + length int +} + +// NewLinkedStack return a empty LinkedStack pointer +func NewLinkedStack[T any]() *LinkedStack[T] { + return &LinkedStack[T]{top: nil, length: 0} +} + +// Data return stack data +func (s *LinkedStack[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 *LinkedStack[T]) Length() int { + return s.length +} + +// IsEmpty checks if stack is empty or not +func (s *LinkedStack[T]) IsEmpty() bool { + return s.length == 0 +} + +// Push element into stack +func (s *LinkedStack[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 *LinkedStack[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 *LinkedStack[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 *LinkedStack[T]) EmptyStack() { + s.top = nil + s.length = 0 +} + +// Print all nodes info of stack link +func (s *LinkedStack[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/linkedstack_test.go b/datastructure/linkedstack_test.go new file mode 100644 index 0000000..c41f7fa --- /dev/null +++ b/datastructure/linkedstack_test.go @@ -0,0 +1,80 @@ +package datastructure + +import ( + "testing" + + "github.com/duke-git/lancet/internal" +) + +func TestLinkedStack_Push(t *testing.T) { + assert := internal.NewAssert(t, "TestLinkedStack_Push") + + stack := NewLinkedStack[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 TestLinkedStack_Pop(t *testing.T) { + assert := internal.NewAssert(t, "TestLinkedStack_Pop") + + stack := NewLinkedStack[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 TestLinkedStack_Peak(t *testing.T) { + assert := internal.NewAssert(t, "TestLinkedStack_Peak") + + stack := NewLinkedStack[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 TestLinkedStack_Empty(t *testing.T) { + assert := internal.NewAssert(t, "TestLinkedStack_Empty") + + stack := NewLinkedStack[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()) +}