0% found this document useful (0 votes)
254 views

Python Stacks

This document describes the stack data structure and its implementation in Python. It begins by defining the stack abstract data type (ADT) as a linear data structure that follows a last-in, first-out (LIFO) protocol. New items are added to the top of the stack and removed from the top. The document then discusses two implementations of the stack ADT in Python - using a Python list and using a linked list. It provides code examples for stack operations like isEmpty(), push(), pop(), etc. for both implementations and analyzes their time complexities.

Uploaded by

Alvaro Ocola
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
254 views

Python Stacks

This document describes the stack data structure and its implementation in Python. It begins by defining the stack abstract data type (ADT) as a linear data structure that follows a last-in, first-out (LIFO) protocol. New items are added to the top of the stack and removed from the top. The document then discusses two implementations of the stack ADT in Python - using a Python list and using a linked list. It provides code examples for stack operations like isEmpty(), push(), pop(), etc. for both implementations and analyzes their time complexities.

Uploaded by

Alvaro Ocola
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 4

Data Structures and

Algorithms Using
Python
Rance D. Necaise
Department of Computer Science
College of William and Mary

JOHN WILEY & SONS, INC.

194

CHAPTER

Stacks

7.1 The Stack ADT


A stack is used to store data such that the last item inserted is the first item
removed. It is used to implement a last-in first-out (LIFO) type protocol. The
stack is a linear data structure in which new items are added, or existing items are
removed from the same end, commonly referred to as the top of the stack. The
opposite end is known as the base. Consider the example in Figure 7.1, which
55

5
55

23

19

74

23
23

12

74

19
19
23
23
74
74

12
12

(a)

Stacks

illustrates new values being added to the top of the stack and one value being
removed from the top.
Define

Stack ADT

A stack is a data structure that stores a linear collection of items with access
limited to a last-in first-out order. Adding and removing items is restricted to one
end known as the top of the stack. An empty stack is one containing no items.

In the previous chapters, we used the Python list and linked list structures to
implement a variety of container abstract data types. In this chapter, we introduce
the stack, which is a type of container with restricted access that stores a linear
collection. Stacks are very common in computer science and are used in many
types of problems. Stacks also occur in our everyday lives. Consider a stack of
trays in a lunchroom. When a tray is removed from the top, the others shift up.
If trays are placed onto the stack, the others are pushed down.

19
19

CHAPTER 7

12
12

(b)

(c)

19
19
23
23
74
74
12
12

(d)

Figure 7.1: Abstract view of a stack: (a) pushing value 19; (b) pushing value 5; (c)
resulting stack after 19 and 5 are added; and (d) popping top value.

193

Stack(): Creates a new empty stack.

isEmpty(): Returns a boolean value indicating if the stack is empty.

length (): Returns the number of items in the stack.

pop(): Removes and returns the top item of the stack, if the stack is not empty.
Items cannot be popped from an empty stack. The next item on the stack
becomes the new top item.

peek(): Returns a reference to the item on top of a non-empty stack without


removing it. Peeking, which cannot be done on an empty stack, does not
modify the stack contents.

push( item ): Adds the given item to the top of the stack.

To illustrate a simple use of the Stack ADT, we apply it to the problem of


reversing a list of integer values. The values will be extracted from the user until a
negative value is entered, which flags the end of the collection. The values will then
be printed in reverse order from how they were entered. We could use a simple list
for this problem, but a stack is ideal since the values can be pushed onto the stack
as they are entered and then popped one at a time to print them in reverse order.
A solution for this problem follows.
PROMPT = "Enter an int value (<0 to end):"
myStack = Stack()
value = int(input( PROMPT ))
while value >= 0 :
myStack.push( value )
value = int(input( PROMPT ))
while not myStack.isEmpty() :
value = myStack.pop()
print( value )

Suppose the user enters the following values, one at a time:


7

13

45

19

28

-1

7.2 Implementing the Stack

When the outer while loop terminates after the negative value is extracted, the
contents of the stack will be as illustrated in Figure 7.2. Notice the last value
entered is at the top and the first is at the base. If we pop the values from the
stack, they will be removed in the reverse order from which they were pushed onto
the stack, producing a reverse ordering.

28
28
19
19
45
45
13
13
77

Figure 7.2: Resulting stack after executing the sample application.

7.2 Implementing the Stack


The Stack ADT can be implemented in several ways. The two most common
approaches in Python include the use of a Python list and a linked list. The choice
depends on the type of application involved.

195

196

CHAPTER 7

Stacks

Listing 7.1

The pyliststack.py module.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

# Returns True if the stack is empty or False otherwise.


def isEmpty( self ):
return len( self ) == 0
# Returns the number of items in the stack.
def __len__ ( self ):
return len( self._theItems )
# Returns the top item on the stack without removing it.
def peek( self ):
assert not self.isEmpty(), "Cannot peek at an empty stack"
return self._theItems[-1]
# Removes and returns the top item on the stack.
def pop( self ):
assert not self.isEmpty(), "Cannot pop from an empty stack"
return self._theItems.pop()
# Push an item onto the top of the stack.
def push( self, item ):
self._theItems.append( item )

