Course Description and Objectives 
At the heart of computer science is the
development of efficient algorithms for solving problems. This
course focuses on the design and analysis of algorithms, addressing
common algorithmic approaches (iterative, recursive,
divideandconquer, greedy, backtracking, branchandbound, dynamic
programming) as well as topics such as correctness, efficiency,
complexity, and NPcompleteness.
The choice of data structures used to implement an algorithm can
have a significant impact on the simplicity and efficiency of a
program, so data structures will also be considered. This course
continues the study of data structures begun in CPSC 225, with a
focus on hashtables, heaps, balanced binary trees, graphs, and
building your own data structure for a particular application.
The course has three main goals (and several subgoals):
 developing the skill of analyzing a problem and creating
an efficient and provably correct solution to that problem, which
includes:
 gaining a
working knowledge of algorithmic efficiency, to inform
the algorithm and
programdesign process by providing a basis for comparing solutions and
defining good solutions
 developing a toolbox of known data structures and algorithmic strategies
which can be used to solve many common problems
 developing the knowledge of
how to think about algorithms and data structures, for when a
"canned" data structure or algorithm might not be sufficient
 fostering an appreciation for the practical value of studying
algorithms and data structures
 developing other skills useful in computer science: abstract
thinking, comfort with the idea of tradeoffs, and a habit of critical
reflection
By the end of the course, the successful student should be able to:
 describe and discuss different ways in which the efficiency of an
algorithm can be determined
 define bigOh notation
 discuss the pros and cons of asymptotic measures (bigOh) and
experimental measures of algorithm efficiency
 define the difference between best case, worst case, and average
case running time/space
 determine the (best, worst, average) running time/space of an
iterative or recursive algorithm
 arrange algorithms from fast to slow based on their asymptotic
running times
 define: iterative algorithm, recursive algorithm,
divideandconquer, greedy, recursive backtracking,
branchandbound, dynamic
programming
 give examples of algorithms utilizing each approach
 for each approach, identify the problem characteristics that make
that approach suitable
 identify the steps for developing algorithms of each type
 develop algorithms for a new problem using suitable approach(es)
 convincingly justify the correctness of the resulting algorithm
 identify the key properties and typical operations of each ADT
 give examples of applications of each ADT
 match the needs of the problem to an appropriate ADT
 compare and contrast the time and spaceefficiency of
different implementations of ADTs
and discuss situations in which each implementation is most appropriate
 define and implement basic graph algorithms (e.g. depthfirst
search, breadthfirst search, topological sort, shortest path),
determine their running times, and discuss their applications
 define P, NP, NPhard, and NPcomplete and give examples of
relevant problems
 describe several important NPcomplete problems (e.g. 3SAT,
vertex cover, clique, knapsack, TSP)
 discuss and apply algorithmic strategies (e.g. backtracking,
branchandbound) for dealing with NPcomplete problems

Prerequisites 
CPSC 225 is required. Programming in this
course will be done in Java, and students are expected to be able to
write a program from pseudocode or a description of an algorithm. Also
expected is familiarity with basic abstract data types (lists, stacks,
queues, and binary trees), how those data types are implemented (using
arrays, linked lists, and linked structures), and recursion.
CPSC 229 is recommended. The most relevant topics from 229 are
the idea of a formal mathematical proof, and specific proof techniques
such as induction and proof by contradiction. Topics such as finite
automata, contextfree grammars, and some notions of computability may
also make an appearance. All of these topics will be introduced as
needed, but prior exposure is helpful.

Software 
Projects will involve programming in Java. The
Eclipse development environment is recommended, but not required.
Java 8 and Eclipse are available on the computers in two labs:
Rosenberg 009 and the Math/CS lab (Lansing 310).
If you wish to program on your own computer, the following will be useful:

Java. If you do not already have a Java development
kit (JDK) installed on your computer (or have a version older than
Java 8), you can download
it here.
Use the "JDK" link (not "Server JRE" or "JRE"), then look for the
"Java SE Development Kit" link appropriate for your computer (Mac OS
X, Windows, or Linux).

Eclipse. You
can download the Eclipse
installer here  choose
the appropriate version for your computer (Mac OS X, Windows, or
Linux) and select "Eclipse IDE for Java Developers" when the installer
prompts you for what you want to install.

A file transfer program such as Fugu (Mac)
or WinSCP (Windows) so you can copy files between your Linux
account and your computer. Follow the
directions here
to download, install, and use the appropriate program for your
computer.
Eclipse projects store some environmentspecific configuration
information and Eclipse does some management of the workspace
directory on its own, so your best bet is to copy the project folder
somewhere other than into your workspace, create a new project within
Eclipse on the current computer (if you don't already have one for
this program), and then import the source files from the copied folder
to the new project via Eclipse. It's a bit awkward, so stop by if you
need help with this.
