Get Algorithms in Java THIRD EDITION pdf Robert Sedgewick free all chapters
Get Algorithms in Java THIRD EDITION pdf Robert Sedgewick free all chapters
https://ebookgate.com/product/the-java-language-specification-third-
edition-james-gosling/
ebookgate.com
https://ebookgate.com/product/java-network-programming-third-edition-
elliotte-rusty-harold/
ebookgate.com
https://ebookgate.com/product/java-closures-and-lambda-1st-edition-
robert-fischer/
ebookgate.com
Java and SOAP 1st ed Edition Robert Englander
https://ebookgate.com/product/java-and-soap-1st-ed-edition-robert-
englander/
ebookgate.com
https://ebookgate.com/product/java-enterprise-best-practices-1st-
edition-robert-eckstein/
ebookgate.com
https://ebookgate.com/product/itext-in-action-creating-and-
manipulating-pdf-1st-edition-bruno-lowagie/
ebookgate.com
https://ebookgate.com/product/java-2-micro-edition-java-in-small-
things-james-white/
ebookgate.com
https://ebookgate.com/product/comprehensive-guide-to-composites-pdf-
ebook-edition-fochtman/
ebookgate.com
Algorithms THIRD EDITION
in Java
PARTS 1–4
FUNDAMENTALS
DATA STRUCTURES
SORTING
SEARCHING
Robert Sedgewick
Princeton University
Addison-Wesley
Boston • San Francisco • New York • Toronto • Montreal
London • Munich • Paris • Madrid
Capetown • Sydney • Tokyo • Singapore • Mexico City
Many of the designations used by manufacturers and sellers to distinguish their products are claimed
as trademarks. Where those designations appear in this book and Addison-Wesley was aware of a
trademark claim, the designations have been printed in initial capital letters or all capitals.
The author and publisher have taken care in the preparation of this book, but make no expressed or
implied warranty of any kind and assume no responsibility for errors or omissions. No liability is
assumed for incidental or consequential damages in connection with or arising out of the use of the
information or programs contained herein.
The publisher offers discounts on this book when ordered in quantity for special sales. For more
information, please contact:
U. S. Corporate and Government Sales
(800) 382-3410
[email protected].
For sales outside of the United States, please contact:
International Sales
(317) 581-3793
[email protected]
Visit Addison-Wesley on the Web: www.awprofessional.com
All rights reserved. No part of this publication may be reproduced, stored in a retrieval system,
or transmitted, in any form or by any means, electronic, mechanical, photocopying, recording, or
otherwise, without the prior written permission of the publisher. Printed in the United States of
America. Published simultaneously in Canada.
For information on obtaining permission for use of material from this work, please submit a written
request to:
Pearson Education, Inc.
75 Arlington Street, Suite 300
Boston, MA 02116
Fax: (617) 848-7047
[email protected]
ISBN 0-201-36120-5
Text printed in the United States on recycled paper at Courier Stoughton in Stoughton, Massachusetts.
9th Printing February 2008
Preface
iii
PREFACE
These books are not just for programmers and computer science
students. Everyone who uses a computer wants it to run faster or to
solve larger problems. The algorithms that we consider represent a
body of knowledge developed during the last 50 years that is the basis
for the efficient use of the computer for a broad variety of applications.
From N -body simulation problems in physics to genetic-sequencing
problems in molecular biology, the basic methods described here have
become essential in scientific research; and from database systems to
Internet search engines, they have become essential parts of modern
software systems. As the scope of computer applications becomes more
widespread, so grows the impact of basic algorithms. The goal of this
book is to serve as a resource so that students and professionals can
know and make intelligent use of these fundamental algorithms as the
need arises in whatever computer application they might undertake.
Scope
This book, Algorithms in Java, Third Edition, Parts 1-4, contains 16
chapters grouped into four major parts: fundamentals, data structures,
sorting, and searching. The descriptions here are intended to give
readers an understanding of the basic properties of as broad a range
of fundamental algorithms as possible. The algorithms described here
have found widespread use for years, and represent an essential body
of knowledge for both the practicing programmer and the computer-
science student. The second volume is devoted to graph algorithms,
and the third consists of four additional parts that cover strings, geom-
etry, and advanced topics. My primary goal in developing these books
has been to bring together fundamental methods from these areas, to
provide access to the best methods known for solving problems by
computer.
You will most appreciate the material here if you have had one
or two previous courses in computer science or have had equivalent
programming experience: one course in programming in a high-level
language such as Java, C, or C++, and perhaps another course that
teaches fundamental concepts of programming systems. This book
is thus intended for anyone conversant with a modern programming
language and with the basic features of modern computer systems.
iv
References that might help to fill in gaps in your background are
suggested in the text.
Most of the mathematical material supporting the analytic results
is self-contained (or is labeled as beyond the scope of this book), so
little specific preparation in mathematics is required for the bulk of the
book, although mathematical maturity is definitely helpful.
v
PREFACE
vi
text. When appropriate, empirical and analytic results are presented
to illustrate why certain algorithms are preferred. When interesting,
the relationship of the practical algorithms being discussed to purely
theoretical results is described. Specific information on performance
characteristics of algorithms and implementations is synthesized, en-
capsulated, and discussed throughout the book.
Programming Language
The programming language used for all of the implementations is Java.
The programs use a wide range of standard Java idioms, and the text
includes concise descriptions of each construct.
Mike Schidlowsky and I developed a style of Java programming
based on abstract data types that we feel is an effective way to present
the algorithms and data structures as real programs. We have striven
for elegant, compact, efficient, and portable implementations. The
style is consistent whenever possible, so programs that are similar
look similar.
For many of the algorithms in this book, the similarities hold re-
gardless of the language: Quicksort is quicksort (to pick one prominent
example), whether expressed in Ada, Algol-60, Basic, C, C ++, Fortran,
Java, Mesa, Modula-3, Pascal, PostScript, Smalltalk, or countless other
programming languages and environments where it has proved to be
an effective sorting method. On the one hand, our code is informed by
experience with implementing algorithms in these and numerous other
languages (C and C++ versions of this book are also available); on
the other hand, some of the properties of some of these languages are
informed by their designers’ experience with some of the algorithms
and data structures that we consider in this book.
Chapter 1 constitutes a detailed example of this approach to de-
veloping efficient Java implementations of our algorithms, and Chapter
2 describes our approach to analyzing them. Chapters 3 and 4 are de-
voted to describing and justifying the basic mechanisms that we use
for data type and ADT implementations. These four chapters set the
stage for the rest of the book.
vii
PREFACE
Acknowledgments
Many people gave me helpful feedback on earlier versions of this book.
In particular, hundreds of students at Princeton and Brown have suf-
fered through preliminary drafts over the years. Special thanks are due
to Trina Avery and Tom Freeman for their help in producing the first
edition; to Janet Incerpi for her creativity and ingenuity in persuading
our early and primitive digital computerized typesetting hardware and
software to produce the first edition; to Marc Brown for his part in
the algorithm visualization research that was the genesis of so many
of the figures in the book; and to Dave Hanson and Andrew Appel
for their willingness to answer all of my questions about programming
languages. I would also like to thank the many readers who have pro-
vided me with comments about various editions, including Guy Almes,
Jon Bentley, Marc Brown, Jay Gischer, Allan Heydon, Kennedy Lemke,
Udi Manber, Dana Richards, John Reif, M. Rosenfeld, Stephen Seid-
man, Michael Quinn, and William Ward.
To produce this new edition, I have had the pleasure of working
with Peter Gordon and Helen Goldstein at Addison-Wesley, who have
patiently shepherded this project as it has evolved. It has also been
my pleasure to work with several other members of the professional
staff at Addison-Wesley. The nature of this project made the book a
somewhat unusual challenge for many of them, and I much appreciate
their forbearance. In particular, Marilyn Rash did an outstanding job
managing the book’s production within a tightly compressed schedule.
I have gained three new mentors in writing this book, and partic-
ularly want to express my appreciation to them. First, Steve Summit
carefully checked early versions of the manuscript on a technical level
and provided me with literally thousands of detailed comments, partic-
ularly on the programs. Steve clearly understood my goal of providing
elegant, efficient, and effective implementations, and his comments not
only helped me to provide a measure of consistency across the imple-
mentations, but also helped me to improve many of them substantially.
Second, Lyn Dupré also provided me with thousands of detailed com-
ments on the manuscript, which were invaluable in helping me not only
to correct and avoid grammatical errors, but also—more important—
to find a consistent and coherent writing style that helps bind together
the daunting mass of technical material here. Third, Chris Van Wyk,
viii
in a long series of spirited electronic mail exchanges, patiently de-
fended the basic precepts of object-oriented programming and helped
me develop a style of coding that exhibits the algorithms with clar-
ity and precision while still taking advantage of what object-oriented
programming has to offer. The basic approach that we developed for
the C++ version of this book has substantially influenced the Java code
here and will certainly influence future volumes in both languages (and
C as well). I am extremely grateful for the opportunity to learn from
Steve, Lyn, and Chris—their input was vital in the development of this
book.
Much of what I have written here I have learned from the teaching
and writings of Don Knuth, my advisor at Stanford. Although Don had
no direct influence on this work, his presence may be felt in the book,
for it was he who put the study of algorithms on the scientific footing
that makes a work such as this possible. My friend and colleague
Philippe Flajolet, who has been a major force in the development of
the analysis of algorithms as a mature research area, has had a similar
influence on this work.
I am deeply thankful for the support of Princeton University,
Brown University, and the Institut National de Recherche en Informa-
tique et Automatique (INRIA), where I did most of the work on the
book; and of the Institute for Defense Analyses and the Xerox Palo
Alto Research Center, where I did some work on the book while visit-
ing. Many parts of the book are dependent on research that has been
generously supported by the National Science Foundation and the Of-
fice of Naval Research. Finally, I thank Bill Bowen, Aaron Lemonick,
and Neil Rudenstine for their support in building an academic envi-
ronment at Princeton in which I was able to prepare this book, despite
my numerous other responsibilities.
Robert Sedgewick
Marly-le-Roi, France, 1983
Princeton, New Jersey, 1990, 1992
Jamestown, Rhode Island, 1997
Princeton, New Jersey, 1998, 2002
ix
PREFACE
Michael Schidlowsky
Oakland Gardens, New York, 2002
x
To Adam, Andrew, Brett, Robbie,
and especially Linda
This page intentionally left blank
Notes on Exercises
Classifying exercises is an activity fraught with peril because readers
of a book such as this come to the material with various levels of
knowledge and experience. Nonetheless, guidance is appropriate, so
many of the exercises carry one of four annotations to help you decide
how to approach them.
Exercises that test your understanding of the material are marked
with an open triangle, as follows:
! 9.57 Give the binomial queue that results when the keys E A S Y
Q U E S T I O N are inserted into an initially empty binomial queue.
Most often, such exercises relate directly to examples in the text. They
should present no special difficulty, but working them might teach you
a fact or concept that may have eluded you when you read the text.
Exercises that add new and thought-provoking information to the
material are marked with an open circle, as follows:
•• 15.29 Prove that the height of a trie built from N random bit-
strings is about 2 lg N.
xiii
These exercises are similar to questions that might be addressed in the
research literature, but the material in the book may prepare you to
enjoy trying to solve them (and perhaps succeeding).
The annotations are intended to be neutral with respect to your
programming and mathematical ability. Those exercises that require
expertise in programming or in mathematical analysis are self-evident.
All readers are encouraged to test their understanding of the algorithms
by implementing them. Still, an exercise such as this one is straight-
forward for a practicing programmer or a student in a programming
course, but may require substantial work for someone who has not
recently programmed:
1.23 Modify Program 1.4 to generate random pairs of integers
between 0 and N −1 instead of reading them from standard input,
and to loop until N − 1 union operations have been performed.
Run your program for N = 103 , 104 , 105 , and 106 and print out
the total number of edges generated for each value of N.
In a similar vein, all readers are encouraged to strive to appreciate
the analytic underpinnings of our knowledge about properties of al-
gorithms. Still, an exercise such as this one is straightforward for a
scientist or a student in a discrete mathematics course, but may require
substantial work for someone who has not recently done mathematical
analysis:
1.13 Compute the average distance from a node to the root in
a worst-case tree of 2n nodes built by the weighted quick-union
algorithm.
There are far too many exercises for you to read and assimilate
them all; my hope is that there are enough exercises here to stimulate
you to strive to come to a broader understanding on the topics that
interest you than you can glean by simply reading the text.
xiv
Contents
Fundamentals
Chapter 1. Introduction 3
1.1 Algorithms · 4
1.2 A Sample Problem: Connectivity · 7
1.3 Union–Find Algorithms · 11
1.4 Perspective · 22
1.5 Summary of Topics · 24
Data Structures
xvi
Sorting
xvii
CONTENTS
Searching
xviii
Chapter 13. Balanced Trees 555
13.1 Randomized BSTs · 559
13.2 Splay BSTs · 566
13.3 Top-Down 2-3-4 Trees · 572
13.4 Red–Black Trees · 577
13.5 Skip Lists · 587
13.6 Performance Characteristics · 595
Appendix 723
Index 727
xix
This page intentionally left blank
P A R T
O N E
Fundamentals
This page intentionally left blank
CHAPTER ONE
Introduction
3
4 §1.1 CHAPTER ONE
1.1 Algorithms
When we write a computer program, we are generally implementing
a method that has been devised previously to solve some problem.
This method is often independent of the particular computer to be
used—it is likely to be equally appropriate for many computers and
many computer languages. It is the method, rather than the computer
program itself, that we must study to learn how the problem is being
attacked. The term algorithm is used in computer science to describe
a problem-solving method suitable for implementation as a computer
program. Algorithms are the stuff of computer science: They are
central objects of study in many, if not most, areas of the field.
Most algorithms of interest involve methods of organizing the
data involved in the computation. Objects created in this way are
called data structures, and they also are central objects of study in
computer science. Thus, algorithms and data structures go hand in
hand. In this book we take the view that data structures exist as the
byproducts or end products of algorithms and that we must therefore
study them in order to understand the algorithms. Simple algorithms
can give rise to complicated data structures and, conversely, compli-
cated algorithms can use simple data structures. We shall study the
properties of many data structures in this book; indeed, the book might
well have been called Algorithms and Data Structures in Java.
INTRODUCTION §1.1 5
Figure 1.2
A large connectivity example
The objects in a connectivity prob-
lem might represent connection
points, and the pairs might be con-
nections between them, as indi-
cated in this idealized example
that might represent wires connect-
ing buildings in a city or compo-
nents on a computer chip. This
graphical representation makes it
possible for a human to spot nodes
that are not connected, but the al-
gorithm has to work with only the
pairs of integers that it is given.
Are the two nodes marked with the
large black dots connected?
that was not previously connected, answering “yes” when the counter
reaches N − 1 and “no” if it never does. This question is but one ex-
ample of a host of questions that we might wish to answer regarding
connectivity. The set of pairs in the input is called a graph, and the set
of pairs output is called a spanning tree for that graph, which connects
all the objects. We consider properties of graphs, spanning trees, and
all manner of related algorithms in Part 5.
It is worthwhile to try to identify the fundamental operations
that we will be performing, and so to make any algorithm that we
develop for the connectivity task useful for a variety of similar tasks.
Specifically, each time that an algorithm gets a new pair, it has first to
determine whether it represents a new connection, then to incorporate
the information that the connection has been seen into its understand-
ing about the connectivity of the objects such that it can check con-
nections to be seen in the future. We encapsulate these two tasks as
abstract operations by considering the integer input values to repre-
sent elements in abstract sets and then designing algorithms and data
structures that can
• Find the set containing a given item.
• Replace the sets containing two given items by their union.
Organizing our algorithms in terms of these abstract operations does
not seem to foreclose any options in solving the connectivity problem,
and the operations may be useful for solving other problems. Devel-
oping ever more powerful layers of abstraction is an essential process
in computer science in general and in algorithm design in particular,
and we shall turn to it on numerous occasions throughout this book.
In this chapter, we use abstract thinking in an informal way to guide us
in designing programs to solve the connectivity problem; in Chapter 4,
we shall see how to encapsulate abstractions in Java code.
The connectivity problem is easy to solve with the find and union
abstract operations. We read a new pair from the input and perform a
find operation for each member of the pair: If the members of the pair
are in the same set, we move on to the next pair; if they are not, we do
a union operation and write out the pair. The sets represent connected
components—subsets of the objects with the property that any two
objects in a given component are connected. This approach reduces
the development of an algorithmic solution for connectivity to the
INTRODUCTION §1.3 11
Each iteration requires at least one instruction (if only to check whether 2 3 4 5 8
ter 2.
Figure 1.4 shows a graphical representation of Figure 1.3. We 1
0 2 3 4 5 6 7 8 9
may think of some of the objects as representing the set to which they
belong, and all of the other objects as having a link to the representative
in their set. The reason for moving to this graphical representation Figure 1.4
of the array will become clear soon. Observe that the connections Tree representation of quick
between objects (links) in this representation are not necessarily the find
same as the connections in the input pairs—they are the information This figure depicts graphical repre-
sentations for the example in Fig-
that the algorithm chooses to remember to be able to know whether
ure 1.3. The connections in these
future pairs are connected. figures do not necessarily represent
The next algorithm that we consider is a complementary method the connections in the input. For
called the quick-union algorithm. It is based on the same data example, the structure at the bot-
tom has the connection 1-7, which
structure—an array indexed by object names—but it uses a differ-
is not in the input, but which is
ent interpretation of the values that leads to more complex abstract made because of the string of con-
structures. Each object has a link to another object in the same set, nections 7-3-4-9-5-6-1.
14 §1.3 CHAPTER ONE
id[i] = j; 2 9 0 1 9 4 9 6 6 7 0 9
in the quick-find trees after following just one link, whereas we might 5 6 0 1 9 4 9 6 9 9 0 0
0 1 2 3 5 6 7 8 Suppose that the input pairs come in the order 1-2, then 2-3, then
4 9 3-4, and so forth. After N − 1 such pairs, we have N objects all in the
same set, and the tree that is formed by the quick-union algorithm is
8 1 2 3 5 6 7
a straight line, with N linking to N − 1, which links to N − 2, which
0 4 9
links to N − 3, and so forth. To execute the find operation for object
8 1 3 5 6 7 N , the program has to follow N − 1 links. Thus, the average number
0 2 4 9 of links followed for the first N pairs is
8 1 3 5 7 (0 + 1 + . . . + (N − 1))/N = (N − 1)/2.
0 2 4 9 6
Now suppose that the remainder of the pairs all connect N to some
8 1 3 7 other object. The find operation for each of these pairs involves at
0 2 4 5 9 least (N − 1) links. The grand total for the M find operations for this
6 sequence of input pairs is certainly greater than M N/2.
8 1 3
Fortunately, there is an easy modification to the algorithm that
0 2 4 5 7 9 allows us to guarantee that bad cases such as this one do not occur.
6 Rather than arbitrarily connecting the second tree to the first for union,
we keep track of the number of nodes in each tree and always connect
3 1 the smaller tree to the larger. This change requires slightly more code
8 2 4 5 7 9 and another array to hold the node counts, as shown in Program 1.3,
0 6
but it leads to substantial improvements in efficiency. We refer to this
algorithm as the weighted quick-union algorithm.
3
Figure 1.7 shows the forest of trees constructed by the weighted
8 1 2 4 5 7 9
0 6
union–find algorithm for the example input in Figure 1.1. Even for
this small example, the paths in the trees are substantially shorter than
for the unweighted version in Figure 1.5. Figure 1.8 illustrates what
Figure 1.7 happens in the worst case, when the sizes of the sets to be merged in
Tree representation of
weighted quick union the union operation are always equal (and a power of 2). These tree
structures look complex, but they have the simple property that the
This sequence depicts the result
of changing the quick-union algo- maximum number of links that we need to follow to get to the root
rithm to link the root of the smaller in a tree of 2n nodes is n. Furthermore, when we merge two trees of
of the two trees to the root of the 2n nodes, we get a tree of 2n+1 nodes, and we increase the maximum
larger of the two trees. The dis-
distance to the root to n + 1. This observation generalizes to provide a
tance from each node to the root
of its tree is small, so the find oper- proof that the weighted algorithm is substantially more efficient than
ation is efficient. the unweighted algorithm.
INTRODUCTION §1.3 17
} 7
}
0
1 2 4 8
Property 1.3 The weighted quick-union algorithm follows at most 3 5 6 9
2 lg N links to determine whether two of N objects are connected. 7
We can prove that the union operation preserves the property that
the number of links followed from any node to the root in a set of Figure 1.8
k objects is no greater than lg k (we do not count the self-link at the Weighted quick union (worst
case)
root). When we combine a set of i nodes with a set of j nodes with
i ≤ j, we increase the number of links that must be followed in the The worst scenario for the weighted
quick-union algorithm is that each
smaller set by 1, but they are now in a set of size i + j, so the property union operation links trees of equal
is preserved because 1 + lg i = lg(i + i) ≤ lg(i + j). size. If the number of objects is
less than 2n , the distance from any
The practical implication of Property 1.3 is that the weighted node to the root of its tree is less
quick-union algorithm uses at most a constant times M lg N instruc- than n.
18 §1.3 CHAPTER ONE
implement than full path compression (see Exercise 1.16), and achieves 0
the same net result. We refer to this variant as weighted quick-union 1
with path compression by halving. Which of these methods is the 2
more effective? Is the savings achieved worth the extra time required 3
to implement path compression? Is there some other technique that 4
we should consider? To answer these questions, we need to look more 5
carefully at the algorithms and implementations. We shall return to this 6
topic in Chapter 2, in the context of our discussion of basic approaches 7
to the analysis of algorithms. 8
The end result of the succession of algorithms that we have con-
sidered to solve the connectivity problem is about the best that we
0
could hope for in any practical sense. We have algorithms that are
1 2
easy to implement whose running time is guaranteed to be within a
3 4
constant factor of the cost of gathering the data. Moreover, the al-
5 6
gorithms are online algorithms that consider each edge once, using
7 8
space proportional to the number of objects, so there is no limitation
on the number of edges that they can handle. The empirical studies
in Table 1.1 validate our conclusion that Program 1.3 and its path- Figure 1.10
compression variations are useful even for huge practical applications. Path compression by halving
Choosing which is the best among these algorithms requires careful We can nearly halve the length
and sophisticated analysis (see Chapter 2). of paths on the way up the tree
by taking two links at a time and
Exercises setting the bottom one to point to
the same node as the top one, as
! 1.4 Show the contents of the id array after each union operation when you shown in this example. The net
use the quick-find algorithm (Program 1.1) to solve the connectivity problem result of performing this opera-
for the sequence 0-2, 1-4, 2-5, 3-6, 0-4, 6-0, and 1-3. Also give the number tion on every path that we traverse
of times the program accesses the id array for each input pair. is asymptotically the same as full
! 1.5 Do Exercise 1.4, but use the quick-union algorithm (Program 1.2). path compression.
20 §1.3 CHAPTER ONE
N M F U W P H
1000 3819 63 53 17 18 15
2500 12263 185 159 22 19 24
5000 21591 698 697 34 33 35
10000 41140 2891 3987 85 101 74
25000 162748 237 267 267
50000 279279 447 533 473
100000 676113 1382 1238 1174
Key:
F quick find (Program 1.1)
U quick union (Program 1.2)
W weighted quick union (Program 1.3)
P weighted quick union with path compression (Exercise 1.16)
H weighted quick union with halving (Program 1.4)
! 1.6 Give the contents of the id array after each union operation for the
weighted quick-union algorithm running on the examples corresponding to
Figure 1.7 and Figure 1.8.
! 1.7 Do Exercise 1.4, but use the weighted quick-union algorithm (Pro-
gram 1.3).
! 1.8 Do Exercise 1.4, but use the weighted quick-union algorithm with path
compression by halving (Program 1.4).
1.9 Prove an upper bound on the number of machine instructions required
to process M connections on N objects using Program 1.3. You may assume,
for example, that any Java assignment statement always requires less than c
instructions, for some fixed constant c.
INTRODUCTION §1.3 21
Figure 1.11
1.10 Estimate the minimum amount of time (in days) that would be required
9 6 A large example of the ef-
for quick find (Program 1.1) to solve a problem with 10 objects and 10 input
fect of path compression
pairs, on a computer capable of executing 109 instructions per second. Assume
that each iteration of the inner for loop requires at least 10 instructions. This sequence depicts the result of
processing random pairs from 100
1.11 Estimate the maximum amount of time (in seconds) that would be objects with the weighted quick-
required for weighted quick union (Program 1.3) to solve a problem with union algorithm with path com-
109 objects and 106 input pairs, on a computer capable of executing 109 pression. All but two of the nodes
instructions per second. Assume that each iteration of the outer for loop in the tree are one or two steps
requires at most 100 instructions. from the root.
1.12 Compute the average distance from a node to the root in a worst-case
tree of 2n nodes built by the weighted quick-union algorithm.
! 1.13 Draw a diagram like Figure 1.10, starting with eight nodes instead of
nine.
◦ 1.14 Give a sequence of input pairs that causes the weighted quick-union
algorithm (Program 1.3) to produce a path of length 4.
• 1.15 Give a sequence of input pairs that causes the weighted quick-union
algorithm with path compression by halving (Program 1.4) to produce a path
of length 4.
1.16 Show how to modify Program 1.3 to implement full path compression,
where we complete each union operation by making every node that we touch
link to the root of the new tree.
! 1.17 Answer Exercise 1.4, but use the weighted quick-union algorithm with
full path compression (Exercise 1.16).
•• 1.18 Give a sequence of input pairs that causes the weighted quick-union
algorithm with full path compression (Exercise 1.16) to produce a path of
length 4.
◦ 1.19 Give an example showing that modifying quick union (Program 1.2) to
implement full path compression (see Exercise 1.16) is not sufficient to ensure
that the trees have no long paths.
• 1.20 Modify Program 1.3 to use the height of the trees (longest path from any
node to the root), instead of the weight, to decide whether to set id[i] = j or
id[j] = i. Run empirical studies to compare this variant with Program 1.3.
•• 1.21 Show that Property 1.3 holds for the algorithm described in Exer-
cise 1.20.
• 1.22 Modify Program 1.4 to generate random pairs of integers between 0
and N −1 instead of reading them from standard input, and to loop until N −1
22 §1.4 CHAPTER ONE
union operations have been performed. Run your program for N = 103 , 104 ,
105 , and 106 , and print out the total number of edges generated for each value
of N.
• 1.23 Modify your program from Exercise 1.22 to plot the number of edges
needed to connect N items, for 100 ≤ N ≤ 1000.
•• 1.24 Give an approximate formula for the number of random edges that are
required to connect N objects, as a function of N.
1.4 Perspective
Each of the algorithms that we considered in Section 1.3 seems to
be an improvement over the previous in some intuitive sense, but the
process is perhaps artificially smooth because we have the benefit of
hindsight in looking over the development of the algorithms as they
were studied by researchers over the years (see reference section). The
implementations are simple and the problem is well specified, so we can
evaluate the various algorithms directly by running empirical studies.
Furthermore, we can validate these studies and quantify the compar-
ative performance of these algorithms (see Chapter 2). Not all the
problem domains in this book are as well developed as this one, and
we certainly can run into complex algorithms that are difficult to com-
pare and mathematical problems that are difficult to solve. We strive to
make objective scientific judgements about the algorithms that we use,
while gaining experience learning the properties of implementations
running on actual data from applications or random test data.
The process is prototypical of the way that we consider various
algorithms for fundamental problems throughout the book. When
possible, we follow the same basic steps that we took for union–find
algorithms in Section 1.2, some of which are highlighted in this list:
• Decide on a complete and specific problem statement, including
identifying fundamental abstract operations that are intrinsic to
the problem.
• Carefully develop a succinct implementation for a straightfor-
ward algorithm.
• Develop improved implementations through a process of step-
wise refinement, validating the efficacy of ideas for improvement
through empirical analysis, mathematical analysis, or both.
INTRODUCTION §1.4 23
Our website is not just a platform for buying books, but a bridge
connecting readers to the timeless values of culture and wisdom. With
an elegant, user-friendly interface and an intelligent search system,
we are committed to providing a quick and convenient shopping
experience. Additionally, our special promotions and home delivery
services ensure that you save time and fully enjoy the joy of reading.
ebookgate.com