Skip to main content
main-content
Top

About this book

This newly expanded and updated second edition of the best-selling classic continues to take the "mystery" out of designing algorithms, and analyzing their efficacy and efficiency. Expanding on the first edition, the book now serves as the primary textbook of choice for algorithm design courses while maintaining its status as the premier practical reference guide to algorithms for programmers, researchers, and students.

The reader-friendly Algorithm Design Manual provides straightforward access to combinatorial algorithms technology, stressing design over analysis. The first part, Techniques, provides accessible instruction on methods for designing and analyzing computer algorithms. The second part, Resources, is intended for browsing and reference, and comprises the catalog of algorithmic resources, implementations and an extensive bibliography.

NEW to the second edition:

• Doubles the tutorial material and exercises over the first edition

• Provides full online support for lecturers, and a completely updated and improved website component with lecture slides, audio and video

• Contains a unique catalog identifying the 75 algorithmic problems that arise most often in practice, leading the reader down the right path to solve them

• Includes several NEW "war stories" relating experiences from real-world applications

• Provides up-to-date links leading to the very best algorithm implementations available in C, C++, and Java

Table of Contents

Practical Algorithm Design

Frontmatter

1. Introduction to Algorithm Design

Abstract
What is an algorithm? An algorithm is a procedure to accomplish a specific task. An algorithm is the idea behind any reasonable computer program.
To be interesting, an algorithm must solve a general, well-specifiedem problem. An algorithmic problem is specified by describing the complete set of instances it must work on and of its output after running on one of these instances. This distinction, between a problem and an instance of a problem, is fundamental.
Steven S. Skiena

2. Algorithm Analysis

Abstract
Algorithms are the most important and durable part of computer science because they can be studied in a language- and machine-independent way. This means that we need techniques that enable us to compare the efficiency of algorithms without implementing them. Our two most important tools are (1) the RAM model of computation and (2) the asymptotic analysis of worst-case complexity.
Steven S. Skiena

3. Data Structures

Abstract
Changing a data structure in a slow program can work the same way an organ transplant does in a sick patient. Important classes of abstract data types such as containers, dictionaries, and priority queues, have many different but functionally equivalent data structures that implement them. Changing the data structure does not change the correctness of the program, since we presumably replace a correct implementation with a different correct implementation. However, the new implementation of the data type realizes different tradeoffs in the time to execute various operations, so the total performance can improve dramatically. Like a patient in need of a transplant, only one part might need to be replaced in order to fix the problem.
Steven S. Skiena

4. Sorting and Searching

Abstract
Typical computer science students study the basic sorting algorithms at least three times before they graduate:first in introductory programming,then in data structures, and finally in their algorithms course.
Steven S. Skiena

5. Graph Traversal

Abstract
Graphs are one of the unifying themes of computer science—an abstract representation that describes the organization of transportation systems, human interactions, and telecommunication networks. That so many different structures can be modeled using a single formalism is a source of great power to the educated programmer.
Steven S. Skiena

6. Weighted Graph Algorithms

Abstract
The data structures and traversal algorithms of Chapter 5 provide the basic building blocks for any computation on graphs. However, all the algorithms presented there dealt with unweighted graphs—i.e., graphs where each edge has identical value or weight.
There is an alternate universe of problems for weighted graphs. The edges of road networks are naturally bound to numerical values such as construction cost, traversal time, length, or speed limit. Identifying the shortest path in such graphs proves more complicated than breadth-first search in unweighted graphs, but opens the door to a wide range of applications.
Steven S. Skiena

7. Combinatorial Search and Heuristic Methods

Abstract
We can solve many problems to optimality using exhaustive search techniques, although the time complexity can be enormous. For certain applications, it may pay to spend extra time to be certain of the optimal solution. A good example occurs in testing a circuit or a program on all possible inputs. You can prove the correctness of the device by trying all possible inputs and verifying that they give the correct answer. Verifying correctness is a property to be proud of.However, claiming that it works correctly on all the inputs you tried is worth much less.
Steven S. Skiena

8. Dynamic Programming

Abstract
The most challenging algorithmic problems involve optimization, where we seek to find a solution that maximizes or minimizes some function. Traveling salesman is a classic optimization problem, where we seek the tour visiting all vertices of a graph at minimum total cost. But as shown in Chapter 1, it is easy to propose “algorithms” solving TSP that generate reasonable-looking solutions but did not always produce the minimum cost tour.
Steven S. Skiena

9. Intractable Problems and Approximation Algorithms

Abstract
We now introduce techniques for proving that no efficient algorithm exists for a given problem. The practical reader is probably squirming at the notion of proving anything, and will be particularly alarmed at the idea of investing time to prove that something does not exist. Why are you better off knowing that something you don’t know how to do in fact can’t be done at all?
Steven S. Skiena

10. How to Design Algorithms

