Outline
- exam review
- generic types
- databases
- iterators
- invariants
- queues
- binary search
- binary trees
- binary search trees
- tree traversal
- runtime analysis
- ability to implement needed methods
- recursion
exam review
- format similar to last exam
- material from lecture notes (including in-class exercises),
book, assignments, quizzes
generic types
- used to parametrize a container class
- used when the exact class provided doesn't matter
- generic type can be specified to extend an interface, e.g.
java.lang.Comparable
- allows methods from that generic class
(toString, compareTo) to be used
- works well with nodes and individual data fields
- harder to use with arrays
databases
- permanent storage for a collection of data
- in this class,
- read from file at start of program
- copy kept in memory
- saved to file whenever memory copy modified
- more sophisticated databases may not have an in-memory copy
of all the data
- comma-separated or space-separated values on a line form an entry
- format should be the same for each line
iterators
- visit each element of a collection class
-
hasNext(),
next(), and the optional method
remove()
- semantic uncertainty: what happens if the program modifies
the collection in-between calls to next()?
- answer: behavior is implementation-dependent
- iterator implementation:
- create a data structure to hold or refer to all
the elements of the collection
hasNext() and
next() can traverse this data structure
-
remove(), if implemented, must remove the items from the
underlying collection
tree traversal
- depth-first:
- pre-order: node, left subtree, right subtree
- in-order: left subtree, node, right subtree
- post-order: left subtree, right subtree, node
in each case, this is a recursive definition
- breadth-first: node, then its siblings, then their children in order
- a tree structure might provide three or more different iterators
- pre-order, post-order, and breadth-first work well even on trees that
are not binary trees (inorder doesn't)
invariants
- invariants are
assertions that the programmer makes about the state of
the world before and after execution of each method
- invariants must be established by constructors
- invariants must be maintained by other methods
- everyone uses invariants, but good programmers make
them explicit when appropriate
queues
- First-In First-Out data structures
- two main implementations:
- circular linked list: pointer to last node in queue
- fixed-size circular array: start index, end index, arithmetic
modulo the queue size
- main operations are constant time
binary search
- searching in a sorted array
- guaranteed logarithmic time
- look in the middle,
- select left or right half,
- and repeat until found or guaranteed not found
- recursive or iterative implementation
binary trees
- tree nomenclature: root, parent, child, subtree, ancestor, descendant,
depth, height, etc
- each node has zero, one, or two children/subtrees
- balanced trees: height of each subtree differs by no more than one
- complete binary trees: all nodes on last level are at the left,
all other leaves are on the previous level
- perfect binary trees: 2height-1 nodes
if tree height is height)
- most operations are O(height)
binary search trees
- binary trees where all values in left subtree are less than value
in root, all values in right subtree are greater than value in root
- finding value is easy
runtime analysis
- constant time: queue insertion and deletion, linked list insertion
or deletion at the front
- log time if doubling the size of the problem increases the time by one:
balanced tree insertion, deletion, find
- linear time: ordered linked list insertion or deletion, worst case
tree insertion, deletion, or find
implementation
- exam questions may expect you to be able to implement
methods covered in class, such as from classes:
- if this is asked, a description of the method would be given
- you may have to come up with the method return type and
parameters. This is especially important for recursive methods
recursion
- recursion is natural when the data structure definition is
recursive, e.g. with linked lists and trees
- with recursion, always pay attention to the parameters
to the method and to the return type of the method
- as long as the base cases are reached eventually, can
assume that the recursive invocations will produce the correct
results
- very powerful when the problem is recursive, simply a replacement for
iteration otherwise