I am trying to implement a simple stack with Python using arrays. I was wondering if someone could let me know what's wrong with my code.
class myStack:
def __init__(self):
self = []
def isEmpty(self):
return self == []
def push(self, item):
self.append(item)
def pop(self):
return self.pop(0)
def size(self):
return len(self)
s = myStack()
s.push('1')
s.push('2')
print(s.pop())
print s
Python list can be used as the stack. It uses the append() method to insert elements to the list where stack uses the push() method. The list also provides the pop() method to remove the last element, but there are shortcomings in the list. The list becomes slow as it grows.
A stack is a linear data structure that stores items in a Last In First Out way. In stack, elements are added at one end and an element is deleted from that end only. The insert and delete operations are called push and pop operations.
You can perform the implementation of stacks in data structures using two data structures that are an array and a linked list. Array: In array implementation, the stack is formed using an array. All the operations are performed using arrays.
A stack is a container (linear collection) in which dynamic set operations
are carried out as per the last-in first-out (LIFO) principle.
There is only one pointer - top
, which is used to perform these operations
CLRS implementation of stack using array:
class Stack:
"""
Last in first out (LIFO) stack implemented using array.
"""
def __init__(self, capacity=4):
"""
Initialize an empty stack array with default capacity of 4.
"""
self.data = [None] * capacity
self.capacity = capacity
self.top = -1
def is_empty(self):
"""
Return true if the size of stack is zero.
"""
if self.top == -1:
return True
return False
def push(self, element):
"""
Add element to the top.
"""
self.top += 1
if self.top >= self.capacity:
raise IndexError('Stack overflow!')
else:
self.data[self.top] = element
def pop(self):
"""
Return and remove element from the top.
"""
if self.is_empty():
raise Exception('Stack underflow!')
else:
stack_top = self.data[self.top]
self.top -= 1
return stack_top
def peek(self):
"""
Return element at the top.
"""
if self.is_empty():
raise Exception('Stack is empty.')
return None
return self.data[self.top]
def size(self):
"""
Return the number of items present.
"""
return self.top + 1
Testing the implemetation:
def main():
"""
Sanity test
"""
stack = Stack()
print('Size of the stack is:', stack.size())
stack.push(3)
print('Element at the top of the stack is: ', stack.peek())
stack.push(901)
print('Element at the top of the stack is: ', stack.peek())
stack.push(43)
print('Element at the top of the stack is: ', stack.peek())
print('Size of the stack is:', stack.size())
stack.push(89)
print('Element at the top of the stack is: ', stack.peek())
print('Size of the stack is:', stack.size())
#stack.push(9) # Raises IndexError
stack.pop()
print('Size of the stack is:', stack.size())
stack.pop()
print('Size of the stack is:', stack.size())
stack.pop()
print('Size of the stack is:', stack.size())
print('Element at the top of the stack is: ', stack.peek())
stack.pop()
#print('Element at the top of the stack is: ', stack.peek()) # Raises empty stack exception
if __name__ == '__main__':
main()
I corrected a few problems below. Also, a 'stack', in abstract programming terms, is usually a collection where you add and remove from the top, but the way you implemented it, you're adding to the top and removing from the bottom, which makes it a queue.
class myStack:
def __init__(self):
self.container = [] # You don't want to assign [] to self - when you do that, you're just assigning to a new local variable called `self`. You want your stack to *have* a list, not *be* a list.
def isEmpty(self):
return self.size() == 0 # While there's nothing wrong with self.container == [], there is a builtin function for that purpose, so we may as well use it. And while we're at it, it's often nice to use your own internal functions, so behavior is more consistent.
def push(self, item):
self.container.append(item) # appending to the *container*, not the instance itself.
def pop(self):
return self.container.pop() # pop from the container, this was fixed from the old version which was wrong
def peek(self):
if self.isEmpty():
raise Exception("Stack empty!")
return self.container[-1] # View element at top of the stack
def size(self):
return len(self.container) # length of the container
def show(self):
return self.container # display the entire stack as list
s = myStack()
s.push('1')
s.push('2')
print(s.pop())
print(s.show())
Assigning to self
won't turn your object into a list (and if it did, the object wouldn't have all your stack methods any more). Assigning to self
just changes a local variable. Instead, set an attribute:
def __init__(self):
self.stack = []
and use the attribute instead of just a bare self
:
def push(self, item):
self.stack.append(item)
Also, if you want a stack, you want pop()
rather than pop(0)
. pop(0)
would turn your data structure into a(n inefficient) queue.
I left a comment with the link to http://docs.python.org/2/tutorial/datastructures.html#using-lists-as-stacks, but if you want to have a custom type that gives you push
, pop
, is_empty
, and size
convenience methods, I'd just subclass list
.
class Stack(list):
def push(self, item):
self.append(item)
def size(self):
return len(self)
def is_empty(self):
return not self
However, as I said in the comments, I'd probably just stick with a straight list
here, as all you are really doing is aliasing existing methods, which usually only serves to make your code harder to use in the long run, as it requires people using it to learn your aliased interface on top of the original.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With