4 Stacks and Queues
4 Stacks and Queues
S E D G E W I C K / W A Y N E
SEDGEWICK
ntist WAYNE
Computer Science
ary
A N I N T E R D I S C I P L I N A RY A P P R O A C H
or
d
gs,
of
omputer
C cience Stacks and Queues
hem
h.
S
nce
d
wick
ysis
orics;
ver
An Interdisciplinary Approach
ROBERT SEDGEWICK
ANADA
K E V I N WAY N E
Section 4.3
COMPUTER SCIENCE
S E D G E W I C K / W A Y N E
Data types
• Set of values.
• Set of operations on those values.
• Some are built into Python int: int, float, str, . . .
• Most are not: complex, graphics, random, . . .
Data structures
• Represent data.
• Represent relationships among data.
• Some are built in to Python: lists, dictionaries, . . .
• Most are not: linked list, circular list, tree, . . .
Design challenge for every data type: Which data structure to use?
• Resource 1: How much memory is needed?
• Resource 2: How much time do data-type methods use?
3
Data structures: sequential versus linked
C4 C4 "Alice"
Linked data structure C5 C5 CA
• Associate with each object a link to another one. C6 C6
• Machine: link is memory address of next object. C7 C7
• Python: link is reference to next object. C8 C8
• Variable size, sequential access. next element C9 C9
• Overlooked by novice programmers. CA CA "Bob"
• Flexible, widely used method for organizing data. CB CB C0
4
Simplest singly-linked data structure: linked list
Linked list
• A recursive data structure.
class _Node:
• A linked list is null or a reference to a node. def __init__(self, item =
• A node holds an item and a pointer to the next node in the list. None, next = None):
self._nextNode = next
self._item = item
Representation
• Use a private nested class _Node to implement the node abstraction.
• For simplicity, start with nodes having two attributes:
• an item
• a reference to a _Node object.
A linked list
Even with just one link ( ) a wide variety of data structures are possible.
Tree
Linked list (this lecture)
Rho
6
Building a linked list
C0 "Carol"
second = _Node(“Bob”, third)
C1 None
first = _Node(“Alice”, second) C2
C3
third C0
C4 "Alice"
second CA
C5 CA
first C4
C6
C7
C8
C9
first second third
CA "Bob"
None
7
List processing algorithms
Standard operations for processing data structured as a singly-linked list: addr value
C7
C8
…and an operation that, for efficiency, calls for a doubly-linked list
C9
• Remove and return the node at the end.
CA "Bob"
CB C0
8
List processing algorithms: Remove and return the first item
item
item = first._someItem "Alice" first "Alice" "Bob" "Carol"
item
first = first._nextNode "Alice" first "Alice" "Bob" "Carol"
9
List processing algorithms: Add a new node at the beginning
item
Goal. Add item to a linked list first.
"Dave"
second
second
second
first._item = item
first "Dave" "Alice" "Bob" "Carol"
first._nextNode = second
10
List processing code: Add a new node at the end
item
Goal. Add item to the end of a linked list.
"Dave" last
Use and maintain a reference last
first "Alice" "Bob" "Carol"
item
"Dave" last
last.next = _Node()
first "Alice" "Bob" "Carol"
item
"Dave" last
last = last.next
first "Alice" "Bob" "Carol"
last
11
List processing algorithms: Traverse a list
x = first; x
while (x != None):
first "Alice" "Bob" "Carol"
print(x._someValue)
x = x._nextNode
List:
Alice
Output
Bob
Carol
12
Implementation of a linked list
class LinkedList: def __iter__(self):
class _Node: # private nested class pointer = self._head
def __init__(self, item = None, nextNode = None): while pointer is not None:
self._nextNode = nextNode yield pointer._item
self._item = item pointer = pointer._nextNode
None
item next
15
Stack and Queue APIs
A collection is an ADT whose values are a multiset of items, usually, all of the same type.
Two fundamental collection ADTs differ in just a detail of the specification of their operations.
• Return the size of the collection. • Return the size of the collection.
Add to the
Stacks and queues both arise naturally in countless applications. end
16
Example of stack operations
push to the pop from the
top top
to be
not not not not not that
stack contents
or or or or or or or or or
after
operation be be be be be be be be be be be is
to to to to to to to to to to to to to to
17
Example of queue operations
dequeue from the
beginning
enqueue at
the end
Goal. Simple, safe, and clear client code for collections of any type of data.
class Stack
Stack() create a stack of items
push(item) add item to stack
Stack API
pop() remove and return the item most recently pushed
isEmpty() is the stack empty ?
size() # of objects on the stack
class Queue
Queue() create a queue of items
enqueue(item) add item to queue
Queue API
dequeue() remove and return the item least recently enqueued
isEmpty() is the queue empty ?
size() # of objects in the queue
19
Performance specifications
Performance
• Memory use is linear in the size of the collection,
specifications when it is nonempty.
• No limits within the code on the collection size.
RS+KW. Implementations that do not meet performance specs do not implement the abstractions.
20
linkedstack.py
# Implemented as a linked-list of Node objects # Pop the top item from the stack and return it.
class Stack: def pop(self):
class _Node: # private nested class if self._first is None:
def __init__(self, item = None, nextNode = None): return None
self._nextNode = nextNode else:
self._item = item item = self._first._item
self._first = self._first._nextNode
# Construct an empty Stack object. return item
def __init__(self):
self._first = None # Reference to first _Node # Return string representation of stack. (Not in the
API.)
# Return True if stack is empty, False otherwise. def __str__(self):
def isEmpty(self): s = ""
return self._first is None cur = self._first
while cur is not None:
# Push item onto the top of stack. s += str(cur._item) + ", "
def push(self, item): cur = cur._nextNode
self._first = self._Node(item, self._first) return s[0:-2]
Note: This class does not fully implement the API shown before.
As a lab exercise you will add the code for size().
21
linkedstack.py
def main(): $: python3 linkedstack.py
s = Stack() Stack contents:
for i in range(13): s.push(i) 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
Stack contents:
print("Stack contents:")
20, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
print(str(s))
Removed: 20
Removed: 12
Stack contents:
s.push(20)
11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
print("Stack contents:")
print(str(s))
There is an alternative implementation in the course
print("Removed:",str(s.pop())) shell, stack.py, implemented using the
print("Removed:",str(s.pop())) built in list type.
print("Stack contents:")
print(str(s)) Exercise: compare the implementations in two ways:
• visually
if __name__ == '__main__':
main()
• performance (use stopwatch.py)
22
linkedqueue.py
Test Client
• reads a text file, one line at a time
• parses each space-separated string, and adds it to the queue, using enqueue()
• ‘-’ is interpreted as a call to dequeue()
def main():
queue = Queue()
tobe.txt
output = "" # to record items removed from the queue
for line in fileinput.input(sys.argv[1:]): #read each to be or not to - be - - that - - - is
line in file
items = line.split(' ') # read each (space-
separated) item in line
for item in items:
$: python3 linkedqueue.py < tobe.txt
item = item.strip() # removes any leading and
to be or not to be
trailing spaces
if item != '-':
queue.enqueue(item)
else:
output += queue.dequeue() + " "
print(output)
23
COMPUTER SCIENCE
S E D G E W I C K / W A Y N E
• Linked lists
• Stacks and Queues
• Client Applications
• Implementations
Stack and queue applications
Queues
• First-come-first-served resource allocation.
• Asynchronous data transfer (standard input,
standard output).
• Dispensing requests on a shared resource.
• Simulations of the real world.
Stacks
• Last-come-first-served resource allocation.
• Function calls in programming languages.
• Basic mechanism in interpreters, compilers.
• Fundamental abstraction in computing.
25
Stack example: "Back" button in a browser
Typical scenario
• Visit a page.
• Click a link to another page.
• Click a link to another page.
• Click a link to another page.
• Click "back" button.
• Click "back" button.
• Click "back" button.
https://introcs.cs.princeton.edu/python/43stack/
https://introcs.cs.princeton.edu/python/40algorithms/
https://introcs.cs.princeton.edu/python/home/
26
Stack client example: Postfix expression evaluation
Infix. Standard way of writing arithmetic expressions, using parentheses for precedence.
1 2 3 + 4 5 * * +
There is only one way find first operator, convert to HP-35 (1972)
1 (2+3)4 5 * * + infix, enclose in ()
to parenthesize a First handheld calculator.
postfix expression. 1 ((2+3)*(4*5))+ "Enter" means "push".
iterate, treating subexpressions in
No parentheses.
parentheses as atomic
(1+((2+3)*(4*5)))
Algorithm
• While input stream is nonempty, read a token.
• Value: Push onto the stack.
• Operator: Pop operand(s), apply operator, push the result.
1 2 3 + 4 5 * * +
1 2 3 + 4 5 * * +
= 5 = 20= 100
= 101 5
3 4 4 20
2 2 5 5 5 5 100
1 1 1 1 1 1 1 1 101
28
Stack client example: postfix expression evaluation
from linkedstack import *
Input expression:
# compute value of postfix expression using a stack • must be in postfix form and contain:
def postfix(expr): • numbers (real or integer, ≥ 0)
s = Stack()
• operators from { +, -, *, / }
for term in expr:
if isinstance(term, int or float): s.push(term)
else: s.push(calc(s.pop(), s.pop(), term)) Output
return s.pop()
$: python3 postfix.py
21
# helper method performs an arithmetic operation
def calc(a, b, op):
if op == '+': return a + b Perspective:
elif op == '-': return a - b
elif op == '*': return a * b
• Easy to add operators of all sorts.
elif op == '/': return a / b • Can do infix with two stacks (see text).
• Could output machine language code.
def main():
print(postfix([6, 9, '-', 5, 2, '+', '*']))
• Indicative of how Python compiler works.
if __name__ == '__main__':
main()
29
COMPUTER SCIENCE
S E D G E W I C K / W A Y N E
PA R T I : P R O G R A M M I N G I N J AVA
Image sources
http://pixabay.com/en/book-stack-learn-knowledge-library-168824/
http://upload.wikimedia.org/wikipedia/commons/2/20/Cars_in_queue_to_enter_Gibraltar_from_Spain.jpg
COMPUTER SCIENCE
S E D G E W I C K / W A Y N E
• Linked lists
• APIs
• Client Applications
• Implementations
Benchmarking the stack implementation
class Stack
Stack() create a stack of items
push(item) add item to stack
Stack API
pop() remove and return the item most recently pushed
isEmpty() is the stack empty ?
size() # of objects on the stack
Also possible to implement the queue abstraction with a singly-linked list (see text).
32
Performance can vary
33
Performance can vary
total2 = 0.0
watch2 = Stopwatch()
a = []
for i in range(n):
a.insert(i, 'fast')
time2 = watch2.elapsedTime()
34
Summary
push to the pop from the dequeue from the
Stacks and queues beginning beginning beginning
enqueue at
the end
Linked structures
• Fundamental alternative to arrays.
• Enable implementations of the stack/queue abstractions that
meet performance specifications.
35
Reading and References
These Slides
• principally based on slides by Robert Sedgewick and Kevin Wayne, and Manrique Mata-Montero
Recommended Reading
• online booksite (Python version) chapter 4
focus on section 4.3
Suggested Wider Reading / Watch & Learn
• section 4.1 from the online booksite on analysis of algorithms
• this might provide some insight into the importance of choosing a data structure wisely!
• A video by Lucid Computing that explains the stack as its coded (one of a series)
Activity:
• complete Lab 2 when available
• download and play with the implementations of linked lists, stacks and queues found in the
course shell
also notice that linkedqueue.py also implements some simple file handling in its main()
36