understanding and defining the problem to be solved, managing its complexity, and decomposing it
into smaller subtasks that can be implemented easily. Often, many of the algorithms required after the
decomposition are trivial to implement. In most cases, however, there are a few algorithms whose
choice is critical because most of the system resources will be spent running those algorithms. These
are the types of algorithms on which we concentrate in this book. We study fundamental algorithms
that are useful for solving challenging problems in a broad variety of applications areas.
The sharing of programs in computer systems is becoming more widespread, so although we might
expect to be using a large fraction of the algorithms in this book, we also might expect to have to
implement only a small fraction of them. For example, the Java libraries contain implementations of a
host of fundamental algorithms. However, implementing simple versions of basic algorithms helps us
to understand them better and thus to more effectively use and tune advanced versions from a library.
More important, the opportunity to reimplement basic algorithms arises frequently. The primary
reason to do so is that we are faced, all too often, with completely new computing environments
(hardware and software) with new features that old implementations may not use to best advantage. In
this book, we concentrate on the simplest reasonable implementations of the best algorithms. We do
pay careful attention to coding the critical parts of the algorithms, and take pains to note where low-
level optimization effort could be most beneficial.
The choice of the best algorithm for a particular task can be a complicated process, perhaps involving
sophisticated mathematical analysis. The branch of computer science that comprises the study of such
questions is called analysis of algorithms. Many of the algorithms that we study have been shown
through analysis to have excellent theoretical performance; others are simply known to work well
through experience. Our primary goal is to learn reasonable algorithms for important tasks, yet we
shall also pay careful attention to comparative performance of the methods. We should not use an
algorithm without having an idea of what resources it might consume, so we strive to be aware of
how our algorithms might be expected to perform.
Summary of topics
As an overview, we describe the major parts of the book, giving specific topics covered and an
indication of our general orientation toward the material. This set of topics is intended to touch on as
many fundamental algorithms as possible. Some of the areas covered are core computer-science areas
that we study in depth to learn basic algorithms of wide applicability. Other algorithms that we
discuss are from advanced fields of study within computer science and related fields. The algorithms
that we consider are the products of decades of research and development and continue to play an
essential role in the ever-expanding applications of computation.
Fundamentals (CHAPTER 1) in the context of this book are the basic principles and methodology that
we use to implement, analyze, and compare algorithms. We consider our Java programming model,
data abstraction, basic data structures, abstract data types for collections, methods of analyzing
algorithm performance, and a case study.
Sorting algorithms (CHAPTER 2) for rearranging arrays in order are of fundamental importance. We
consider a variety of algorithms in considerable depth, including insertion sort, selection sort,
shellsort, quicksort, mergesort, and heapsort. We also encounter algorithms for several related
problems, including priority queues, selection, and merging. Many of these algorithms will find
application as the basis for other algorithms later in the book.