Académique Documents
Professionnel Documents
Culture Documents
stacks
resizing arrays
queues
generics
Algorithms F O U R T H E D I T I O N
iterators
applications
R O B E R T S E D G E W I C K K E V I N W A Y N E
Algorithms, 4th Edition Robert Sedgewick and Kevin Wayne Copyright 20022011 September 27, 2011 3:35:54 PM
Stacks and queues
stack push
pop
queue
enqueue dequeue
Stack. Examine the item most recently added. LIFO = "last in first out"
Queue. Examine the item least recently added. FIFO = "first in first out"
2
Client, implementation, interface
Benefits.
Client can't know details of implementation
client has many implementation from which to choose.
Implementation can't know details of client needs
many clients can re-use the same implementation.
Design: creates modular, reusable libraries.
Performance: use optimized implementation where it matters.
3
stacks
resizing arrays
queues
generics
iterators
applications
4
Stack API
push pop
5
Stack test client
push pop
public static void main(String[] args)
{
StackOfStrings stack = new StackOfStrings();
while (!StdIn.isEmpty())
{
String item = StdIn.readString();
if (item.equals("-")) StdOut.print(stack.pop());
else stack.push(item);
}
}
% more tobe.txt
to be or not to - be - - that - - - is
6
Stack: linked-list representation
StdIn StdOut
to
to
null
be
be to
first null
insert at front or or
be
of linked list to
null
not
not or
be
to
null
to
to not
or
be
to
null
- to not
or
be
to
remove from front null
of linked list be
be not
or
be
to
null
not
- be or
be
to
null
or
- not be
to
null
that
that or
be 7
to
null
Stack pop: linked-list implementation
first = first.next;
nodeinner
objectclass
(inner class) 40 bytes
first or
public class Node be
to
{ null
String item; object
Node next; overhead
first
... or
be
} to
extra null
overhead
item
references
return saved item
next return item;
first or
be
to
null
10
Stack: linked-list implementation performance
0 1 2 3 4 5 6 7 8 9
N capacity = 10
decrement N;
then use to index into array
13
Stack considerations
15
Stack: resizing-array implementation
First try.
push(): increase size of array s[] by 1.
pop(): decrease size of array s[] by 1.
Too expensive.
Need to copy all item to a new array.
Inserting first N items takes time proportional to 1 + 2 + + N ~ N 2 / 2.
"repeated doubling"
Q. How to grow array?
A. If array is full, create a new array of twice the size, and copy items.
public ResizingArrayStackOfStrings()
{ s = new String[1]; }
128
cost (array accesses)
64
red dots give cumulative average 3
0
0 number of push() operations 128
Amortized cost of adding to a Stack
18
Stack: resizing-array implementation
First try.
push(): double size of array s[] when array is full.
pop(): halve size of array s[] when array is one-half full.
"thrashing"
Too expensive in worst case.
Consider push-pop-push-pop- sequence when array is full.
Each operation takes time proportional to N.
N = 4 to be or not
N = 4 to be or not
19
Stack: resizing-array implementation
Efficient solution.
push(): double size of array s[] when array is full.
pop(): halve size of array s[] when array is one-quarter full.
20
Stack: resizing-array implementation trace
a[]
push() pop() N a.length
0 1 2 3 4 5 6 7
0 1 null
to 1 1 to
be 2 2 to be
or 3 4 to be or null
not 4 4 to be or not
to 5 8 to be or not to null null null
- to 4 8 to be or not null null null null
be 5 8 to be or not be null null null
- be 4 8 to be or not null null null null
- not 3 8 to be or null null null null null
that 4 8 to be or that null null null null
- that 3 8 to be or null null null null null
- or 2 4 to be null null
- be 1 2 to null
is 2 2 to is
21
Stack resizing-array implementation: performance
Proposition. Starting from an empty stack, any sequence of M push and pop
operations takes time proportional to M.
construct 1 1 1
push 1 N 1
pop 1 N 1
doubling and
halving operations
size 1 1 1
22
Stack resizing-array implementation: memory usage
Tradeoffs. Can implement a stack with either a resizing array or a linked list;
save a link to the list
client can use interchangeably. Which one is better?
Node oldfirst = first;
oldfirst
Linked-list implementation.
first
or
Every operation takes constant
be
time to
in the worst case.
null
Uses extra time and space to deal with the links.
create a new node for the beginning
oldfirst
Every operation
first
takes constant amortized time.
or
Less wasted space. be
to
null
first.next = oldfirst;
first not
or
be
to
null
25
Queue API
enqueue
dequeue
26
Queue: linked-list representation
StdIn StdOut
to
to
null
to
be be
first null last
or to
be
insert at end
or
null
of linked list
to
not be
or
not
null
to
to be
or
not
to
null
be
- to or
not
to
remove from front null
of linked list be be
or
not
to
be
null
or
- be not
to
be
null
not
- or to
be
27
null
not
Queue dequeue: linked-list implementation
first = first.next;
last
first to
nodeinner
objectclass
(inner class) 40 bytes be
or
null
public class Node
{ last
first
String item; object to
be
Node next; overhead or
... null
}
extra
overhead
return saved item
item
return item;
references
next
Removing the first node in a linked list
Remark. Identical code to linked-list stack pop().
28
Queue enqueue: linked-list implementation
oldlast
last
first to
be
or
null
} null
extra
overhead
link the new node to the end of the list
itemoldlast.next = last;
oldlast
references last
first to
next be
or
not
null
30
Queue: resizing array implementation
q[] null null the best of times null null null null
0 1 2 3 4 5 6 7 8 9
31
stacks
resizing arrays
queues
generics
iterators
applications
32
Parameterized stack
We implemented: StackOfStrings.
We also want: StackOfURLs, StackOfInts, StackOfVans, .
33
Parameterized stack
We implemented: StackOfStrings.
We also want: StackOfURLs, StackOfInts, StackOfVans, .
run-time error
34
Parameterized stack
We implemented: StackOfStrings.
We also want: StackOfURLs, StackOfInts, StackOfVans, .
type parameter
a = s.pop();
36
Generic stack: array implementation
37
Generic stack: array implementation
the way it is
38
Generic data types: autoboxing
Wrapper type.
Each primitive type has a wrapper object type.
Ex: Integer is wrapper type for int.
Bottom line. Client code can use generic stack for any type of data.
39
stacks
resizing arrays
queues
generics
iterators
applications
40
Iteration
i N
0 1 2 3 4 5 6 7 8 9
first current
41
Iterators
Iterable interface
Q. What is an Iterable ?
A. Has a method that returns an Iterator. public interface Iterable<Item>
{
Iterator<Item> iterator();
}
Q. What is an Iterator ?
Iterator interface
A. Has methods hasNext() and next().
public interface Iterator<Item>
{
boolean hasNext();
Item next();
Q. Why make data structures Iterable ? void remove();
optional; use
at your own risk
A. Java supports elegant client code. }
import java.util.Iterator;
first current
import java.util.Iterator;
i N
0 1 2 3 4 5 6 7 8 9
44
Iteration: concurrent modification
concurrent modification
To detect:
Count total number of push() and pop() operations in Stack.
Save current count in *Iterator subclass upon creation.
Check that two values are still equal when calling next() and hasNext().
45
Bag API
47
Java collections library
boolean contains(Item item) does the list contain the given item?
...
java.util.Stack.
49
War story (from COS 226)
Kenny
Parsing in a compiler.
Java virtual machine.
Undo in a word processor.
Back button in a Web browser.
PostScript language for printers.
Implementing function calls in a compiler.
...
51
Function calls
52
it is easy to convince yourself that it computes the proper value: any time the algo-
Arithmetic expression evaluation
rithm encounters a subexpression consisting of two operands separated by an op-
erator, all surrounded by parentheses, it leaves the result of performing that opera-
tion on those operands on the operand stack. The result is the same as if that value
had appeared in the input instead of the sub-
Goal. Evaluate infix expressions.
expression, so we can think of replacing valuethe
stack
subexpression by the value to get an expression
operator stack (1+((2+3)*(4*5)))
that would yield the same result. We can apply 1
this argument again and again until we get a +((2+3)*(4*5)))
( 1 + ( ( 2 + 3 ) * single
( 4 value.
* 5 For) example,
) ) the algorithm com- 1
putes the same value of all of these expres- + ((2+3)*(4*5)))
sions: 1 2
operand operator
+3)*(4*5)))
( 1 + ( ( 2 + 3 ) * ( 4 * 5 ) ) ) +
( 1 + ( 5 * ( 4 * 5 ) ) ) 1 2
( 1 + ( 5 * 20 ) ) + + 3)*(4*5)))
( 1 + 100 )
Two-stack algorithm. [E. W. Dijkstra]
101 1 2 3
+ + )*(4*5)))
+ *
+ *
Right parenthesis: pop operator
converts the string and twoonvalues;
into code a lower-level
1 5 4
machine that can do the job. This conversion + * * 5)))
push the result of applying
is a more that operator
complicated process than the step-
1 5 4 5
by-step conversion used by an interpreter, but )))
to those values onto the operand stack.
+ * *
it is based on the same underlying mechanism.
1 5 20
Initially, Java was based on using an interpret- + * ))
er. Now, however, the Java system includes a
1 100
compiler that converts arithmetic expressions + )
(and, more generally, Java programs) into code
101
Context. An interpreter!
for the Java virtual machine, an imaginary ma-
chine that is easy to simulate on an actual com-
puter. Trace of expression evaluation (Program 4.3.5) 53
Arithmetic expression evaluation demo
54
Arithmetic expression evaluation
55
Correctness
Q. Why correct?
A. When algorithm encounters an operator surrounded by two values within
parentheses, it leaves the result on the value stack.
( 1 + ( ( 2 + 3 ) * ( 4 * 5 ) ) )
( 1 + ( 5 * ( 4 * 5 ) ) )
( 1 + ( 5 * 20 ) )
( 1 + 100 )
101
( 1 ( ( 2 3 + ) ( 4 5 * ) * ) + )
1 2 3 + 4 5 * * + Jan Lukasiewicz
%!
72 72 translate
/kochR
{
2 copy ge { dup 0 rlineto }
{
3 div
2 copy kochR 60 rotate
2 copy kochR -120 rotate
2 copy kochR 60 rotate
2 copy kochR
} ifelse
pop pop
} def
see page 218
0 0 moveto 81 243 kochR
0 81 moveto 27 243 kochR
0 162 moveto 9 243 kochR
0 243 moveto 1 243 kochR
stroke
59
Queue applications
Familiar applications.
iTunes playlist.
Data buffers (iPod, TiVo).
Asynchronous data transfer (file IO, pipes, sockets).
Dispensing requests on a shared resource (printer, processor).
60
M/M/1 queuing model
M/M/1 queue.
Customers arrive according to Poisson process at rate of per minute.
Customers are serviced with rate of per minute.
interarrival time has exponential distribution Pr[X x] = 1 - e - x
service time has exponential distribution Pr[X x] = 1 - e - x
61
3 4 5
time (seconds)
0 0
0 1 4 5
0 1 5 30
1 2
An M/D/1 queue
3 4
20
3 4 5
3 4 5
4 5
5 30
62
while (true)
{
while (nextArrival < nextService) next event is an arrival
{
queue.enqueue(nextArrival);
nextArrival += StdRandom.exp(lambda);
}
63
M/M/1 queuing model: experiments
64
M/M/1 queuing model: experiments
65
M/M/1 queuing model: experiments
66
M/M/1 queuing model: analysis
1
W = , L = W