The individual stack operations are easy to evaluate for the Python list-based
implementation. isEmpty(), len , and peek() only require O(1) time. The
pop() and push() methods both require O(n) time in the worst case since the
underlying array used to implement the Python list may have to be reallocated
to accommodate the addition or removal of the top stack item. When used in
sequence, both operations have an amortized cost of O(1).

7.2.1 Using a Python List


The Python list-based implementation of the Stack ADT is the easiest to implement. The first decision we have to make when using the list for the Stack ADT
is which end of the list to use as the top and which as the base. For the most
efficient ordering, we let the end of the list represent the top of the stack and the
front represent the base. As the stack grows, items are appended to the end of the
list and when items are popped, they are removed from the same end. Listing 7.1
on the next page provides the complete implementation of the Stack ADT using a
Python list.
The peek() and pop() operations can only be used with a non-empty stack
since you cannot remove or peek at something that is not there. To enforce this
requirement, we first assert the stack is not empty before performing the given
operation. The peek() method simply returns a reference to the last item in the
list. To implement the pop() method, we call the pop() method of the list structure, which actually performs the same operation that we are trying to implement.
That is, it saves a copy of the last item in the list, removes the item from the list,
and then returns the saved copy. The push() method simply appends new items
to the end of the list since that represents the top of our stack.

# Implementation of the Stack ADT using a Python list.


class Stack :
# Creates an empty stack.
def __init__( self ):
self._theItems = list()

7.2.2

Using a Linked List


The Python list-based implementation may not be the best choice for stacks with
a large number of push and pop operations. Remember, each append() and pop()
list operation may require a reallocation of the underlying array used to implement
the list. A singly linked list can be used to implement the Stack ADT, alleviating
the concern over array reallocations.
To use a linked list, we again must decide how to represent the stack structure.
With the Python list implementation of the stack, it was most efficient to use the
end of the list as the top of the stack. With a linked list, however, the front of the
list provides the most efficient representation for the top of the stack. In Chapter 6,
we saw how to easily prepend nodes to the linked list as well as remove the first
node. The Stack ADT implemented using a linked list is provided in Listing 7.2.

7.2 Implementing the Stack


Listing 7.2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

197

198

CHAPTER 7

The lliststack.py module.

size 4

# Implementation of the Stack ADT using a singly linked list.


class Stack :
# Creates an empty stack.
def __init__( self ):
self._top = None
self._size = 0

top

19
19

23
23

74
74

12
12

Stack

Figure 7.3: Sample object of the Stack ADT implemented as a linked list.

# Returns True if the stack is empty or False otherwise.


def isEmpty( self ):
return self._top is None

The peek() method simply returns a reference to the data item in the first
node after verifying the stack is not empty. If the method were used on the stack
represented by the linked list in Figure 7.3, a reference to 19 would be returned.
The peek operation is only meant to examine the item on top of the stack. It
should not be used to modify the top item as this would violate the definition of
the Stack ADT.
The pop() method always removes the first node in the list. This operation
is illustrated in Figure 7.4(a). This is easy to implement and does not require a
search to find the node containing a specific item. The result of the linked list after
popping the top item from the stack is illustrated in Figure 7.4(b).
The linked list implementation of the Stack ADT is more efficient than the
Python-list based implementation. All of the operations are O(1) in the worst
case, the proof of which is left as an exercise.

# Returns the number of items in the stack.


def __len__( self ):
return self._size
# Returns the top item on the stack without removing it.
def peek( self ):
assert not self.isEmpty(), "Cannot peek at an empty stack"
return self._top.item
# Removes and returns the top item on the stack.
def pop( self ):
assert not self.isEmpty(), "Cannot pop from an empty stack"
node = self._top
self.top = self._top.next
self._size -= 1
return node.item

size 4

# Pushes an item onto the top of the stack.


def push( self, item ) :
self._top = _StackNode( item, self._top )
self._size += 1

top

19
19

23
23

Stack

# The private storage class for creating stack nodes.


class _StackNode :
def __init__( self, item, link ) :
self.item = item
self.next = link

The class constructor creates two instance variables for each Stack. The top
field is the head reference for maintaining the linked list while size is an integer
value for keeping track of the number of items on the stack. The latter has to be
adjusted when items are pushed onto or popped off the stack. Figure 7.3 on the
next page illustrates a sample Stack object for the stack from Figure 7.1(b).
The StackNode class is used to create the linked list nodes. Note the inclusion
of the link argument in the constructor, which is used to initialize the next field of
the new node. By including this argument, we can simplify the prepend operation
of the push() method. The two steps required to prepend a node to a linked list
are combined by passing the head reference top as the second argument of the
StackNode() constructor and assigning a reference to the new node back to top.

Stacks

74
74

12
12

(a)
size 33
top

23
23

Stack

74
74

12
12

(b)

Figure 7.4: Popping an item from the stack: (a) the required link modifications, and (b) the
result after popping the top item.

7.3

Stack Applications
The Stack ADT is required by a number of applications encountered in computer
science. In this section, we examine several basic applications that traditionally
are presented in a data structures course.

You might also like