This section comprises brief descriptions of the major parts of the tutorial, 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, such as numerical analysis and operations research—in these cases, our treatment serves as an introduction to these fields through examination of basic methods.
The first four parts of the tutorial, which are contained in this volume, cover the most widely used set of algorithms and data structures, a first level of abstraction for collections of objects with keys that can support a broad variety of important fundamental algorithms. 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 apps of computation.
Fundamentals (Part I) in the context of this tutorial are the basic principles and methodology that we use to implement, analyze, and compare algorithms. The material in motivates our study of algorithm design and analysis; in , we consider basic methods of obtaining quantitative information about the performance of algorithms.
Data Structures (Part II) go hand-in-hand with algorithms: We shall develop a thorough understanding of data representation methods for use throughout the rest of the tutorial. We begin with an introduction to basic concrete data structures in , including arrays, linked lists, and strings. In , we consider fundamental abstract data types (ADTs) such as stacks and queues, including implementations using elementary data structures. Then in we consider recursive programs and data structures, in particular trees and algorithms for manipulating them.
Sorting algorithms (Part III) for rearranging files into order are of fundamental importance. We consider a variety of algorithms in considerable depth, including shellsort, quicksort, mergesort, heapsort, and radix sorts. We shall encounter algorithms for several related problems, including priority queues, selection, and merging. Many of these algorithms will find app as the basis for other algorithms later in the tutorial.
Searching algorithms (Part IV) for finding specific items among large collections of items are also of fundamental importance. We discuss basic and advanced methods for searching using trees and digital key transformations, including binary search trees, balanced trees, hashing, digital search trees and tries, and methods appropriate for huge files. We note relationships among these methods, comparative performance statistics, and correspondences to sorting methods.
Parts 5 through 8, which are contained in two separate volumes (one for Part 5, another for Parts 6 through 8), cover advanced apps of the algorithms described here for a diverse set of apps—a second level of abstractions specific to a number of important apps areas. We also delve more deeply into techniques of algorithm design and analysis. Many of the problems that we touch on are the subject of ongoing research.
Graph Algorithms (Part 5) are useful for a variety of difficult and important problems. A general strategy for searching in graphs is developed and applied to fundamental connectivity problems, including shortest path, minimum spanning tree, network flow, and matching. A unified treatment of these algorithms shows that they are all based on the same procedure (which depends on the basic priority queue ADT). We also show the broad applicability of graph-processing algorithms by considering general problem-solving models such as the mincost flow problem and the concept of reducing one problem to another.
String Processing algorithms (Part 6) include a range of methods for processing (long) sequences of characters. String searching leads to pattern matching, which leads to parsing. File-compression techniques are also considered. Again, an introduction to advanced topics is given through treatment of some elementary problems that are important in their own right.
Geometric Algorithms (Part 7) are methods for solving problems involving points and lines (and other simple geometric objects) that have found a multitude of apps. We consider algorithms for finding the convex hull of a set of points, for finding intersections among geometric objects, for solving closest-point problems, and for multidimensional searching. Many of these methods nicely complement the more elementary sorting and searching methods.
Advanced Topics (Part 8) are discussed for the purpose of relating the material in the tutorial to several other advanced fields of study. We begin with major approaches to the design and analysis of algorithms, including divide-and-conquer, dynamic programming, randomization, and amortization. We survey linear programming, the fast Fourier transform, NP-completeness, and other advanced topics from an introductory viewpoint to gain appreciation for the interesting advanced fields of study suggested by the elementary problems confronted in this tutorial.
The study of algorithms is interesting because it is a new field (almost all the algorithms that we study are less than 50 years old, and some were just recently discovered) with a rich tradition (a few algorithms have been known for thousands of years). New discoveries are constantly being made, but few algorithms are completely understood. In this tutorial we shall consider intricate, complicated, and difficult algorithms as well as elegant, simple, and easy algorithms. Our challenge is to understand the former and to appreciate the latter in the context of many different potential apps. In doing so, we shall explore a variety of useful tools and develop a style of algorithmic thinking that will serve us well in computational challenges to come.