Abstract
Designing the right algorithm for a given application is a major creative act—that of taking a problem and pulling a solution out of the ether. The space of choices you can make in algorithm design is enormous, leaving you plenty of freedom to hang yourself.
This book is designed to make you a better algorithm designer. The techniques presented in Part I of this book provide the basic ideas underlying all combinatorial algorithms. The problem catalog of Part II will help you with modeling your application, and tell you what is known about the relevant problems. However, being a successful algorithm designer requires more than book knowledge. It requires a certain attitude—the right problem-solving approach. It is difficult to teach this mindset in a book, yet getting it is essential to becoming a successful designer.
Steven S. Skiena

The Hitchhiker’s Guide to Algorithms

Frontmatter

11. A Catalog of Algorithmic Problems

Abstract
This is a catalog of algorithmic problems that arise commonly in practice.It describes what is known about them and gives suggestions about how best to proceed if the problem arises in your application.
What is the best way to use this catalog? First, think about your problem. If you recall the name, look up the catalog entry in the index or table of contents and start reading. Read through the entire entry, since it contains pointers to other relevant problems. Leaf through the catalog, looking at the pictures and problem names to see if something strikes a chord. Don’t be afraid to use the index, for every problem in the book is listed there under several possible keywords and applications. If you still don’t find something relevant, your problem is either not suitable for attack by combinatorial algorithms or else you don’t fully understand it. In either case, go back to step one.
Steven S. Skiena

12. Data Structures

Abstract
Data structures are not so much algorithms as they are the fundamental constructs around which you build your application. Becoming fluent in what the standard data structures can do for you is essential to get full value from them.
This puts data structures slightly out of sync with the rest of the catalog. Perhaps the most useful aspect of it will be the pointers to various implementations and data structure libraries. Many of these data structures are nontrivial to implement well, so the programs we point to will be useful as models even if they do not do exactly what you need. Certain fundamental data structures, like kd-trees and suffix trees, are not as well known as they should be. Hopefully, this catalog will serve to better publicize them.
Steven S. Skiena

13. Numerical Problems

Abstract
If most problems you encounter are numerical in nature,there is an excellent chance that you are reading the wrong book. Numerical Recipes [PFTV07] gives a terrific overview to the fundamental problems in numerical computing, including linear algebra, numerical integration, statistics, and differential equations.Different flavors of the book include source code for all the algorithms in C++, Fortran, and even Pascal.
Steven S. Skiena

14. Combinatorial Problems

Abstract
We now consider several algorithmic problems of a purely combinatorial nature. These include sorting and permutation generations, both of which were among the first non-numerical problems arising on electronic computers. Sorting can be viewed as identifying or imposing a total order on the keys, while searching and selection involve identifying specific keys based on their position in this total order.
Steven S. Skiena

15. Graph Problems: Polynomial-Time

Abstract
Algorithmic graph problems constitute approximately one third of the problems in this catalog. Problems from other sections could have been formulated equally well in terms of graphs, such as bandwidth minimization and finite-state automata optimization. Identifying the name of a graph-theoretic invariant or problem is one of the primary skills of a good algorist. Indeed, the catalog will tell you exactly how to proceed as soon as you figure out your particular problem’s name.
In this section, we deal only with problems for which there are efficient algorithms to solve them. As there is often more than one way to model a given application, it makes sense to look here before proceeding on to the harder formulations.
Steven S. Skiena

16. Graph Problems: Hard Problems

Abstract
A cynical view of graph algorithms is that “everything we want to do is hard.”Indeed, no polynomial-time algorithms are known for any of the problems in this section.All of them are provably NP-complete with the exception of graph isomorphism—whose complexity status remains an open question.
The theory of NP-completeness demonstrates that all NP-complete problems must have polynomial-time algorithms if any one of them does. This prospect is sufficiently preposterous that an NP-completeness reduction suffices as de facto proof that no efficient algorithm exists to solve the given problem.
Still, do not abandon hope if your problem resides in this chapter. We provide a recommended line of attack for each problem, be it combinatorial search, heuristics, approximation algorithms, or algorithms for restricted instances. Hard problems require a different methodology to work with than polynomial-time problems, but with care they can usually be dealt with successfully.
Steven S. Skiena

17. Computational Geometry

Abstract
Computational geometry is the algorithmic study of geometric problems. Its emergence coincided with application areas such as computer graphics, computer-aided design/manufacturing, and scientific computing, which together provide much of the motivation for geometric computing. The past twenty years have seen enormous maturity in computational geometry, resulting in a significant body of useful algorithms, software, textbooks, and research results.
Steven S. Skiena

18. Set and String Problems

Abstract
Sets and strings both represent collections of objects—the difference is whether order matters.Sets are collections of symbols whose order is assumed to carry no significance, while strings are defined by the sequence or arrangement of symbols.
The assumption of a fixed order makes it possible to solve string problems much more efficiently than set problems, through techniques such as dynamic programming and advanced data structures like suffix trees. The interest in and importance of string-processing algorithms have been increasing due to bioinformatics, Web searches, and other text-processing applications.
Steven S. Skiena

19. Algorithmic Resources

Abstract
This chapter briefly describes resources that the practical algorithm designer should be familiar with. Although some of this information has appeared elsewhere in the catalog, the most important pointers are collected here for general reference.
Steven S. Skiena
Additional information