Java collections library
List interface. java.util.List is API for an sequence of items.
public interface List<Item> implements Iterable<Item>
List()
boolean isEmpty()
int size()
create an empty list
is the list empty?
number of items
void add(Item item)
append item to the end
Item get(int index)
return item at given index
Item remove(int index)
boolean contains(Item item)
Iteartor<Item> iterator()
return and delete item at given index
does the list contain the given item?
iterator over all items in the list
...
Implementations. java.util.ArrayList uses resizing array;
java.util.LinkedList uses linked list.
53
Java collections library
java.util.Stack.
Supports push(), pop(), and and iteration.
Also implements java.util.List interface from previous slide,
including, get(), remove(), and contains().
Bloated and poorly-designed API (why?)
java.util.Queue. An interface, not an implementation of a queue.
Best practices. Use our implementations of Stack, Queue, and Bag.
54
War story (from COS 226)
Generate random open sites in an N-by-N percolation system.
Jenny:
percolates
pick (i, j) at random; if already
open, repeat. blocked
site
Takes ~ c1 N 2 seconds.
Kenny:
does not percolate
create a java.util.ArrayList of N 2 closed sites.
Pick an index at random and delete.
open
Takes ~ c2 N 4 seconds.
site
open site connected to top
no open site connected to
Why is my program so slow?
Kenny
Lesson. Don't use a library until you understand its API!
This course. Can't use a library until we've implemented it in class.
55
Stack applications
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.
...
56
Function calls
How a compiler implements a function.
Function call: push local environment and return address.
Return: pop return address and local environment.
Recursive function. Function that calls itself.
Note. Can always use an explicit stack to remove recursion.
gcd (216, 192)
static int gcd(int p, int q) {
if (q == 0) return p;
else return gcd(q,gcd
p %(192,
q); 24)
}
static int gcd(int p, int q) {
p = 192, q = 24
if (q == 0) return p;
gcd
else return gcd(q, p
% (24,
q); 0)
}
static int gcd(int p, int q) {
if (q == 0) return p;
p = 24, q = 0
else return gcd(q, p % q);
}
p = 216, q = 192
57
it is easy to convince yourself that it computes the proper value: any time the algorithm encounters a subexpression consisting of two operands separated by an opArithmetic expressionerator,
evaluation
all surrounded by parentheses, it leaves the result of performing that operation on those operands on the operand stack. The result is the same as if that value
had appeared in the input instead of the subexpression, so we can think of replacing
valuethe
stack
Goal. Evaluate infix expressions.
(1+((2+3)*(4*5)))
subexpression by the value to get an
expression
operator
stack
that would yield the same result. We can apply
1
+((2+3)*(4*5)))
this argument again and again until we get a
( 1 + ( ( 2 + 3 ) * ( single
4 * 5
) )For)example, the algorithm comvalue.
1
((2+3)*(4*5)))
putes the same value of all of these expres+
sions:
1 2
operand
operator
( 1
( 1
( 1
( 1
101
+
+
+
+
( (
( 5
( 5
100
2 + 3 ) * ( 4 * 5 ) ) )
* ( 4 * 5 ) ) )
* 20 ) )
)
Two-stack algorithm. [E. W. Dijkstra]
+3)*(4*5)))
1 2
+ +
3)*(4*5)))
1 2 3
+ +
)*(4*5)))
(PROGRAM 4.3.5) is an implemen1 5
Value: push onto the
stack.This code is a simple
tationvalue
of this method.
*(4*5)))
+
example of an interpreter : a program that in1 5
Operator: push onto
the
stack.by a given
terprets
theoperator
computation specified
(4*5)))
+ *
string and performs the computation to ar1 5 4
Left parenthesis: ignore.
rive at the result. A compiler is a program that
*5)))
+ *
converts the string into code on a lower-level
Right parenthesis: machine
pop operator
and two values; 1 5 4
that can do the job. This conversion
5)))
+ * *
is a more complicated
process than the steppush the result of applying
that operator
1 5 4 5
by-step conversion used by an interpreter, but
)))
+ * *
it is based
the same underlying
to those values onto
the on
operand
stack.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
for the Java virtual machine, an imaginary maContext. An interpreter!
chine that is easy to simulate on an actual computer.
Trace of expression evaluation (Program 4.3.5)
Evaluate
58
Dijkstra's two-stack algorithm demo
value stack
infix expression
operator stack
(fully parenthesized)
+
operand
operator
59
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 ) ) )
as if the original input were:
( 1 + ( 5 * ( 4 * 5 ) ) )
Repeating the argument:
( 1 + ( 5 * 20 ) )
( 1 + 100 )
101
Extensions. More ops, precedence order, associativity.
61
Stack-based programming languages
Observation 1. Dijkstra's two-stack algorithm computes the same value if
the operator occurs after the two values.
( 1 ( ( 2 3 + ) ( 4 5 * ) * ) + )
Observation 2. All of the parentheses are redundant!
1 2 3 + 4 5 * * +
Jan Lukasiewicz
Bottom line. Postfix or "reverse Polish" notation.
Applications. Postscript, Forth, calculators, Java virtual machine,
62