Skip to content

Commit 85451af

Browse files
feat: optimized stack array implementation (#658)
* optimized stack array implementation and modified the unit tests accordingly * Fixed formatting issues * fix exported all methods and converted tests to blackbox * Added generic parameter and fixed package name --------- Co-authored-by: Rak Laptudirm <[email protected]>
1 parent 02fde76 commit 85451af

File tree

4 files changed

+105
-80
lines changed

4 files changed

+105
-80
lines changed

structure/stack/stack_test.go

+54-45
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,24 @@
77
// author [Milad](https://github.com/miraddo)
88
// see stackarray.go, stacklinkedlist.go, stacklinkedlistwithlist.go
99

10-
package stack
10+
package stack_test
1111

1212
import (
1313
"container/list"
14+
"github.com/TheAlgorithms/Go/structure/stack"
1415
"reflect"
1516
"testing"
1617
)
1718

1819
// TestStackLinkedList for testing Stack with LinkedList
1920
func TestStackLinkedList(t *testing.T) {
20-
var newStack Stack
21+
var newStack stack.Stack
2122

22-
newStack.push(1)
23-
newStack.push(2)
23+
newStack.Push(1)
24+
newStack.Push(2)
2425

2526
t.Run("Stack Push", func(t *testing.T) {
26-
result := newStack.show()
27+
result := newStack.Show()
2728
expected := []any{2, 1}
2829
for x := range result {
2930
if result[x] != expected[x] {
@@ -33,20 +34,20 @@ func TestStackLinkedList(t *testing.T) {
3334
})
3435

3536
t.Run("Stack isEmpty", func(t *testing.T) {
36-
if newStack.isEmpty() {
37-
t.Error("Stack isEmpty is returned true but expected false", newStack.isEmpty())
37+
if newStack.IsEmpty() {
38+
t.Error("Stack isEmpty is returned true but expected false", newStack.IsEmpty())
3839
}
3940

4041
})
4142

4243
t.Run("Stack Length", func(t *testing.T) {
43-
if newStack.len() != 2 {
44-
t.Error("Stack Length should be 2 but got", newStack.len())
44+
if newStack.Length() != 2 {
45+
t.Error("Stack Length should be 2 but got", newStack.Length())
4546
}
4647
})
4748

48-
newStack.pop()
49-
pop := newStack.pop()
49+
newStack.Pop()
50+
pop := newStack.Pop()
5051

5152
t.Run("Stack Pop", func(t *testing.T) {
5253
if pop != 1 {
@@ -55,74 +56,82 @@ func TestStackLinkedList(t *testing.T) {
5556

5657
})
5758

58-
newStack.push(52)
59-
newStack.push(23)
60-
newStack.push(99)
61-
t.Run("Stack Peak", func(t *testing.T) {
62-
if newStack.peak() != 99 {
63-
t.Error("Stack Peak should return 99 but got ", newStack.peak())
59+
newStack.Push(52)
60+
newStack.Push(23)
61+
newStack.Push(99)
62+
t.Run("Stack Peek", func(t *testing.T) {
63+
if newStack.Peek() != 99 {
64+
t.Error("Stack Peak should return 99 but got ", newStack.Peek())
6465
}
6566
})
6667
}
6768

6869
// TestStackArray for testing Stack with Array
6970
func TestStackArray(t *testing.T) {
71+
newStack := stack.NewStack[int]()
7072
t.Run("Stack With Array", func(t *testing.T) {
7173

72-
stackPush(2)
73-
stackPush(3)
74+
newStack.Push(2)
75+
newStack.Push(3)
7476

7577
t.Run("Stack Push", func(t *testing.T) {
76-
if !reflect.DeepEqual([]any{3, 2}, stackArray) {
77-
t.Errorf("Stack Push is not work we expected %v but got %v", []any{3, 2}, stackArray)
78+
var stackElements []any
79+
for i := 0; i < 2; i++ {
80+
poppedElement := newStack.Pop()
81+
stackElements = append(stackElements, poppedElement)
82+
}
83+
84+
if !reflect.DeepEqual([]any{3, 2}, stackElements) {
85+
t.Errorf("Stack Push is not work we expected %v but got %v", []any{3, 2}, newStack)
7886
}
87+
88+
newStack.Push(2)
89+
newStack.Push(3)
7990
})
8091

81-
pop := stackPop()
92+
pop := newStack.Pop()
8293

8394
t.Run("Stack Pop", func(t *testing.T) {
84-
85-
if stackLength() == 2 && pop != 3 {
95+
if newStack.Length() == 2 && pop != 3 {
8696
t.Errorf("Stack Pop is not work we expected %v but got %v", 3, pop)
8797
}
8898
})
8999

90-
stackPush(2)
91-
stackPush(83)
100+
newStack.Push(2)
101+
newStack.Push(83)
92102

93103
t.Run("Stack Peak", func(t *testing.T) {
94-
95-
if stackPeak() != 83 {
96-
t.Errorf("Stack Peak is not work we expected %v but got %v", 83, stackPeak())
104+
if newStack.Peek() != 83 {
105+
t.Errorf("Stack Peek is not work we expected %v but got %v", 83, newStack.Peek())
97106
}
98107
})
99108

100109
t.Run("Stack Length", func(t *testing.T) {
101-
if stackLength() != 3 {
102-
t.Errorf("Stack Length is not work we expected %v but got %v", 3, stackLength())
110+
if newStack.Length() != 3 {
111+
t.Errorf("Stack Length is not work we expected %v but got %v", 3, newStack.Length())
103112
}
104113
})
105114

106115
t.Run("Stack Empty", func(t *testing.T) {
107-
if stackEmpty() == true {
108-
t.Errorf("Stack Empty is not work we expected %v but got %v", false, stackEmpty())
116+
if newStack.IsEmpty() == true {
117+
t.Errorf("Stack Empty is not work we expected %v but got %v", false, newStack.IsEmpty())
109118
}
110119

111-
stackPop()
112-
stackPop()
113-
stackPop()
120+
newStack.Pop()
121+
newStack.Pop()
122+
newStack.Pop()
114123

115-
if stackEmpty() == false {
116-
t.Errorf("Stack Empty is not work we expected %v but got %v", true, stackEmpty())
124+
if newStack.IsEmpty() == false {
125+
t.Errorf("Stack Empty is not work we expected %v but got %v", true, newStack.IsEmpty())
117126
}
118127
})
119128
})
120129
}
121130

122131
// TestStackLinkedListWithList for testing Stack with Container/List Library (STL)
123132
func TestStackLinkedListWithList(t *testing.T) {
124-
stackList := &SList{
125-
stack: list.New(),
133+
stackList := &stack.SList{
134+
Stack: list.New(),
126135
}
127136

128137
t.Run("Stack Push", func(t *testing.T) {
@@ -147,7 +156,7 @@ func TestStackLinkedListWithList(t *testing.T) {
147156

148157
stackList.Push(2)
149158
stackList.Push(83)
150-
peak, _ := stackList.Peak()
159+
peak, _ := stackList.Peek()
151160
if peak != 83 {
152161
t.Errorf("Stack Peak is not work we expected %v but got %v", 83, peak)
153162
}
@@ -160,8 +169,8 @@ func TestStackLinkedListWithList(t *testing.T) {
160169
})
161170

162171
t.Run("Stack Empty", func(t *testing.T) {
163-
if stackList.Empty() == true {
164-
t.Errorf("Stack Empty is not work we expected %v but got %v", false, stackList.Empty())
172+
if stackList.IsEmpty() == true {
173+
t.Errorf("Stack Empty is not work we expected %v but got %v", false, stackList.IsEmpty())
165174
}
166175

167176
d1, err := stackList.Pop()
@@ -172,8 +181,8 @@ func TestStackLinkedListWithList(t *testing.T) {
172181
t.Errorf("got an unexpected error %v, pop1: %v, pop2: %v, pop3: %v", err, d1, d2, d3)
173182
}
174183

175-
if stackList.Empty() == false {
176-
t.Errorf("Stack Empty is not work we expected %v but got %v", true, stackList.Empty())
184+
if stackList.IsEmpty() == false {
185+
t.Errorf("Stack Empty is not work we expected %v but got %v", true, stackList.IsEmpty())
177186
}
178187
})
179188
}

structure/stack/stackarray.go

+34-18
Original file line numberDiff line numberDiff line change
@@ -9,31 +9,47 @@
99

1010
package stack
1111

12-
var stackArray []any
12+
type Array[T any] struct {
13+
elements []T
14+
}
15+
16+
// NewStack creates and returns a new stack.
17+
func NewStack[T any]() *Array[T] {
18+
return &Array[T]{}
19+
}
1320

14-
// stackPush push to first index of array
15-
func stackPush(n any) {
16-
stackArray = append([]any{n}, stackArray...)
21+
// Push adds an element to the top of the stack.
22+
func (s *Array[T]) Push(value T) {
23+
s.elements = append(s.elements, value)
1724
}
1825

19-
// stackLength return length of array
20-
func stackLength() int {
21-
return len(stackArray)
26+
// Size returns the number of elements in the stack.
27+
func (s *Array[T]) Length() int {
28+
return len(s.elements)
2229
}
2330

24-
// stackPeak return last input of array
25-
func stackPeak() any {
26-
return stackArray[0]
31+
// Peek returns the top element of the stack without removing it.
32+
func (s *Array[T]) Peek() T {
33+
if s.IsEmpty() {
34+
var zeroValue T
35+
return zeroValue // Stack is empty
36+
}
37+
return s.elements[len(s.elements)-1]
2738
}
2839

29-
// stackEmpty check array is empty or not
30-
func stackEmpty() bool {
31-
return len(stackArray) == 0
40+
// IsEmpty returns true if the stack is empty, false otherwise.
41+
func (s *Array[T]) IsEmpty() bool {
42+
return len(s.elements) == 0
3243
}
3344

34-
// stackPop return last input and remove it in array
35-
func stackPop() any {
36-
pop := stackArray[0]
37-
stackArray = stackArray[1:]
38-
return pop
45+
// Pop removes and returns the top element from the stack.
46+
func (s *Array[T]) Pop() T {
47+
if s.IsEmpty() {
48+
var zeroValue T
49+
return zeroValue // Stack is empty
50+
}
51+
index := len(s.elements) - 1
52+
popped := s.elements[index]
53+
s.elements = s.elements[:index]
54+
return popped
3955
}

structure/stack/stacklinkedlist.go

+6-6
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ type Stack struct {
2222
}
2323

2424
// push add value to last index
25-
func (ll *Stack) push(n any) {
25+
func (ll *Stack) Push(n any) {
2626
newStack := &Node{} // new node
2727

2828
newStack.Val = n
@@ -33,7 +33,7 @@ func (ll *Stack) push(n any) {
3333
}
3434

3535
// pop remove last item as first output
36-
func (ll *Stack) pop() any {
36+
func (ll *Stack) Pop() any {
3737
result := ll.top.Val
3838
if ll.top.Next == nil {
3939
ll.top = nil
@@ -46,22 +46,22 @@ func (ll *Stack) pop() any {
4646
}
4747

4848
// isEmpty to check our array is empty or not
49-
func (ll *Stack) isEmpty() bool {
49+
func (ll *Stack) IsEmpty() bool {
5050
return ll.length == 0
5151
}
5252

5353
// len use to return length of our stack
54-
func (ll *Stack) len() int {
54+
func (ll *Stack) Length() int {
5555
return ll.length
5656
}
5757

5858
// peak return last input value
59-
func (ll *Stack) peak() any {
59+
func (ll *Stack) Peek() any {
6060
return ll.top.Val
6161
}
6262

6363
// show all value as an interface array
64-
func (ll *Stack) show() (in []any) {
64+
func (ll *Stack) Show() (in []any) {
6565
current := ll.top
6666

6767
for current != nil {

structure/stack/stacklinkedlistwithlist.go

+11-11
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,18 @@ import (
1616

1717
// SList is our struct that point to stack with container/list.List library
1818
type SList struct {
19-
stack *list.List
19+
Stack *list.List
2020
}
2121

2222
// Push add a value into our stack
2323
func (sl *SList) Push(val any) {
24-
sl.stack.PushFront(val)
24+
sl.Stack.PushFront(val)
2525
}
2626

2727
// Peak is return last value that insert into our stack
28-
func (sl *SList) Peak() (any, error) {
29-
if !sl.Empty() {
30-
element := sl.stack.Front()
28+
func (sl *SList) Peek() (any, error) {
29+
if !sl.IsEmpty() {
30+
element := sl.Stack.Front()
3131
return element.Value, nil
3232
}
3333
return "", fmt.Errorf("stack list is empty")
@@ -36,11 +36,11 @@ func (sl *SList) Peak() (any, error) {
3636
// Pop is return last value that insert into our stack
3737
// also it will remove it in our stack
3838
func (sl *SList) Pop() (any, error) {
39-
if !sl.Empty() {
39+
if !sl.IsEmpty() {
4040
// get last element that insert into stack
41-
element := sl.stack.Front()
41+
element := sl.Stack.Front()
4242
// remove element in stack
43-
sl.stack.Remove(element)
43+
sl.Stack.Remove(element)
4444
// return element value
4545
return element.Value, nil
4646
}
@@ -49,12 +49,12 @@ func (sl *SList) Pop() (any, error) {
4949

5050
// Length return length of our stack
5151
func (sl *SList) Length() int {
52-
return sl.stack.Len()
52+
return sl.Stack.Len()
5353
}
5454

5555
// Empty check our stack has value or not
56-
func (sl *SList) Empty() bool {
56+
func (sl *SList) IsEmpty() bool {
5757
// check our stack is empty or not
5858
// if is 0 it means our stack is empty otherwise is not empty
59-
return sl.stack.Len() == 0
59+
return sl.Stack.Len() == 0
6060
}

0 commit comments

Comments
 (0)