Download pptx

Survey
yes no Was this document useful for you?
   Thank you for your participation!

* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project

Document related concepts
no text concepts found
Transcript
06 Stacks, Queues, and Deques
Hongfei Yan
Mar. 30, 2016
Contents
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•
01 Python Primer (P2-51)
02 Object-Oriented Programming (P57-103)
03 Algorithm Analysis (P111-141)
04 Recursion (P150-180)
05 Array-Based Sequences (P184-224)
06 Stacks, Queues, and Deques (P229-250)
07 Linked Lists (P256-294)
08 Trees (P300-352)
09 Priority Queues (P363-395)
10 Maps, Hash Tables, and Skip Lists (P402-452)
11 Search Trees (P460-528)
12 Sorting and Selection (P537-574)
13 Text Processing (P582-613)
14 Graph Algorithms (P620-686)
15 Memory Management and B-Trees (P698-717)
Contents
6.1 Stacks
6.2 Queues
6.3 Double-Ended Queues
6.1 Stacks
6.1.1 The Stack Abstract Data Type
6.1.2 Simple Array-Based Stack Implementation
6.1.3 Reversing Data Using a Stack
6.1.4 Matching Parentheses and HTML Tags
A stack is a collection of objects that are inserted
and removed according to the last-in, first-out
(LIFO) principle.
• A user may insert objects into a stack at any time, but may only
access or remove the most recently inserted object that remains (at
the so-called “top” of the stack).
• The name “stack” is derived from the metaphor of a stack of plates in
a spring-loaded, cafeteria plate dispenser. In this case, the
fundamental operations involve the “pushing” and “popping” of
plates on the stack.
E.g., a PEZ candy dispenser, which stores mint candies in a
spring-loaded container that “pops” out the topmost candy
in the stack when the top of the dispenser is lifted
Figure 6.1: A
schematic drawing of a PEZ dispenser; a physical
implementation of the stack ADT. (PEZ is a registered trademark
of PEZ Candy, Inc.)
?
?
Applications of Stacks
• Direct applications
• Page-visited history in a Web browser
• Undo sequence in a text editor
• Chain of method calls in a language that supports recursion
• Indirect applications
• Auxiliary data structure for algorithms
• Component of other data structures
Abstract Data Types (ADTs)
• An abstract data type (ADT) • Example: ADT modeling a simple
is an abstraction of a data
stock trading system
structure
• The data stored are buy/sell orders
• The operations supported are
• An ADT specifies:
• Data stored
• Operations on the data
• Error conditions associated
with operations
• order buy(stock, shares, price)
• order sell(stock, shares, price)
• void cancel(order)
• Error conditions:
• Buy/sell a nonexistent stock
• Cancel a nonexistent order
6.1.1 The Stack Abstract Data Type
• The Stack ADT stores arbitrary objects
• Insertions and deletions follow the lastin first-out scheme
• Think of a spring-loaded plate
dispenser
• Main stack operations:
• push(object): inserts an element
• object pop(): removes and returns the last
inserted element
• Auxiliary stack operations:
• object top(): returns the last
inserted element without
removing it
• integer len(): returns the
number of elements stored
• boolean is_empty():
indicates whether no
elements are stored
By convention, we assume that a newly created stack is empty, and that there is no a priori
bound on the capacity of the stack. Elements added to the stack can have arbitrary type.
Example 6.3: The following table shows a series of stack operations and their effects on an
initially empty stack S of integers.
6.1.2 Simple Array-based Stack Implementation
• A simple way of implementing the Stack ADT uses an array
• We add elements from left to right
• A variable keeps track of the index of the top element
…
S
0 1 2
t
Array-based Stack (cont.)
• The array storing the stack elements may become full
• A push operation will then need to grow the array and copy all
the elements over.
…
S
0 1 2
t
The Adapter Pattern
• The adapter design pattern applies to any context where we
effectively want to modify an existing class so that its methods match
those of a related, but different, class or interface.
Implementing a Stack Using a Python List
• use the adapter design pattern to define an ArrayStack class that uses
an underlying Python list for storage.
• One question that remains is what our code should do if a user calls
pop or top when the stack is empty.
• Our ADT suggests that an error occurs, but we must decide what type of error.
• When pop is called on an empty Python list, it formally raises an IndexError,
as lists are index-based sequences.
• That choice does not seem appropriate for a stack, since there is no
assumption of indices.
• Instead, we can define a new exception class that is more appropriate. Code
Fragment 6.1 defines such an Empty class as a trivial subclass of the Python
Exception class.
Array-based Stack in Python
We choose the name ArrayStack to emphasize
that the underlying storage is inherently array based.)
Example
© 2013 Goodrich, Tamassia, Goldwasser
Stacks
21
Performance and Limitations
• Let n be the number of elements in the stack
• The space used is O(n)
• Each operation runs in time O(1) (amortized in
the case of a push)
Avoiding Amortization by Reserving Capacity
• In some contexts, there may be additional knowledge that suggests a
maximum size that a stack will reach.
• In the analysis of lists from Section 5.4.1, we emphasized that it is
more efficient in practice to construct a list with initial length n than it
is to start with an empty list and append n items (even though both
approaches run in O(n) time).
6.1.3 Reversing Data Using a Stack
6.1.4 Parentheses Matching and HTML Tags
• In our first application, we consider arithmetic expressions that may
contain various pairs of grouping symbols, such as
• Parentheses: “(” and “)”
• Braces: “{” and “}”
• Brackets: “[” and “]”
• Each “(”, “{”, or “[” must be paired with a matching “)”, “}”, or “[”
•
•
•
•
•
correct: ( )(( )){([( )])}
correct: ((( )(( )){([( )])}
incorrect: )(( )){([( )])}
incorrect: ({[ ])}
incorrect: (
Parentheses Matching Algorithm
Algorithm ParenMatch(X,n):
Input: An array X of n tokens, each of which is either a grouping symbol, a
variable, an arithmetic operator, or a number
Output: true if and only if all the grouping symbols in X match
Let S be an empty stack
for i=0 to n-1 do
if X[i] is an opening grouping symbol then
S.push(X[i])
else if X[i] is a closing grouping symbol then
if S.is_empty() then
return false {nothing to match with}
if S.pop() does not match the type of X[i] then
return false {wrong type}
if S.isEmpty() then
return true {every symbol matched}
else return false {some symbols were never matched}
Parentheses
Matching in Python
Performance
• If the length of the original expression is n, the algorithm will make at
most n calls to push and n calls to pop. Those calls run in a total of
O(n) time,
• even considering the amortized nature of the O(1) time bound for those
methods.
• Given that our selection of possible delimiters, ({[, has constant size,
auxiliary tests such as c in lefty and righty.index(c) each run in O(1)
time.
• Combining these operations, the matching algorithm on a sequence
of length n runs in O(n) time.
Matching Tags in a Markup Language
For fully-correct HTML, each <name> should pair with a matching </name>
<body>
<center>
The Little Boat
<h1> The Little Boat </h1>
</center>
<p> The storm tossed the little
boat like a cheap sneaker in an
old washing machine. The three
drunken fishermen were used to
such treatment, of course, but
not the tree salesman, who even as
a stowaway now felt that he
had overpaid for the voyage. </p>
The storm tossed the little boat
like a cheap sneaker in an old
washing machine. The three
drunken fishermen were used to
such treatment, of course, but not
the tree salesman, who even as
a stowaway now felt that he had
overpaid for the voyage.
<ol>
<li> Will the salesman die? </li>
<li> What color is the boat? </li>
<li> And what about Naomi? </li>
</ol>
</body>
1. Will the salesman die?
2. What color is the boat?
3. And what about Naomi?
Tag Matching Algorithm in Python
Code Fragment 6.5: Function
for testing if an HTML document has matching tags.
6.2 Queue
6.2.1 The Queue Abstract Data Type
6.2.2 Array-Based Queue Implementation
Another fundamental data structure is the queue. It is a close “cousin” of
the stack, as a queue is a collection of objects that are inserted and
removed according to the first-in, first-out (FIFO) principle. That is,
elements can be inserted at any time, but only the element that has been
in the queue the longest can be next removed.
Applications of Queues
• Direct applications
• Waiting lists, bureaucracy
• Access to shared resources (e.g., printer)
• Multiprogramming
• Indirect applications
• Auxiliary data structure for algorithms
• Component of other data structures
The Queue ADT
• The Queue ADT stores arbitrary objects
• Insertions and deletions follow the first-in first-out
scheme
• Insertions are at the rear of the queue and removals
are at the front of the queue
• Main queue operations:
• enqueue(object): inserts an element at the end of
the queue
• object dequeue(): removes and returns the element
at the front of the queue
• Auxiliary queue operations:
• object first(): returns the element at the
front without removing it
• integer len(): returns the number of
elements stored
• boolean is_empty(): indicates whether no
elements are stored
• Exceptions
• Attempting the execution of dequeue or
front on an empty queue throws an
EmptyQueueException
Example 6.4: The following table shows a series of queue
operations and their effects on an initially empty queue Q of
integers.
6.2.2 Array-based Queue
• Use an array of size N in a circular fashion
• Two variables keep track of the front and rear
f index of the front element
r index immediately past the rear element
• Array location r is kept empty
normal configuration
Q
0 1 2
f
r
wrapped-around configuration
Q
0 1 2
r
f
Queue Operations
• We use the modulo operator
(remainder of division)
Algorithm size()
return (N - f + r) mod N
Algorithm isEmpty()
return (f = r)
Q
0 1 2
f
0 1 2
r
r
Q
f
Queue Operations (cont.)
• Operation enqueue throws an
exception if the array is full
• This exception is implementationdependent
Algorithm enqueue(o)
if size() = N - 1 then
throw FullQueueException
else
Q[r]  o
r  (r + 1) mod N
Q
0 1 2
f
0 1 2
r
r
Q
f
Queue Operations (cont.)
• Operation dequeue throws an
exception if the queue is empty
• This exception is specified in the
queue ADT
Algorithm dequeue()
if isEmpty() then
throw EmptyQueueException
else
o  Q[f]
f  (f + 1) mod N
return o
Q
0 1 2
f
0 1 2
r
r
Q
f
Queue in Python
• Use the following three instance variables:
• _data: is a reference to a list instance with a fixed capacity.
• _size: is an integer representing the current number of elements
stored in the queue (as opposed to the length of the data list).
• _front: is an integer that represents the index within data of the
first element of the queue (assuming the queue is not empty).
Queue in Python (1/3)
Queue in Python (2/3)
Queue in Python (3/3)
Table 6.3: Performance
of an array-based implementation of a queue. The
bounds for enqueue and dequeue are amortized due to the resizing of
the array. The space usage is O(n), where n is the current number of
elements in the queue.
Application: Round Robin Schedulers
•
We can implement a round robin scheduler using a queue Q by
repeatedly performing the following steps:
1.
2.
3.
e = Q.dequeue()
Service element e
Q.enqueue(e)
Queue
Dequeue
Enqueue
Shared
Service
6.3 Double-Ended Queues
• queue-like data structure that supports insertion and deletion at
both the front and the back of the queue.
• Such a structure is called a doubleended queue, or deque, which is
usually pronounced “deck”
• to avoid confusion with the dequeue method of the regular queue ADT,
which is pronounced like the abbreviation “D.Q.”
• An implementation of a deque class is available in Python’s
standard collections module.
Deque in Python (1/3)
Deque in Python (2/3)
Deque in Python (3/3)
Summary: Stack, Queue, Deque