diff --git a/README.md b/README.md index e1948d7..4918d21 100644 --- a/README.md +++ b/README.md @@ -152,6 +152,7 @@ All stacks implement the stack interface with the following methods: Empty() bool Size() int Clear() + Values() []interface{} ``` ####LinkedListStack @@ -169,6 +170,7 @@ func main() { stack := lls.New() // empty stack.Push(1) // 1 stack.Push(2) // 1, 2 + stack.Values() // 2, 1 (LIFO order) _, _ = stack.Peek() // 2,true _, _ = stack.Pop() // 2, true _, _ = stack.Pop() // 1, true @@ -183,7 +185,7 @@ func main() { ####ArrayStack -This stack structure is based on a array. +This stack structure is back by ArrayList. All operations are guaranted constant time performance. @@ -196,6 +198,7 @@ func main() { stack := arraystack.New() // empty stack.Push(1) // 1 stack.Push(2) // 1, 2 + stack.Values() // 2, 1 (LIFO order) _, _ = stack.Peek() // 2,true _, _ = stack.Pop() // 2, true _, _ = stack.Pop() // 1, true diff --git a/examples/arraystack.go b/examples/arraystack.go index bad52af..1dd93ce 100644 --- a/examples/arraystack.go +++ b/examples/arraystack.go @@ -32,6 +32,7 @@ func ArrayStackExample() { stack := arraystack.New() // empty stack.Push(1) // 1 stack.Push(2) // 1, 2 + stack.Values() // 2, 1 (LIFO order) _, _ = stack.Peek() // 2,true _, _ = stack.Pop() // 2, true _, _ = stack.Pop() // 1, true diff --git a/examples/linkedliststack.go b/examples/linkedliststack.go index ce77bcf..b7911f1 100644 --- a/examples/linkedliststack.go +++ b/examples/linkedliststack.go @@ -32,6 +32,7 @@ func LinkedListStackExample() { stack := lls.New() // empty stack.Push(1) // 1 stack.Push(2) // 1, 2 + stack.Values() // 2, 1 (LIFO order) _, _ = stack.Peek() // 2,true _, _ = stack.Pop() // 2, true _, _ = stack.Pop() // 1, true diff --git a/stacks/arraystack/arraystack.go b/stacks/arraystack/arraystack.go index 329d859..4e0599a 100644 --- a/stacks/arraystack/arraystack.go +++ b/stacks/arraystack/arraystack.go @@ -24,7 +24,7 @@ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -// Implementation of stack using a slice. +// Implementation of stack backed by ArrayList. // Structure is not thread safe. // References: http://en.wikipedia.org/wiki/Stack_%28abstract_data_type%29 @@ -32,6 +32,7 @@ package arraystack import ( "fmt" + "github.com/emirpasic/gods/lists/arraylist" "github.com/emirpasic/gods/stacks" "strings" ) @@ -41,64 +42,54 @@ func assertInterfaceImplementation() { } type Stack struct { - elements []interface{} - top int + list *arraylist.List } // Instantiates a new empty stack func New() *Stack { - return &Stack{top: -1} + return &Stack{list: arraylist.New()} } // Pushes a value onto the top of the stack func (stack *Stack) Push(value interface{}) { - // Increase when capacity is reached by a factor of 1.5 and add one so it grows when size is zero - if stack.top+1 >= cap(stack.elements) { - currentSize := len(stack.elements) - sizeIncrease := int(1.5*float32(currentSize) + 1.0) - newSize := currentSize + sizeIncrease - newItems := make([]interface{}, newSize, newSize) - copy(newItems, stack.elements) - stack.elements = newItems - } - stack.top += 1 - stack.elements[stack.top] = value + stack.list.Add(value) } // Pops (removes) top element on stack and returns it, or nil if stack is empty. // Second return parameter is true, unless the stack was empty and there was nothing to pop. func (stack *Stack) Pop() (value interface{}, ok bool) { - if stack.top >= 0 { - value, ok = stack.elements[stack.top], true - stack.top -= 1 - return - } - return nil, false + return stack.list.Get(stack.list.Size() - 1) } // Returns top element on the stack without removing it, or nil if stack is empty. // Second return parameter is true, unless the stack was empty and there was nothing to peek. func (stack *Stack) Peek() (value interface{}, ok bool) { - if stack.top >= 0 { - return stack.elements[stack.top], true - } - return nil, false + return stack.list.Get(stack.list.Size() - 1) } // Returns true if stack does not contain any elements. func (stack *Stack) Empty() bool { - return stack.Size() == 0 + return stack.list.Empty() } // Returns number of elements within the stack. func (stack *Stack) Size() int { - return stack.top + 1 + return stack.list.Size() } // Removes all elements from the stack. func (stack *Stack) Clear() { - stack.top = -1 - stack.elements = []interface{}{} + return stack.list.Clear() +} + +// Returns all elements in the stack (LIFO order). +func (stack *Stack) Values() []interface{} { + size := stack.list.Size() + elements := make([]interface{}, size, size) + for i := size - 1; i >= 0; i-- { // in reverse + elements[i] = stack.list.Get(i) + } + return elements } func (stack *Stack) String() string { diff --git a/stacks/arraystack/arraystack_test.go b/stacks/arraystack/arraystack_test.go index 7681c31..e6358ba 100644 --- a/stacks/arraystack/arraystack_test.go +++ b/stacks/arraystack/arraystack_test.go @@ -27,6 +27,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package arraystack import ( + "github.com/emirpasic/gods/utils" "testing" ) @@ -43,6 +44,10 @@ func TestArrayStack(t *testing.T) { stack.Push(2) stack.Push(3) + if actualValue := stack.Values(); !utils.IdenticalSlices(actualValue, []interface{}{3, 2, 1}) { + t.Errorf("Got %v expected %v", actualValue, []interface{}{3, 2, 1}) + } + if actualValue := stack.Empty(); actualValue != false { t.Errorf("Got %v expected %v", actualValue, false) } @@ -77,6 +82,10 @@ func TestArrayStack(t *testing.T) { t.Errorf("Got %v expected %v", actualValue, true) } + if actualValue := stack.Values(); !utils.IdenticalSlices(actualValue, []interface{}{}) { + t.Errorf("Got %v expected %v", actualValue, []interface{}{}) + } + } func BenchmarkArrayStack(b *testing.B) { diff --git a/stacks/linkedliststack/linkedliststack.go b/stacks/linkedliststack/linkedliststack.go index 607dfaa..41d64ca 100644 --- a/stacks/linkedliststack/linkedliststack.go +++ b/stacks/linkedliststack/linkedliststack.go @@ -98,6 +98,19 @@ func (stack *Stack) Clear() { stack.size = 0 } +// Returns all elements in the stack (LIFO order). +func (stack *Stack) Values() []interface{} { + size := stack.list.Size() + elements := make([]interface{}, size, size) + element := stack.top + for index := 0; element != nil; index++ { + elements[index] = element + element = element.next + } + + return elements +} + func (stack *Stack) String() string { str := "LinkedListStack\n" element := stack.top diff --git a/stacks/linkedliststack/linkedliststack_test.go b/stacks/linkedliststack/linkedliststack_test.go index 79bec5a..b2fca60 100644 --- a/stacks/linkedliststack/linkedliststack_test.go +++ b/stacks/linkedliststack/linkedliststack_test.go @@ -27,6 +27,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package linkedliststack import ( + "github.com/emirpasic/gods/utils" "testing" ) @@ -43,6 +44,10 @@ func TestLinkedListStack(t *testing.T) { stack.Push(2) stack.Push(3) + if actualValue := stack.Values(); !utils.IdenticalSlices(actualValue, []interface{}{3, 2, 1}) { + t.Errorf("Got %v expected %v", actualValue, []interface{}{3, 2, 1}) + } + if actualValue := stack.Empty(); actualValue != false { t.Errorf("Got %v expected %v", actualValue, false) } @@ -77,6 +82,10 @@ func TestLinkedListStack(t *testing.T) { t.Errorf("Got %v expected %v", actualValue, true) } + if actualValue := stack.Values(); !utils.IdenticalSlices(actualValue, []interface{}{}) { + t.Errorf("Got %v expected %v", actualValue, []interface{}{}) + } + } func BenchmarkLinkedListStack(b *testing.B) { diff --git a/stacks/stacks.go b/stacks/stacks.go index 5b3bf16..cd5f816 100644 --- a/stacks/stacks.go +++ b/stacks/stacks.go @@ -33,4 +33,5 @@ type Interface interface { Empty() bool Size() int Clear() + Values() []interface{} } diff --git a/utils/slices.go b/utils/slices.go new file mode 100644 index 0000000..1009f7c --- /dev/null +++ b/utils/slices.go @@ -0,0 +1,14 @@ +package utils + +// order and elements in the two slices have to match +func IdenticalSlices(s1 []interface{}, s2 []interface{}) bool { + if len(s1) != len(s2) { + return false + } + for i := 0; i < len(s1); i++ { + if s1[i] != s2[i] { + return false + } + } + return true +}