You’re in the right place if you want to improve your Java programming skills and learn lots about the various ways to organize data efficiently for your applications. You’ll also learn about analysis of algorithms, formal specifications, automated unit testing, performance analysis, and a few more things.
Catalog Description: This course covers the analysis, design, and implementation of data structures including arrays, stacks, queues, linked lists, binary trees, heaps, balanced trees, and graphs. Other topics include sorting, hashing, Java generics, unit testing, and benchmarking. Course work involves both written homework and Java programming assignments.
Prerequisite(s): 601.107: Introductory Programming in Java or 601.220: Intermediate Programming.
Policies: Please read the general course policies and take them to heart. Additional policies specific to this course may be posted at a later date.
There is no required text book for this course, but it’s highly recommended that you obtain reference material to supplement lecture. Here are some suggestions.
checkstylethat you may run into
Please check the individual assignments for due dates and the structure your solutions should have. See the course policies for detailed submission instructions.
If you have an opinion on these assignments, be it good or bad, please let us know about it. We’re always trying to make these things more enjoyable (if that’s an applicable term? :-).
This is not a schedule. It’s a “log” of what we did, roughly, in each lecture. Don’t expect it to turn into a schedule, it won’t. Also there will eventually be gaps, sorry.
-Xlint:allcompiler option; using
checkstyleto enforce consistent programming style; putting together (and double-checking!)
.tar.gzarchives for submissions.
Counterinterface; Java classes as implementations; the
SimpleCounterimplementation; testing the
assertfor automated, self-contained testing; a second
WeirdCounterimplementation plus test cases.
Integerspecification; developing three variants of the
Counterspecification; design tradeoff: how specific should a specification be?
Variable; ADT notation for type parameters and constraints; the
Anyspecification, equals operation; ADT notation for functions with multiple parameters; see Piazza for writeups of all the specifications; introduction to generics in Java; hacking a
Variableinterface and a
SimpleVariableimplementation plus test cases.
ArrayADT; partial functions and preconditions in specifications.
Arrayinterface and a
SimpleArrayimplementation; exceptions in Java to enforce precondition (for partial functions in the specification); the difference between
RuntimeExceptionin Java; testing
SimpleArray; deriving test cases from the specification; testing exceptions.
toString; review of Java’s for-each loop; the
Iteratorinterfaces in Java; adjusting the
Arrayinterface to be iterable; implementing the iterator as a nested class in Java.
Arraybased on singly-linked lists; nested class for
Nodeobjects; inner class for
Iteratorimplementation; adapting the
StackADT; developing a specification for
Stack; the problem with
equalsfor stacks, why we don’t want to be “programming” in specifications; the
Stackinterface; implementation with a singly-linked list; appending vs. prepending nodes on
push, implications for
pop; implementation with a Java array; tracking the “used” portion of the array; the trouble with
push: whatever the size of the array, it’s wrong, we need to “resize” the array when necessary.
ArrayStackimplementation: make a bigger one (twice as big is good), copy existing data, then “switch” the arrays; introduction to sorting; specifying what “sorted” means; in place / in situ sorting algorithms; stable sorting algorithms; a “silly” sorting algorithm that takes up to n! steps; “better” sorting algorithms that take roughly n^2 steps: bubble sort, selection sort, insertion sort.
staticimports to avoid
Assert.assertEqualsand so on; some background on
-classpathto compile and run JUnit 4 test cases; extended example of writing the
Countertests; testing against interfaces by splitting tests into base class (which has the general interface test cases) and derived classes (which instantiate the unit under test and have implementation-specific tests).
pushis O(n) in
ArrayStack; more detailed analysis shows that
pushis amortized O(1) instead; long discussion of the list abstraction, especially the need for abstract positions; contrast to array and deque abstractions; starting on the interface for
Listimplementation as a doubly-linked list of node objects; how to think about / visualize the implementation over time; figuring out
insertFrontin some detail, focus on getting “pointers” or “references” between nodes (and the list object itself) right; “disguising”
Position; validating positions.
nullpointers; simplifying the implementation; introduction to experimental analysis (think “physics lab”); contrasting asymptotic and experimental analysis; the
jaybeeframework for benchmarking; examples (building up long strings, comparing the cost of basic integer operations).
jaybee(copying and initializing arrays, comparing Java’s
ArrayList); a bit of midterm Q&A.
Treeinterface for generic, n-ary trees; implementation options for the
Treeinterface (using lists, arrays, or parent-sibling representation, various tradeoffs).
Graphinterface, our first with two generic type parameters.
Edgeto allow better type-checking and enable overloading; returning
Iterable<Edge<E>>from methods that have many results; sparse versus dense graphs; implementation options for graphs (adjacency matrix for dense graphs, incidence lists for sparse graphs, detailed sketch of incidence list representation).
Comparator; simple priority queue implementation based on arrays; introduction to binary heaps; shape property; ordering property; implications for min/max depending on ordering relationship; inserting into binary heaps; removing from binary heaps; outline of O(log n) for both; how to map heaps into arrays.