100% found this document useful (2 votes)
98 views

Get Algorithms in Java THIRD EDITION pdf Robert Sedgewick free all chapters

Algorithms

Uploaded by

adamotandihw
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (2 votes)
98 views

Get Algorithms in Java THIRD EDITION pdf Robert Sedgewick free all chapters

Algorithms

Uploaded by

adamotandihw
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 81

Visit https://ebookgate.

com to download the full version and


explore more ebooks

Algorithms in Java THIRD EDITION pdf Robert


Sedgewick

_____ Click the link below to download _____


https://ebookgate.com/product/algorithms-in-java-third-
edition-pdf-robert-sedgewick/

Explore and download more ebooks at ebookgate.com


Here are some recommended products that might interest you.
You can download now and explore!

The Java Language Specification Third Edition James


Gosling

https://ebookgate.com/product/the-java-language-specification-third-
edition-james-gosling/

ebookgate.com

Java Network Programming Third Edition Elliotte Rusty


Harold

https://ebookgate.com/product/java-network-programming-third-edition-
elliotte-rusty-harold/

ebookgate.com

Data structures and algorithms made easy in Java data


structure and algorithmic puzzles 2nd Edition Narasimha
Karumanchi
https://ebookgate.com/product/data-structures-and-algorithms-made-
easy-in-java-data-structure-and-algorithmic-puzzles-2nd-edition-
narasimha-karumanchi/
ebookgate.com

Java Closures and Lambda 1st Edition Robert Fischer

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

Java Enterprise Best Practices 1st Edition Robert Eckstein

https://ebookgate.com/product/java-enterprise-best-practices-1st-
edition-robert-eckstein/

ebookgate.com

iText in Action Creating and Manipulating PDF 1st Edition


Bruno Lowagie

https://ebookgate.com/product/itext-in-action-creating-and-
manipulating-pdf-1st-edition-bruno-lowagie/

ebookgate.com

Java 2 micro edition Java in small things James White

https://ebookgate.com/product/java-2-micro-edition-java-in-small-
things-james-white/

ebookgate.com

Comprehensive Guide to Composites PDF eBook edition


Fochtman

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

Library of Congress Cataloging-in-Publication Data


Sedgewick, Robert, 1946 –
Algorithms in Java / Robert Sedgewick. — 3d ed.
p. cm.
ISBN 0-201-36120-5 (alk. paper)
Includes bibliographical references and index.
Contents: v. 1, pts. 1–4. Fundamentals, data structures, sorting, searching.
1. Java (Computer program language) 2. Computer algorithms.
I. Title.
QA76.73.C15S 2003
005.13’3—dc20 92-901
CIP

c 2003 by Pearson Education, Inc.


Copyright !

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

T HIS BOOK IS the first of three volumes that are intended to


survey the most important computer algorithms in use today.
This first volume (Parts 1–4) covers fundamental concepts (Part 1),
data structures (Part 2), sorting algorithms (Part 3), and searching
algorithms (Part 4); the second volume (Part 5) covers graphs and
graph algorithms; and the (yet to be published) third volume (Parts
6–8) covers strings (Part 6), computational geometry (Part 7), and
advanced algorithms and applications (Part 8).
The books are useful as texts early in the computer science cur-
riculum, after students have acquired basic programming skills and
familiarity with computer systems, but before they have taken spe-
cialized courses in advanced areas of computer science or computer
applications. The books also are useful for self-study or as a refer-
ence for people engaged in the development of computer systems or
applications programs because they contain implementations of useful
algorithms and detailed information on these algorithms’ performance
characteristics. The broad perspective taken makes the series an ap-
propriate introduction to the field.
Together the three volumes comprise the Third Edition of a book
that has been widely used by students and programmers around the
world for many years. I have completely rewritten the text for this
edition, and I have added thousands of new exercises, hundreds of
new figures, dozens of new programs, and detailed commentary on all
the figures and programs. This new material provides both coverage of
new topics and fuller explanations of many of the classic algorithms. A
new emphasis on abstract data types throughout the books makes the
programs more broadly useful and relevant in modern object-oriented
programming environments. People who have read previous editions
will find a wealth of new information throughout; all readers will
find a wealth of pedagogical material that provides effective access to
essential concepts.

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.

Use in the Curriculum


There is a great deal of flexibility in how the material here can be
taught, depending on the taste of the instructor and the preparation
of the students. There is sufficient coverage of basic material for the
book to be used to teach data structures to beginners, and there is
sufficient detail and coverage of advanced material for the book to
be used to teach the design and analysis of algorithms to upper-level
students. Some instructors may wish to emphasize implementations
and practical concerns; others may wish to emphasize analysis and
theoretical concepts.
An elementary course on data structures and algorithms might
emphasize the basic data structures in Part 2 and their use in the
implementations in Parts 3 and 4. A course on design and analysis of
algorithms might emphasize the fundamental material in Part 1 and
Chapter 5, then study the ways in which the algorithms in Parts 3
and 4 achieve good asymptotic performance. A course on software
engineering might omit the mathematical and advanced algorithmic
material, and emphasize how to integrate the implementations given
here into large programs or systems. A course on algorithms might
take a survey approach and introduce concepts from all these areas.
Earlier editions of this book that are based on other programming
languages have been used at scores of colleges and universities as a text
for the second or third course in computer science and as supplemental
reading for other courses. At Princeton, our experience has been that
the breadth of coverage of material in this book provides our majors
with an introduction to computer science that can be expanded on
in later courses on analysis of algorithms, systems programming, and
theoretical computer science, while providing the growing group of
students from other disciplines with a large set of techniques that these
people can put to good use immediately.

v
PREFACE

The exercises—nearly all of which are new to this third edition—


fall into several types. Some are intended to test understanding of ma-
terial in the text, and simply ask readers to work through an example
or to apply concepts described in the text. Others involve implement-
ing and putting together the algorithms, or running empirical studies
to compare variants of the algorithms and to learn their properties.
Still others are a repository for important information at a level of
detail that is not appropriate for the text. Reading and thinking about
the exercises will pay dividends for every reader.

Algorithms of Practical Use


Anyone wanting to use a computer more effectively can use this book
for reference or for self-study. People with programming experience
can find information on specific topics throughout the book. To a large
extent, you can read the individual chapters in the book independently
of the others, although, in some cases, algorithms in one chapter make
use of methods from a previous chapter.
The orientation of the book is to study algorithms likely to be of
practical use. The book provides information about the tools of the
trade to the point that readers can confidently implement, debug, and
put algorithms to work to solve a problem or to provide functionality
in an application. Full implementations of the methods discussed are
included, as are descriptions of the operations of these programs on a
consistent set of examples.
Because we work with real code, rather than write pseudo-code,
you can put the programs to practical use quickly. Program listings
are available from the book’s home page. You can use these working
programs in many ways to help you study algorithms. Read them
to check your understanding of the details of an algorithm, or to
see one way to handle initializations, boundary conditions, and other
awkward situations that often pose programming challenges. Run
them to see the algorithms in action, to study performance empirically
and check your results against the tables in the book, or to try your
own modifications.
Characteristics of the algorithms and of the situations in which
they might be useful are discussed in detail. Connections to the analysis
of algorithms and theoretical computer science are developed in con-

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

Java Consultant’s Preface


In the past decade, Java has become the language of choice for a
variety of applications. But Java developers have found themselves
repeatedly referring to references such as Sedgewick’s Algorithms in C
for solutions to common programming problems. There has long been
an empty space on the bookshelf for a comparable reference work for
Java; this book is here to fill that space.
We wrote the sample programs as utility methods to be used in
a variety of contexts. To that end, we did not use the Java package
mechanism. To focus on the algorithms at hand (and to expose the
algorithmic basis of many fundamental library classes), we avoided
the standard Java library in favor of more fundamental types. Proper
error checking and other defensive practices would both substantially
increase the amount of code and distract the reader from the core
algorithms. Developers should introduce such code when using the
programs in larger applications.
Although the algorithms we present are language independent,
we have paid close attention to Java-specific performance issues. The
timings throughout the book are provided as one context for compar-
ing algorithms, and will vary depending on the virtual machine. As
Java environments evolve, programs will perform as fast as natively
compiled code, but such optimizations will not change the perfor-
mance of algorithms relative to one another. We provide the timings
as a useful reference for such comparisons.
I would like to thank Mike Zamansky, for his mentorship and
devotion to the teaching of computer science, and Daniel Chaskes,
Jason Sanders, and James Percy, for their unwavering support. I would
also like to thank my family for their support and for the computer
that bore my first programs. Bringing together Java with the classic
algorithms of computer science was an exciting endeavor for which I
am very grateful. Thank you, Bob, for the opportunity to do so.

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:

◦ 14.20 Write a program that inserts N random integers into a


table of size N/100 using separate chaining, then finds the length
of the shortest and longest lists, for N = 103 , 104 , 105 , and 106 .
Such exercises encourage you to think about an important concept
that is related to the material in the text, or to answer a question that
may have occurred to you when you read the text. You may find it
worthwhile to read these exercises, even if you do not have the time to
work them through.
Exercises that are intended to challenge you are marked with a black
dot, as follows:

• 8.46 Suppose that mergesort is implemented to split the file at


a random position, rather than exactly in the middle. How many
comparisons are used by such a method to sort N elements, on
the average?
Such exercises may require a substantial amount of time to complete,
depending on your experience. Generally, the most productive ap-
proach is to work on them in a few different sittings.
A few exercises that are extremely difficult (by comparison with
most others) are marked with two black dots, 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

Chapter 2. Principles of Algorithm Analysis 27


2.1 Implementation and Empirical Analysis · 28
2.2 Analysis of Algorithms · 33
2.3 Growth of Functions · 36
2.4 Big-Oh Notation · 44
2.5 Basic Recurrences · 49
2.6 Examples of Algorithm Analysis · 53
2.7 Guarantees, Predictions, and Limitations · 60
CONTENTS

Data Structures

Chapter 3. Elementary Data Structures 69


3.1 Building Blocks · 70
3.2 Arrays · 84
3.3 Linked Lists · 91
3.4 Elementary List Processing · 97
3.5 Memory Allocation for Lists · 107
3.6 Strings · 111
3.7 Compound Data Structures · 116

Chapter 4. Abstract Data Types 127


4.1 Collections of Items · 137
4.2 Pushdown Stack ADT · 139
4.3 Examples of Stack ADT Clients · 142
4.4 Stack ADT Implementations · 148
4.5 Generic Implementations · 154
4.6 Creation of a New ADT · 157
4.7 FIFO Queues and Generalized Queues · 165
4.8 Duplicate and Index Items · 173
4.9 First-Class ADTs · 177
4.10 Application-Based ADT Example · 188
4.11 Perspective · 194

Chapter 5. Recursion and Trees 197


5.1 Recursive Algorithms · 198
5.2 Divide and Conquer · 206
5.3 Dynamic Programming · 219
5.4 Trees · 227
5.5 Mathematical Properties of Trees · 236
5.6 Tree Traversal · 240
5.7 Recursive Binary-Tree Algorithms · 246
5.8 Graph Traversal · 251
5.9 Perspective · 257

xvi
Sorting

Chapter 6. Elementary Sorting Methods 263


6.1 Rules of the Game · 265
6.2 Generic Sort Implementations · 270
6.3 Selection Sort · 283
6.4 Insertion Sort · 285
6.5 Bubble Sort · 288
6.6 Performance Characteristics of Elementary Sorts · 289
6.7 Algorithm Visualization · 295
6.8 Shellsort · 300
6.9 Sorting Linked Lists · 308
6.10 Key-Indexed Counting · 312

Chapter 7. Quicksort 315


7.1 The Basic Algorithm · 316
7.2 Performance Characteristics of Quicksort · 321
7.3 Stack Size · 325
7.4 Small Subfiles · 328
7.5 Median-of-Three Partitioning · 331
7.6 Duplicate Keys · 336
7.7 Strings and Vectors · 339
7.8 Selection · 341

Chapter 8. Merging and Mergesort 347


8.1 Two-Way Merging · 348
8.2 Abstract In-Place Merge · 351
8.3 Top-Down Mergesort · 353
8.4 Improvements to the Basic Algorithm · 357
8.5 Bottom-Up Mergesort · 359
8.6 Performance Characteristics of Mergesort · 363
8.7 Linked-List Implementations of Mergesort · 366
8.8 Recursion Revisited · 370

Chapter 9. Priority Queues and Heapsort 373


9.1 Elementary Implementations · 377
9.2 Heap Data Structure · 381

xvii
CONTENTS

9.3 Algorithms on Heaps · 383


9.4 Heapsort · 389
9.5 Priority-Queue ADT · 396
9.6 Priority Queues for Client Arrays · 402
9.7 Binomial Queues · 406

Chapter 10. Radix Sorting 417


10.1 Bits, Bytes, and Words · 419
10.2 Binary Quicksort · 423
10.3 MSD Radix Sort · 427
10.4 Three-Way Radix Quicksort · 435
10.5 LSD Radix Sort · 441
10.6 Performance Characteristics of Radix Sorts · 444
10.7 Sublinear-Time Sorts · 448

Chapter 11. Special-Purpose Sorting Methods 453


11.1 Batcher’s Odd–Even Mergesort · 455
11.2 Sorting Networks · 460
11.3 Sorting In Place · 468
11.4 External Sorting · 474
11.5 Sort–Merge Implementations · 480
11.6 Parallel Sort–Merge · 486

Searching

Chapter 12. Symbol Tables and BSTs 495


12.1 Symbol-Table Abstract Data Type · 497
12.2 Key-Indexed Search · 507
12.3 Sequential Search · 511
12.4 Binary Search · 519
12.5 Index Implementations with Symbol Tables · 524
12.6 Binary Search Trees · 531
12.7 Performance Characteristics of BSTs · 537
12.8 Insertion at the Root in BSTs · 542
12.9 BST Implementations of Other ADT Operations · 546

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

Chapter 14. Hashing 599


14.1 Hash Functions · 600
14.2 Separate Chaining · 610
14.3 Linear Probing · 615
14.4 Double Hashing · 620
14.5 Dynamic Hash Tables · 625
14.6 Perspective · 629

Chapter 15. Radix Search 635


15.1 Digital Search Trees · 637
15.2 Tries · 641
15.3 Patricia Tries · 650
15.4 Multiway Tries and TSTs · 660
15.5 Text-String–Index Applications · 679

Chapter 16. External Searching 685


16.1 Rules of the Game · 687
16.2 Indexed Sequential Access · 690
16.3 B Trees · 692
16.4 Extendible Hashing · 706
16.5 Perspective · 718

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

T HE OBJECTIVE OF THIS BOOK is to study a broad variety of


important and useful algorithms—methods for solving problems
that are suited for computer implementation. We shall deal with many
different areas of application, always concentrating on fundamental
algorithms that are important to know and interesting to study. We
shall spend enough time on each algorithm to understand its essential
characteristics and to respect its subtleties. Our goal is to learn well
enough to be able to use and appreciate a large number of the most
important algorithms used on computers today.
The strategy that we use for understanding the programs pre-
sented in this book is to implement and test them, to experiment with
their variants, to discuss their operation on small examples, and to try
them out on larger examples similar to what we might encounter in
practice. We shall use the Java programming language to describe the
algorithms, thus providing useful implementations at the same time.
Our programs have a uniform style that is amenable to translation into
other modern programming languages as well.
We also pay careful attention to performance characteristics of
our algorithms in order to help us develop improved versions, com-
pare different algorithms for the same task, and predict or guarantee
performance for large problems. Understanding how the algorithms
perform might require experimentation or mathematical analysis or
both. We consider detailed information for many of the most impor-
tant algorithms, developing analytic results directly when feasible, or
calling on results from the research literature when necessary.

3
4 §1.1 CHAPTER ONE

To illustrate our general approach to developing algorithmic so-


lutions, we consider in this chapter a detailed example comprising a
number of algorithms that solve a particular problem. The problem
that we consider is not a toy problem; it is a fundamental compu-
tational task, and the solution that we develop is of use in a variety
of applications. We start with a simple solution, then seek to under-
stand that solution’s performance characteristics, which help us to see
how to improve the algorithm. After a few iterations of this process,
we come to an efficient and useful algorithm for solving the problem.
This prototypical example sets the stage for our use of the same general
methodology throughout the book.
We conclude the chapter with a short discussion of the contents
of the book, including brief descriptions of what the major parts of
the book are and how they relate to one another.

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

When we use a computer to help us solve a problem, we typically


are faced with a number of possible different approaches. For small
problems, it hardly matters which approach we use, as long as we
have one that solves the problem correctly. For huge problems (or
applications where we need to solve huge numbers of small problems),
however, we quickly become motivated to devise methods that use
time or space as efficiently as possible.
The primary reason to learn about algorithm design is that this
discipline gives us the potential to reap huge savings, even to the point
of making it possible to do tasks that would otherwise be impossible.
In an application where we are processing millions of objects, it is not
unusual to be able to make a program millions of times faster by using
a well-designed algorithm. We shall see such an example in Section 1.2
and on numerous other occasions throughout the book. By contrast,
investing additional money or time to buy and install a new computer
holds the potential for speeding up a program by perhaps a factor of
only 10 or 100. Careful algorithm design is an extremely effective part
of the process of solving a huge problem, whatever the applications
area.
When a huge or complex computer program is to be developed,
a great deal of effort must go into 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 im-
plement. 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. Those are the types of algorithms on which
we concentrate in this book. We shall study a variety of fundamental
algorithms that are useful for solving huge 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, im-
plementing 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
6 §1.1 CHAPTER ONE

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 other words, we often implement
basic algorithms tailored to our problem, rather than depending on a
system routine, to make our solutions more portable and longer last-
ing. Another common reason to reimplement basic algorithms is that,
despite the advances embodied in Java, the mechanisms that we use
for sharing software are not always sufficiently powerful to allow us to
conveniently tailor library programs to perform effectively on specific
tasks.
Computer programs are often overoptimized. It may not be
worthwhile to take pains to ensure that an implementation of a partic-
ular algorithm is the most efficient possible unless the algorithm is to
be used for an enormous task or is to be used many times. Otherwise,
a careful, relatively simple implementation will suffice: We can have
some confidence that it will work, and it is likely to run perhaps 5 or 10
times slower at worst than the best possible version, which means that
it may run for an extra few seconds. By contrast, the proper choice
of algorithm in the first place can make a difference of a factor of 100
or 1000 or more, which might translate to minutes, hours, or even
more in running time. In this book, we concentrate on the simplest
reasonable implementations of the best algorithms. We do pay careful
attention to carefully 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 per-
formance; 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, and we strive to be aware of how
our algorithms might be expected to perform.
INTRODUCTION §1.2 7

1.2 A Sample Problem: Connectivity


Suppose that we are given a sequence of pairs of integers, where each
integer represents an object of some type and we are to interpret the
pair p-q as meaning “p is connected to q.” We assume the relation “is
connected to” to be transitive: If p is connected to q, and q is connected
to r, then p is connected to r. Our goal is to write a program to filter
out extraneous pairs from the set: When the program inputs a pair
p-q, it should output the pair only if the pairs it has seen to that point
do not imply that p is connected to q. If the previous pairs do imply
that p is connected to q, then the program should ignore p-q and
should proceed to input the next pair. Figure 1.1 gives an example of
this process.
Our problem is to devise a program that can remember sufficient
information about the pairs it has seen to be able to decide whether or
not a new pair of objects is connected. Informally, we refer to the task
of designing such a method as the connectivity problem. This problem
arises in a number of important applications. We briefly consider three 3-4 3-4
examples here to indicate the fundamental nature of the problem. 4-9 4-9
8-0 8-0
For example, the integers might represent computers in a large 2-3 2-3
network, and the pairs might represent connections in the network. 5-6 5-6
Then, our program might be used to determine whether we need to es- 2-9 2-3-4-9
tablish a new direct connection for p and q to be able to communicate 5-9 5-9
7-3 7-3
or whether we could use existing connections to set up a communi- 4-8 4-8
cations path. In this kind of application, we might need to process 5-6 5-6
millions of points and billions of connections, or more. As we shall 0-2 0-8-4-3-2
see, it would be impossible to solve the problem for such an application 6-1 6-1
without an efficient algorithm. Figure 1.1
Similarly, the integers might represent contact points in an electri- Connectivity example
cal network, and the pairs might represent wires connecting the points. Given a sequence of pairs of in-
In this case, we could use our program to find a way to connect all the tegers representing connections
between objects (left), the task of a
points without any extraneous connections, if that is possible. There connectivity algorithm is to output
is no guarantee that the edges in the list will suffice to connect all the those pairs that provide new con-
points—indeed, we shall soon see that determining whether or not they nections (center). For example, the
pair 2-9 is not part of the output
will could be a prime application of our program.
because the connection 2-3-4-9 is
Figure 1.2 illustrates these two types of applications in a larger implied by previous connections
example. Examination of this figure gives us an appreciation for the (this evidence is shown at right).
8 §1.2 CHAPTER ONE

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?

difficulty of the connectivity problem: How can we arrange to tell


quickly whether any given two points in such a network are connected?
Still another example arises in certain programming environ-
ments where it is possible to declare two variable names as equivalent.
The problem is to be able to determine whether two given names are
equivalent, after a sequence of such declarations. This application is an
early one that motivated the development of several of the algorithms
that we are about to consider. It directly relates our problem to a sim-
ple abstraction that provides us with a way to make our algorithms
useful for a wide variety of applications, as we shall see.
Applications such as the variable-name–equivalence problem de-
scribed in the previous paragraph require that we associate an integer
with each distinct variable name. This association is also implicit in the
INTRODUCTION §1.2 9

network-connection and circuit-connection applications that we have


described. We shall be considering a host of algorithms in Chapters 10
through 16 that can provide this association in an efficient manner.
Thus, we can assume in this chapter, without loss of generality, that
we have N objects with integer names, from 0 to N − 1.
We are asking for a program that does a specific and well-defined
task. There are many other related problems that we might want to
have solved as well. One of the first tasks that we face in developing
an algorithm is to be sure that we have specified the problem in a
reasonable manner. The more we require of an algorithm, the more
time and space we may expect it to need to finish the task. It is
impossible to quantify this relationship a priori, and we often modify
a problem specification on finding that it is difficult or expensive to
solve or, in happy circumstances, on finding that an algorithm can
provide information more useful than was called for in the original
specification.
For example, our connectivity-problem specification requires
only that our program somehow know whether or not any given pair
p-q is connected, and not that it be able to demonstrate any or all
ways to connect that pair. Adding a requirement for such a specifica-
tion makes the problem more difficult and would lead us to a different
family of algorithms, which we consider briefly in Chapter 5 and in
detail in Part 5.
The specifications mentioned in the previous paragraph ask us
for more information than our original one did; we could also ask for
less information. For example, we might simply want to be able to
answer the question: “Are the M connections sufficient to connect to-
gether all N objects?” This problem illustrates that to develop efficient
algorithms we often need to do high-level reasoning about the abstract
objects that we are processing. In this case, a fundamental result from
graph theory implies that all N objects are connected if and only if
the number of pairs output by the connectivity algorithm is precisely
N − 1 (see Section 5.4). In other words, a connectivity algorithm will
never output more than N − 1 pairs because, once it has output N − 1
pairs, any pair that it encounters from that point on will be connected.
Accordingly, we can get a program that answers the yes–no question
just posed by changing a program that solves the connectivity problem
to one that increments a counter, rather than writing out each pair
10 §1.2 CHAPTER ONE

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

tasks of defining a data structure representing the sets and developing


union and find algorithms that efficiently use that data structure.
There are many ways to represent and process abstract sets, some
of which we consider in Chapter 4. In this chapter, our focus is on
finding a representation that can support efficiently the union and find
operations that we see in solving the connectivity problem.
Exercises
1.1 Give the output that a connectivity algorithm should produce when
given the input 0-2, 1-4, 2-5, 3-6, 0-4, 6-0, and 1-3.
1.2 List all the different ways to connect two different objects for the ex-
ample in Figure 1.1.
1.3 Describe a simple method for counting the number of sets remaining
after using the union and find operations to solve the connectivity problem as
described in the text.

1.3 Union–Find Algorithms


The first step in the process of developing an efficient algorithm to
solve a given problem is to implement a simple algorithm that solves
the problem. If we need to solve a few particular problem instances
that turn out to be easy, then the simple implementation may finish
the job for us. If a more sophisticated algorithm is called for, then the
simple implementation provides us with a correctness check for small
cases and a baseline for evaluating performance characteristics. We
always care about efficiency, but our primary concern in developing
the first program that we write to solve a problem is to make sure that
the program is a correct solution to the problem.
The first idea that might come to mind is somehow to save all
the input pairs, then to write a function to pass through them to try
to discover whether the next pair of objects is connected. We shall use
a different approach. First, the number of pairs might be sufficiently
large to preclude our saving them all in memory in practical applica-
tions. Second, and more to the point, no simple method immediately
suggests itself for determining whether two objects are connected from
the set of all the connections, even if we could save them all! We
consider a basic method that takes this approach in Chapter 5, but
the methods that we shall consider in this chapter are simpler, because
they solve a less difficult problem, and more efficient, because they do
12 §1.3 CHAPTER ONE

Program 1.1 Quick-find solution to connectivity problem


This program takes an integer N from the command line, reads a se-
quence of pairs of integers, interprets the pair p q to mean “connect
object p to object q,” and prints the pairs that represent objects that are
not yet connected. The program maintains the array id such that id[p]
and id[q] are equal if and only if p and q are connected.
The In and Out methods that we use for input and output are
described in the Appendix, and the standard Java mechanism for taking
parameter values from the command line is described in Section 3.7.

public class QuickF


{ public static void main(String[] args)
{ int N = Integer.parseInt(args[0]);
int id[] = new int[N];
for (int i = 0; i < N ; i++) id[i] = i;
for( In.init(); !In.empty(); )
p q 0 1 2 3 4 5 6 7 8 9 { int p = In.getInt(), q = In.getInt();
int t = id[p];
3 4 0 1 2 4 4 5 6 7 8 9 if (t == id[q]) continue;
4 9 0 1 2 9 9 5 6 7 8 9
8 0 0 1 2 9 9 5 6 7 0 9
for (int i = 0; i < N; i++)
2 3 0 1 9 9 9 5 6 7 0 9 if (id[i] == t) id[i] = id[q];
5 6 0 1 9 9 9 6 6 7 0 9 Out.println(" " + p + " " + q);
2 9 0 1 9 9 9 6 6 7 0 9
}
5 9 0 1 9 9 9 9 9 7 0 9
7 3 0 1 9 9 9 9 9 9 0 9 }
4 8 0 1 0 0 0 0 0 0 0 0 }
5 6 0 1 0 0 0 0 0 0 0 0
0 2 0 1 0 0 0 0 0 0 0 0
6 1 1 1 1 1 1 1 1 1 1 1 not require saving all the pairs. They all use an array of integers—one
corresponding to each object—to hold the requisite information to be
Figure 1.3 able to implement union and find. Arrays are elementary data struc-
Example of quick find (slow tures that we discuss in detail in Section 3.2. Here, we use them in
union)
their simplest form: we create an array that can hold N integers by
This sequence depicts the con-
writing int id[] = new int[N]; then we refer to the ith integer in
tents of the id array after each
of the pairs at left is processed the array by writing id[i], for 0 ≤ i < 1000.
by the quick-find algorithm (Pro- Program 1.1 is an implementation of a simple algorithm called
gram 1.1). Shaded entries are the quick-find algorithm that solves the connectivity problem (see Sec-
those that change for the union op- tion 3.1 and Program 3.1 for basic information on Java programs).
eration. When we process the pair
p q, we change all entries with The basis of this algorithm is an array of integers with the property
the value id[p] to have the value that p and q are connected if and only if the pth and qth array entries
id[q]. are equal. We initialize the ith array entry to i for 0 ≤ i < N . To
INTRODUCTION §1.3 13

implement the union operation for p and q, we go through the array,


changing all the entries with the same name as p to have the same name
0 1 2 4 5 6 7 8 9
as q. This choice is arbitrary—we could have decided to change all the 3
entries with the same name as q to have the same name as p.
Figure 1.3 shows the changes to the array for the union opera- 0 1 2 9 5 6 7 8
tions in the example in Figure 1.1. To implement find, we just test 3 4
the indicated array entries for equality—hence the name quick find.
The union operation, on the other hand, involves scanning through 1 2 9 5 6 7 0
the whole array for each input pair. 3 4 8

Property 1.1 The quick-find algorithm executes at least M N instruc-


1 9 5 6 7 0
tions to solve a connectivity problem with N objects that involves M
2 3 4 8
union operations.
For each of the M union operations, we iterate the for loop N times. 1 9 6 7 0

Each iteration requires at least one instruction (if only to check whether 2 3 4 5 8

the loop is finished).


1 9 7 0
We can execute tens or hundreds of millions of instructions per 2 3 4 5 6 8
second on modern computers, so this cost is not noticeable if M and
N are small, but we also might find ourselves with billions of objects 1 9 0
and millions of input pairs to process in a modern application. The 2 3 4 5 6 7 8
inescapable conclusion is that we cannot feasibly solve such a problem
using the quick-find algorithm (see Exercise 1.10). We consider the 1 0

process of precisely quantifying such a conclusion precisely in Chap- 2 3 4 5 6 7 8 9

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

in a structure with no cycles. To determine whether two objects are


in the same set, we follow links for each until we reach an object that
has a link to itself. The objects are in the same set if and only if this
0 1 2 4 5 6 7 8 9
3 process leads them to the same object. If they are not in the same
set, we wind up at different objects (which have links to themselves).
0 1 2 9 5 6 7 8
4 To form the union, then, we just link one to the other to perform the
3 union operation; hence the name quick union.
Figure 1.5 shows the graphical representation that corresponds to
1 2 9 5 6 7 0
4 8 Figure 1.4 for the operation of the quick-union algorithm on the exam-
3 ple of Figure 1.1, and Figure 1.6 shows the corresponding changes to
the id array. The graphical representation of the data structure makes
1 9 5 6 7 0
2 4 8 it relatively easy to understand the operation of the algorithm—input
3 pairs that are known to be connected in the data are also connected to
one another in the data structure. As mentioned previously, it is im-
1 9 6 7 0
2 4 5 8 portant to note at the outset that the connections in the data structure
3 are not necessarily the same as the connections in the application im-
plied by the input pairs; rather, they are constructed by the algorithm
1 9 7 0
2 4 6 8 to facilitate efficient implementation of union and find.
3 5 The connected components depicted in Figure 1.5 are called trees;
1
they are fundamental combinatorial structures that we shall encounter
9 0
2 4 6 7 8 on numerous occasions throughout the book. We shall consider the
3 5 properties of trees in detail in Chapter 5. For the union and find
operations, the trees in Figure 1.5 are useful because they are quick to
1 0
9 8 build and have the property that two objects are connected in the tree
2 4 6 7 if and only if the objects are connected in the input. By moving up the
3 5
tree, we can easily find the root of the tree containing each object, so
1
we have a way to find whether or not they are connected. Each tree
0 has precisely one object that has a link to itself, which is called the
9 8 root of the tree. The self-link is not shown in the diagrams. When
2 4 6 7
we start at any object in the tree, move to the object to which its link
3 5
refers, then move to the object to which that object’s link refers, and
so forth, we always eventually end up at the root. We can prove this
Figure 1.5 property to be true by induction: It is true after the array is initialized
Tree representation of quick to have every object link to itself, and if it is true before a given union
union
operation, it is certainly true afterward.
This figure is a graphical represen-
tation of the example in Figure 1.3. The diagrams in Figure 1.4 for the quick-find algorithm have the
We draw a line from object i to same properties as those described in the previous paragraph. The
object id[i]. difference between the two is that we reach the root from all the nodes
INTRODUCTION §1.3 15

Program 1.2 Quick-union solution to connectivity problem


If we replace the body of the for loop in Program 1.1 by this code, we
have a program that meets the same specifications as Program 1.1, but
does less computation for the union operation at the expense of more
computation for the find operation. The for loops and subsequent if
statement in this code specify the necessary and sufficient conditions on
p q 0 1 2 3 4 5 6 7 8 9
the id array for p and q to be connected. The assignment statement
id[i] = j implements the union operation.
3 4 0 1 2 4 4 5 6 7 8 9
int i, j, p = In.getInt(), q = In.getInt(); 4 9 0 1 2 4 9 5 6 7 8 9
for (i = p; i != id[i]; i = id[i]); 8 0 0 1 2 4 9 5 6 7 0 9
for (j = q; j != id[j]; j = id[j]); 2 3 0 1 9 4 9 5 6 7 0 9
if (i == j) continue; 5 6 0 1 9 4 9 6 6 7 0 9

id[i] = j; 2 9 0 1 9 4 9 6 6 7 0 9

Out.println(" " + p + " " + q); 5 9 0 1 9 4 9 6 9 7 0 9


7 3 0 1 9 4 9 6 9 9 0 9
4 8 0 1 9 4 9 6 9 9 0 0

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

need to follow several links to get to the root in a quick-union tree. 0 2 0 1 9 4 9 6 9 9 0 0


6 1 1 1 9 4 9 6 9 9 0 0
Program 1.2 is an implementation of the union and find opera-
tions that comprise the quick-union algorithm to solve the connectivity 5 8 1 1 9 4 9 6 9 9 0 0
problem. The quick-union algorithm would seem to be faster than the
quick-find algorithm, because it does not have to go through the entire
array for each input pair; but how much faster is it? This question is Figure 1.6
Example of quick union (not-
more difficult to answer here than it was for quick find, because the too-quick find)
running time is much more dependent on the nature of the input. By This sequence depicts the con-
running empirical studies or doing mathematical analysis (see Chap- tents of the id array after each of
ter 2), we can convince ourselves that Program 1.2 is far more efficient the pairs at left are processed by
than Program 1.1, and that it is feasible to consider using Program 1.2 the quick-union algorithm (Pro-
gram 1.2). Shaded entries are
for huge practical problems. We shall discuss one such empirical study those that change for the union
at the end of this section. For the moment, we can regard quick union operation (just one per operation).
as an improvement because it removes quick find’s main liability (that When we process the pair p q, we
the program requires at least N M instructions to process M union follow links from p to get an entry
i with id[i] == i; then, we fol-
operations among N objects). low links from q to get an entry j
This difference between quick union and quick find certainly with id[j] == j; then, if i and j
represents an improvement, but quick union still has the liability that differ, we set id[i] = id[j]. For
the find operation for the pair 5-8
we cannot guarantee it to be substantially faster than quick find in
(final line), i takes on the values 5
every case, because the input data could conspire to make the find 6 9 0 1, and j takes on the values
operation slow. 8 0 1.
16 §1.3 CHAPTER ONE

Property 1.2 For M > N , the quick-union algorithm could take


0 1 2 3 5 6 7 8 9 more than M N/2 instructions to solve a connectivity problem with M
4 pairs of N objects.

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

Program 1.3 Weighted version of quick union 0 2 3 4 5 6 7 8 9


This program is a modification to the quick-union algorithm (see Pro- 1
gram 1.2) that keeps an additional array sz for the purpose of main-
taining, for each object with id[i] == i, the number of nodes in the 0 2 4 5 6 7 8 9
associated tree so that the union operation can link the smaller of the 1 3
two specified trees to the larger, thus preventing the growth of long paths
in the trees. 0 2 4 6 7 8 9
1 3 5
public class QuickUW
{ public static void main(String[] args) 0 2 4 6 8 9
{ int N = Integer.parseInt(args[0]); 1 3 5 7
int id[] = new int[N], sz[] = new int[N];
0 2 4 6 8
for (int i = 0; i < N ; i++) 1 3 5 7 9
{ id[i] = i; sz[i] = 1; }
for(In.init(); !In.empty(); ) 0 4 6 8
{ int i, j, p = In.getInt(), q = In.getInt(); 1 2 5 7 9
3
for (i = p; i != id[i]; i = id[i]);
for (j = q; j != id[j]; j = id[j]);
0 4 8
if (i == j) continue;
1 2 5 6 9
if (sz[i] < sz[j]) 3 7
{ id[i] = j; sz[j] += sz[i]; }
else { id[j] = i; sz[i] += sz[j]; } 0 8
Out.println(" " + p + " " + q); 1 2 4 9
} 3 5 6

} 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

3 1 tions to process M edges on N objects (see Exercise 1.9). This result is


8 2 4 5 7 9 in stark contrast to our finding that quick find always (and quick union
0 6 sometimes) uses at least M N/2 instructions. The conclusion is that,
with weighted quick union, we can guarantee that we can solve huge
3 practical problems in a reasonable amount of time (see Exercise 1.11).
8 1 2 4 5 6 7 9 For the price of a few extra lines of code, we get a program that is
0 literally millions of times faster than the simpler algorithms for the
huge problems that we might encounter in practical applications.
It is evident from the diagrams that relatively few nodes are
0 8 far from the root; indeed, empirical studies on huge problems tell us
1 2 4 9 that the weighted quick-union algorithm of Program 1.3 typically can
3 5 6 solve practical problems in linear time. That is, the cost of running the
7 algorithm is within a constant factor of the cost of reading the input.
We could hardly expect to find a more efficient algorithm.
0 We immediately come to the question of whether or not we can
1 2 4 6 8 find an algorithm that has guaranteed linear performance. This ques-
3 5 7 9 tion is an extremely difficult one that plagued researchers for many
years (see Section 2.7). There are a number of easy ways to improve
Figure 1.9 the weighted quick-union algorithm further. Ideally, we would like
Path compression every node to link directly to the root of its tree, but we do not want
We can make paths in the trees to pay the price of changing a large number of links, as we did in the
even shorter by simply making all quick-union algorithm. We can approach the ideal simply by making
the objects that we touch point all the nodes that we do examine link to the root. This step seems
to the root of the new tree for the
union operation, as shown in these
drastic at first blush, but it is easy to implement, and there is nothing
two examples. The example at the sacrosanct about the structure of these trees: If we can modify them
top shows the result correspond- to make the algorithm more efficient, we should do so. We can easily
ing to Figure 1.7. For short paths, implement this method, called path compression, by adding another
path compression has no effect,
but when we process the pair 1
pass through each path during the union operation, setting the id entry
6, we make 1, 5, and 6 all point corresponding to each vertex encountered along the way to link to the
to 3 and get a tree flatter than the root. The net result is to flatten the trees almost completely, approxi-
one in Figure 1.7. The example at mating the ideal achieved by the quick-find algorithm, as illustrated in
the bottom shows the result cor-
responding to Figure 1.8. Paths
Figure 1.9. The analysis that establishes this fact is extremely complex,
that are longer than one or two but the method is simple and effective. Figure 1.11 shows the result of
links can develop in the trees, path compression for a large example.
but whenever we traverse them, There are many other ways to implement path compression. For
we flatten them. Here, when we
process the pair 6 8, we flatten example, Program 1.4 is an implementation that compresses the paths
the tree by making 4, 6, and 8 all by making each link skip to the next node in the path on the way up
point to 0. the tree, as depicted in Figure 1.10. This method is slightly easier to
INTRODUCTION §1.3 19

Program 1.4 Path compression by halving


If we replace the for loops in Program 1.3 by this code, we halve the
length of any path that we traverse. The net result of this change is
that the trees become almost completely flat after a long sequence of
operations.

for (i = p; i != id[i]; i = id[i])


id[i] = id[id[i]];
for (j = q; j != id[j]; j = id[j])
id[j] = id[id[j]];

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

Table 1.1 Empirical study of union-find algorithms

These relative timings for solving random connectivity problems us-


ing various union–find algorithms demonstrate the effectiveness of the
weighted version of the quick-union algorithm. The added incremental
benefit due to path compression is less important. In these experiments,
M is the number of random connections generated until all N objects
are connected. This process involves substantially more find operations
than union operations, so quick union is substantially slower than quick
find. Neither quick find nor quick union is feasible for huge N. The
running time for the weighted methods is evidently roughly proportional
to M .

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

• Find high-level abstract representations of data structures or al-


gorithms in operation that enable effective high-level design of
improved versions.
• Strive for worst-case performance guarantees when possible, but
accept good performance on actual data when available.
The potential for spectacular performance improvements for practical
problems such as those that we saw in Section 1.2 makes algorithm
design a compelling field of study; few other design activities hold the
potential to reap savings factors of millions or billions, or more.
More important, as the scale of our computational power and
our applications increases, the gap between a fast algorithm and a
slow one grows. A new computer might be 10 times faster and be
able to process 10 times as much data as an old one, but if we are
using a quadratic algorithm such as quick find, the new computer will
take 10 times as long on the new job as the old one took to finish
the old job! This statement seems counterintuitive at first, but it is
easily verified by the simple identity (10N )2 /10 = 10N 2 , as we shall
see in Chapter 2. As computational power increases to allow us to
take on larger and larger problems, the importance of having efficient
algorithms increases as well.
Developing an efficient algorithm is an intellectually satisfying
activity that can have direct practical payoff. As the connectivity
problem indicates, a simply stated problem can lead us to study nu-
merous algorithms that are not only both useful and interesting, but
also intricate and challenging to understand. We shall encounter many
ingenious algorithms that have been developed over the years for a host
of practical problems. As the scope of applicability of computational
solutions to scientific and commercial problems widens, so also grows
the importance of being able to apply efficient algorithms to solve
known problems and of being able to develop efficient solutions to
new problems.
Exercises
1.25 Suppose that we use weighted quick union to process 10 times as many
connections on a new computer that is 10 times as fast as an old one. How
much longer would it take the new computer to finish the new job than it took
the old one to finish the old job?
1.26 Answer Exercise 1.25 for the case where we use an algorithm that
requires N 3 instructions.
24 §1.5 CHAPTER ONE

1.5 Summary of Topics


This section comprises brief descriptions of 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, 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 book, which are contained in this vol-
ume, 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 applications of computation.

Fundamentals (Part 1) in the context of this book are the basic


principles and methodology that we use to implement, analyze, and
compare algorithms. The material in Chapter 1 motivates our study
of algorithm design and analysis; in Chapter 2, we consider basic
methods of obtaining quantitative information about the performance
of algorithms.
Data Structures (Part 2) go hand-in-hand with algorithms: We
shall develop a thorough understanding of data representation meth-
ods for use throughout the rest of the book. We begin with an in-
troduction to basic concrete data structures in Chapter 3, including
arrays, linked lists, and strings. In Chapter 4, we consider fundamen-
tal abstract data types (ADTs) such as stacks and queues, including
implementations using elementary data structures. Then in Chapter 5
we consider recursive programs and data structures, in particular trees
and algorithms for manipulating them.
Sorting algorithms (Part 3) for rearranging files into order are of
fundamental importance. We consider a variety of algorithms in con-
siderable depth, including shellsort, quicksort, mergesort, heapsort,
and radix sorts. We shall encounter algorithms for several related
Random documents with unrelated
content Scribd suggests to you:
a cradle song; it is the pillow of the sick and the last word of the
dying, it is written on the door-posts and in their hearts as well as
since eternity on the throne of God, it is to the devout Moslem the
name above every name; grammarians can tell you how its four
letters are representative of all the sciences and mysteries by their
wonderful combination. The name of Mohammed is the best to give
a child and the best to swear by for an end of all dispute in a close
bargain. The exceeding honor given to Mohammed’s name by his
followers is only one indication of the place their prophet occupies in
their system and holds in their hearts. From the fullness of the heart
the mouth speaketh. Mohammed holds the keys of heaven and hell.
No Moslem, however bad his character, will perish finally; no
unbeliever, however good his life, can be saved except through
Mohammed. One has only to question the Moslem masses or read a
single volume of the traditions to prove these statements.
Islam denies a mediator and an incarnation but the “Story of the
Jew” and similar tales put Mohammed in the place of a mediator
without an incarnation, without an atonement, without holiness. Our
Analysis of the Moslem creed shows how all the later teaching which
so exalted Mohammed was present in the germ. “La ilaha illa Allah”
is the theology, “Mohammed er rasool Allah,” the complete
Soteriology of Islam. The logical necessity of a perfect mediator was
at the basis of the doctrine of Tradition. Islam has, it claims, a
perfect revelation in the letter of the Koran; and a perfect example in
the life of Mohammed. The stream has not risen higher than its
sources.
The Book of Islam. When Mohammed Webb the latest American
champion of Islam spoke at the Chicago Parliament of religions in
praise of the Koran and its teaching, Rev. George E. Post, M. D., of
Beirut deemed it a sufficient reply to let the book speak for itself. He
said: “I hold in my hand a book which is never touched by
200,000,000 of the human race with unwashen hands, a book which
is never carried below the waist, a book which is never laid upon the
floor, a book every word of which to these 200,000,000 of the
human race is considered the direct word of God which came down
from heaven. I propose without note or comment to read to you a
few words from the sacred book and you may make your own
comments upon them afterward.” After quoting several verses to
show that Mohammed preached a religion of the sword and of
polygamy, he added: “There is one chapter which I dare not stand
before you, my sisters, mothers and daughters, and read to you. I
have not the face to read it; nor would I like to read it even in a
congregation of men. It is the sixty-fourth chapter of the Koran.”
What sort of a book is this revelation of Mohammed of which parts
are unfit to read before a Christian audience and which yet is too
holy to be touched by other than Moslem hands? A book which the
orthodox Moslem believes to be uncreated and eternal, all-
embracing and all-surpassing, miraculous in its origin and contents.
A book concerning which Mohammed himself has said, “If the Koran
were wrapped in a skin and thrown into the fire it would not burn.”
Goethe described it thus: “However often we turn to it, at first
disgusting us each time afresh it soon attracts, astounds, and in the
end enforces our reverence. Its style in accordance with its contents
and aim is stern, grand, terrible—and ever and anon truly sublime.
Thus this book will go on exercising through all ages a most potent
influence.” And Nöldeke writes, “if it were not for the exquisite
flexibility and vigor of the Arabic language itself, which, however is
to be attributed more to the age in which the author lived than to
his individuality, it would scarcely be bearable to read the later
portions of the Koran a second time.” Goethe read only the
translation; and Nöldeke was master of the original. It is as hopeless
to arrive at a unanimous verdict regarding the Koran as it is to reach
an agreement regarding Mohammed.
The book has fifty-five noble titles on the lips of its people but is
generally called the Koran or “The Reading.” It has one hundred and
fourteen chapters, some of which are as long as the book of Genesis
and others consisting of two or three sentences only. The whole
book is smaller than the New Testament, has no chronological order
whatever and is without logical sequence or climax. What strikes the
reader first of all is its jumbled character; every sort of fact and
fancy, law and legend is thrown together piecemeal. The four
proposed chronological arrangements, by Jorlal-ud-Din, Muir,
Rodwell and Nöldeke are in utter disagreement. Only two of
Mohammed’s contemporaries are mentioned in the entire book and
his own name occurs only five times. The book is unintelligible to the
average Moslem without a commentary, and I defy any one else to
lead it through, without the aid of notes, and understand a single
chapter or even section.
We will not stop to consider the fabulous account which Moslems
give of the origin of the Koran and how the various chapters were
revealed. Although Moslems claim that the book was eternally
perfect in form and preserved in heaven, they are compelled to
admit that it was revealed piecemeal and at various times and places
by Mohammed to his followers. It was recorded in writing, after the
rude Arab fashion, “on palm-leaves and sheep-bones and white
stones” to some extent; but for the most part was preserved orally
by constant repetition. Omar suggested to Abu-Bekr after the battle
of Yemama that since many of the Koran reciters were slain, it would
be the part of wisdom to put the book of God in permanent form.
The task was committed to Zaid, the chief amanuensis of
Mohammed and the resulting volume was entrusted to the care of
Hafsa, one of the widows of the prophet. Ten years later a recension
of the Koran was ordered by the Caliph Othman and all previous
copies were called in and burned. This recension of Othman, sent to
all the chief cities of the Moslem world, has been faithfully handed
down to the present. “No other book in the world has remained
twelve centuries with so pure a text.” (Hughes.) The present
variations in editions of the Arabic Koran are numerous but none of
them are, in any sense important. The present Koran is the same
book that Mohammed professed to have received from God. Out of
its own mouth will we judge the book; and we cannot judge the
book without judging the prophet.
We will speak later of the poetical beauties of the Koran and of its
literary character. We do not deny also that there are in the Koran
certain moral beauties, such as its deep and fervent trust in the one
God, its lofty descriptions of His Almighty power and omnipresence,
and its sententious wisdom. The first chapter and the verse of the
throne are examples.

“In the name of God, the Compassionate, the Merciful.


Praise be to God, Lord of all the worlds!
The Compassionate, the Merciful!
King on the Day of Judgment!
Thee do we worship, and to Thee do we cry for help!
Guide Thou us on the right path!
The path of those to whom Thou art gracious!
Not of those with whom Thou art angered, nor of those who go
astray.”

“God! there is no God but He; the living, the Eternal


Slumber doth not overtake Him, neither sleep.
To Him belongeth whatsoever is in heaven and on the earth.
The preservation of both is no weariness unto Him.
He is the high, the mighty.”

The great bulk of the Koran is either legislative or legendary; the


book consists of laws and stories. The former relate entirely to
subjects which engrossed the Arabs of Mohammed’s day—the laws
of inheritance, the relation of the sexes, the law of retaliation, etc—
and this part of the book has a local character. The stories on the
other hand go back to Adam and the patriarchs, take in several
unknown Arabian prophets or leaders, centre around Jesus Christ,
Moses and Solomon and do not venture beyond Jewish territory
except to mention Alexander the Great and Lukman (Æsop).
From the analytical tables it is not very difficult to see whence the
material for the Koran was selected. Rabbi Geiger’s book, recently
translated into English, will satisfy any reader that Hughes is nearly
right when he says, “Mohammedanism is simply Talmudic Judaism
adapted to Arabia plus the apostleship of Jesus and Mohammed.”
But it is Talmudic Judaism and not the Judaism of the Old
Testament. For the Koran is remarkable most of all not because of its
contents but because of its omissions. Not because of what it reveals
but for what it conceals of “former revelations.” The defects of its
teaching are many. It is full of historical errors and blunders. It has
monstrous fables. It teaches a false cosmogony. It is full of
superstitions. It perpetuates slavery, polygamy, religious intolerance,
the seclusion and degradation of woman and petrifies social life. But
all this is of minor importance compared with the fact that the Koran
professing to be a revelation from God does not teach the way to
reconciliation with God and seems to ignore the first and great
barrier to such reconciliation, viz: sin. Of this the Old and New
Testaments are always speaking. Sin and salvation are the subject of
which the Torah and the Zaboor and the Injil (Law Prophets and
Psalms) are full. The Koran is silent or if not absolutely silent, keeps
this great question ever in the background.[62]
It is a commonplace of theology that “to form erroneous
conceptions of sin is to fall into still graver errors regarding the way
of salvation.” Mohammed, as is evident from his whole life, had no
deep conviction of sin in himself; he was full of self-righteousness.
His ideas, too, of God, were physical, not moral; he saw God’s
power, but never had a glimpse of His holiness. And so we find that
there is an inward unity binding together the prophet and his book
as to their real character in the light of the gospel. With such ideas
of God, such a prophet and such a book, it is easy to understand
why the Mohammedan world became what it is to-day. These bare
outlines of the system of Islam are all that are necessary to indicate
its nature and genus. Allah’s character as the revealer, Mohammed’s
character as the channel of the revelation, and the revelation itself,
show us Islam in its cradle.
XIX
THE WAHABI RULERS AND REFORMERS

“Nothing is so easy to appreciate as true Christian


commerce. It is a speaking argument, even to the lowest
savage, for a gospel of truth and love, and yet more to
the races sophisticated by a false civilization.”—Principal
Cairns.
The history of the Arabian Peninsula has never yet been written.
Many books describe certain periods of its history from the time of
the earlier Arabian rulers, but there is no volume that tells the story
from the beginning in a way worthy of the subject. It would be
interesting to search out the earliest records and trace the Himyarite
dynasties to their origin; to learn the story of the Jewish immigrants
who settled in Medina, Mecca and Yemen even before the Christian
Era; to follow the Arabs in their conquests under the banner of the
prophet; to watch the sudden rise of the Carmathians and follow
them in their career of destruction; to search the old libraries and
rediscover the romantic story of the Portuguese, the Dutch and the
English in Arabian waters;—but our space limits us to the story of
the past century.[63]
To understand the present political conditions and recent history
of Arabia, we must go back to the year 1765, which marks the rise
of the remarkable Wahabi movement, which was at the bottom of all
the political changes that the Peninsula has seen since that time.
This movement was the renaissance of Islam, even though it ended
in apparent disaster, and was politically a splendid fiasco. The
Wahabi reform attracted the attention of Turkey to Arabia; its
influence was felt in India to the extent of declaring a jihad or
religious war against the government, and compelled England to
study the situation and send representatives to the very heart of
Arabia.
Beginning with the Wahabi dynasty, the history of the past century
in Arabia centres in the rulers of Nejd and Oman, the Turkish
conquests and the English influence and occupation. The strong
independent government of Nejd under Ibn Rashid and his
successor, Abd-ul-Aziz, would have been an impossibility except for
the result of the Wahabi movement, in demonstrating the weakness
of Turkish rule. And it was for fear of the Wahabi aggressions that
Turkey strengthened her Arabian possessions and invaded Hassa.
Mohammed bin Abd-ul-Wahab was born at Ayinah in Nejd, in
1691. Carefully instructed by his father in the tenets of Islam
according to the school of Hambali, the strictest of the four great
sects.[64] Abd-ul-Wahab visited the schools of Mecca, Busrah and
Bagdad, to increase his learning. At Medina, too, he absorbed the
deepest learning of the Moslem divines and soaked himself in the
“six correct books” of traditions. In his travels he had observed the
laxity of faith and practice which had crept in, especially among the
Turks and the Arabs of the large cities. He tried to distinguish
between the essential elements of Islam and its later additions,
some of which seemed to him to savor of gross idolatry and
worldliness. What most offended the rigid monotheism of his
philosophy was the almost universal visitation of shrines, invocation
of saints and honor paid to the tomb of Mohammed. The use of the
rosary, of jewels, silk, gold, silver, wine and tobacco, were all
abominations to be eschewed. These were indications of the great
need for reform. The earlier teaching of the companions of the
prophet had been set aside or overlaid by later teaching. Even the
four orthodox schools had departed from the pure faith by allowing
pilgrimage to Medina, by multiplying festivals and philosophizing
about the nature of Allah. Therefore it was that Abd-ul-Wahab
preached reform not only, but proclaimed himself the leader of a
new sect. His teaching was based on the Koran and the early
traditions.
This movement is chiefly distinguished from the orthodox system
in the following particulars:

1. The Wahabis reject Ijma or the agreement of later


interpreters.
2. They offer no prayers to prophet, wali, or saint, nor visit their
tombs for that purpose.
3. They say Mohammed is not yet an intercessor; although at
the last day he will be.
4. They forbid women to visit the graves of the dead.
5. They allow only four festivals, Fitr, Azha, ’Ashura and Lailat El
Mobarek.
6. They do not celebrate Mohammed’s birth.
7. They use their knuckles for prayer-counting, and not rosaries.
8. They strictly forbid the use of silk, gold, silver ornaments,
tobacco, music, opium, and every luxury of the Orient, except
perfume and women.
9. They have anthropomorphic ideas of God by strictly literal
interpretation of the Koran texts about “His hand,” “sitting,” etc.
10. They believe jihad or religious war, is not out of date, but
incumbent on the believer.
11. They condemn minarets, tombstones, and everything that
was not in use during the first years of Islam.

There is no doubt that Abd-ul-Wahab honestly tried to bring about


a reform and that in many of the points enumerated his reform was
strictly a return to primitive Islam. But it was too radical to last. It
took no count of modern civilization and the ten centuries that had
modified the very character of the Arabs of the towns not to speak
of those outside of Arabia. Yet the preaching of the Reformer found
willing ears in the isolation of the desert. As in the days of Omar, the
promise of reform in religion was made attractive by the promise of
rich booty to those who fought in the path of God and destroyed
creature-worshippers. Mohammed Abd-ul-Wahab was the preacher,
but to propagate his doctrine he needed a sword. Mohammed bin
Saud, of Deraiyah, supplied the latter factor and the two
Mohammeds, allied by marriage and a common ambition, began to
make converts and conquests. The son of Bin Saud, Abd-ul-Aziz, was
the Omar of the new movement, and his son Saud even surpassed
the father in military prowess and successful conquest. Abd-ul-Aziz
was murdered by a Persian fanatic while prostrate in prayer in the
mosque at Deraiyah, in 1803. Saud at this very time was pushing the
Wahabi conquest to the very gates of Mecca. On the 27th of April,
1803, he carried his banner into the court of the Kaaba and began to
cleanse the holy place. Piles of pipes, tobacco, silks, rosaries and
amulets were collected into one great heap and set on fire by the
infuriated enthusiasts. No excesses were committed against the
people except that religion was forced upon them. The mosques
were filled by public “whips” who used their leather thongs without
mercy on all the lazy or negligent. Everybody, for a marvel, prayed
five times a day. The result of his victory at Mecca was
communicated by the dauntless Saud in the following naïve letter
addressed to the Sultan of Turkey:
“Saud To Salim—I entered Mecca on the fourth day of
Moharram in the 1218th year of the Hegira. I kept peace
toward the inhabitants. I destroyed all things that were
idolatrously worshipped. I abolished all taxes except those
that were required by the law. I confirmed the Kadhi
whom you had appointed agreeably to the commands of
the prophet of God. I desire that you will give orders to
the rulers of Damascus and Cairo not to come up to the
sacred city with the Mahmal[65] and with trumpets and
drums. Religion is not profited by these things. May the
peace and blessing of God be with you.”
The absence of long salutations and the usual phrases of honor is
characteristic of all Wahabi correspondence. In this respect it is a
great improvement on the excessive lavishment of titles and honors
so usual among Moslems, especially among the Persians and the
Turks.
Before the close of the year Saud avenged his father’s death by
attacking Medina and destroying the gilded dome that covered the
prophet’s tomb. As early as 1801 parties of plundering Wahabis had
sacked the tomb of Hussein and carried off rich booty from the
sacred city of Kerbela. According to the official inventory this booty
consisted of vases, carpets, jewels, weapons innumerable; also, 500
gilded copper-plates from the dome, 4,000 cashmire shawls, 6,000
Spanish doubloons, 350,000 Venetian coins of silver, 400,000 Dutch
ducats, 250,000 Spanish dollars and a large number of Abyssinian
slaves belonging to the mosque.[66] Their raids and conquests
extended in every direction so that in a few years the Wahabi power
was supreme in the greater part of Arabia.
A single illustration will show the great Saud’s[67] prudence and
celerity in action. When he invaded the Hauran plains, in 1810,
although it was thirty-five days’ journey from his capital, yet the
news of his approach only preceded his arrival by two days, nor was
it known what part of Syria he planned to attack, and thirty-five
villages of Hauran were sacked before the Pasha of Damascus could
make any demonstrations for defence!
Meanwhile the Sublime Porte remained inactive and nothing was
done to regain the sacred territories. It was deemed impossible to
reach Mecca from Damascus with any large body of soldiers through
hostile territory where supplies were scarce. Salvation was expected
from Egypt; and it was hoped that an expedition by sea might
succeed in taking Jiddah and thence advance upon Mecca.
Mohammed Ali began preparations in 1810, and in the summer of
1811 an expedition under his son Touson Pasha was sent out from
Suez. In October the fleet arrived at Yenbo and the troops took the
town. Ghaleb the Sherif of Mecca proved false to the Wahabis and
made negotiations with the Turkish commander to hand over the
town. In January the army occupied Medina but at Bedr the troops
were attacked by Wahabis and utterly routed.
All through this first campaign the cruelty and treachery of the
Turks was shocking even to the mind of their Bedouin allies. None of
their promises were kept; the skulls of the enemy slain were
constructed into a sort of tower near Medina; Ghalib, the Sherif, was
betrayed and in violation of the most sacred promises he was taken
prisoner and deported; wholesale butchery of the wounded and
mutilation of the slain were common.
A second army under Mustafa Bey advanced toward Mecca and
also took possession of Taif. Although the five cities of the Hejaz
were now in the hands of the Turks the Wahabi power was not yet
broken. Mohammed Ali Pasha himself proceeded from Egypt with
another army; he had great difficulty in securing transportation and
provisions. Finally he landed his troops at Jiddah and went on to
Mecca, planning to attack Taraba the great Wahabi centre of the
south, as Deraiyah was the capital of the north. Here the enemy had
gathered in great numbers under an Amazon leader, a widow named
Ghalye who ruled the Begoum Arabs. She was reported to be a
sorceress among the Turks and stories of her skill and courage
inspired them with fear. When the attack was made the Wahabis
came off victorious and so harassed the army of occupation that
during 1813 and the beginning of 1814 they remained perfectly
inactive. Later the Turks made a sea attack on Gunfida, the port
south of Jiddah, and captured it. The Wahabis however captured the
wells that supplied the town, made a sortie and the Turkish troops
fled panic-stricken, to their ships. Discontentment arose among the
Turkish troops. Supplies failed and wages were in arrears.
Mohammed Ali changed now his tactics and tried to bribe the
Bedouin chiefs to desert the Wahabi leaders. At this time the Turkish
army consisted of nearly 20,000 men and yet the campaign dragged
on without a definite victory.[68]
The greatest battle was fought at Bissel near Taif where
Mohammed Ali defeated the Wahabis with great slaughter. Six
dollars were offered for every Wahabi head and before the day
ended 5,000 bloody heads were piled up before the Pasha. About
300 prisoners were taken and offered quarter. But on reaching
Mecca the cruel commander impaled fifty of them before the gates
of the city; twelve suffered a like horrible death at every one of the
ten coffee-houses, halting places between Mecca and Jiddah; the
remainder were killed at Jiddah and their carcasses left to dogs and
vultures.
But the battle went against the Turks when they met the desert
and its terrors. Hunger, thirst, fevers and the Bedouin robbers
attacked the camp. In one day a hundred horses died; the soldiers
were dissatisfied and deserted. At length Mohammed Ali made
proposals of peace to Abdullah bin Saud the Wahabi chief, and when
Saud entered Kasim with an army the negotiations were concluded
and peace was declared. But peace was not kept, and Ibrahim
Pasha, the son of Mohammed Pasha was despatched with a large
expedition against the Wahabis in August, 1816.
While Egypt was attacking the Wahabi strongholds from the west,
with infinite trouble and dubious results, the greatest loss the
Wahabi government had yet suffered, was from a blow dealt by the
British. In 1809 an English expedition went from Bombay against the
piratical inhabitants of their chief castle and harbor, Ras-el-Kheimah.
The place was bombarded and laid in ashes.
Ibrahim Pasha accomplished by intrigue and bribery what his
father failed to do by force of arms. After a series of advances one
tribe after another was detached from the Wahabi government. At
last without a battle the capital Deraiyah was taken, Abdullah
captured, sent to Constantinople and there publicly executed on
December 18th, 1818.
The Turks were naturally jubilant over their success and thought
they had made an end of the hated Wahabis. They soon learned
their mistake. No sooner was the army of Ibrahim Pasha withdrawn
than the old spirit rehabilitated the fallen empire with the old time
strength of fanaticism. The army of the Pashas could not govern or
even occupy the vast territories they had overrun. Within a few
years Turki the son of the late Amir was proclaimed Sultan of Nejd,
recovered all and more than his father’s territories, and by the
judicious payment of a small tribute and yet smaller honor to the
Egyptian Khedive retained the throne until he was murdered in
1831. His son and successor, Feysul, took the reins of government
and was rash enough to repudiate the Egyptian Suzerainty. Nejd was
again invaded. Hofhoof and Katif were temporarily occupied by
Egyptian and Turkish troops and Feysul was banished to Egypt.[69]
Feysul died in 1865, having returned from his banishment in 1843
and ruling alone and supreme for all those years. His son Abdullah,
who had acted as regent during the later years of Feysul, succeeded
to the throne. But there was a rival in his brother Saud. Intrigues,
treasons and violence were hatching in the palace courts even
before the death of Feysul. The dagger and the coffee-cup of
poisoned beverage have always been favorite weapons in seating
and unseating the rulers of Arabia. A prolonged fight ensued
between the two brothers. Saud was at first successful but Abdullah
flying to Turkey invited the aid of that power with the result that an
expedition from Bagdad ended in formally and permanently
occupying El Hassa as a Turkish province.
At the time of Saud’s death, in 1874, the conflict was renewed,
but Abdullah ultimately regained the supremacy and was ruler at
Riad until 1886, when events occurred that heralded the rise of
another power in Nejd, based on political intrigue and the sword
rather than on religion and fanaticism.
When Turki the Amir was murdered by his own cousin, Meshari,
and Feysul succeeded to the throne, there was present at Riad in the
army an obscure youth from Hail, Abdullah bin Rashid. He it was
who entered the palace by stealth, stabbed Meshari, and helped to
restore Feysul to his father’s seat as ruler. His valor and loyalty were
rewarded by bestowing upon him the governorship of his own native
province Shammar; he was also granted a small army to strengthen
the Wahabi rule in that region. He soon became almost as strong as
his master and showed himself an expert in all the intrigue and skill
possible to the Arabs. He extended his personal influence on all
sides, built a massive palace at Hail and defeated all who plotted his
destruction. Hired assassins dogged him on the streets, but Abdullah
escaped every danger and his star remained in the ascendant. In
1844 he died suddenly, leaving unaccomplished ambitions and three
sons, Telal, Mitaab, and Mohammed. Telal, the eldest son, was
proclaimed ruler and was ever more popular than his father had
been, and no less successful as a ruler. He strengthened his capital,
invited merchants from Busrah and Bagdad to reside there, and
gradually but surely established his entire independence of the
Wahabi ruler at Riad. Tormented, however, by an internal malady he
shot himself in 1867. His younger brother, Mitaab, who succeeded,
ruled very briefly and was murdered by his nephews, the sons of
Telal, within a year. Meanwhile, the third son of Abdullah bin Rashid,
Mohammed, had been a refugee at the Riad capital. But his
ambitions now found their opportunity and his true character was
revealed. By permission of the Amir Abdullah bin Feysul he went
back to Hail. He commenced by stabbing his nephew Bander who
had usurped the throne; he then killed the five remaining children of
his brother Telal and became undisputed Amir at Hail in 1868.
During the next eighteen years he consolidated his authority. His
rule was after the Arab heart—with a rod of iron and lavish
hospitality; continual executions and continual feasting.
The Arabs at Bahrein tell many almost incredible tales of
Mohammed bin Rashid’s stern justice and speedy method of
executing it, as well of his cruelty to those who resisted his will. In
those days the public executioner’s sword was always wet with
blood; men were tied to camels and torn asunder; but the desert-
roads were everywhere safe and robbers met with no mercy. As an
indication of his wealth and hospitality it is related that he
constructed in the courtyard of his palace a stone-cistern of great
size always kept filled with that best of Bedouin dainties, clarified
butter (dihn). A bucket and rope were at hand and oil was dealt out
as freely as water to the honored guests of the great ruler.
In the year 1886 the long-looked for opportunity came for
Mohammed bin Rashid to complete the work of Telal. He not only
aspired to be independent of the Riad rulers but to make Riad, the
Saud dynasty and all the Wahabi state a dependency of his Nejd
kingdom. In that year Amir Abdullah bin Feysul was seized and
imprisoned by two of his nephews, one of whom usurped the
throne. Mohammed, as a loyal subject, marched to the rescue,
deposed the pretender, but carried the Amir himself to Hail, leaving
a younger brother as his deputy governor. The great empire of the
Sauds was virtually ended; henceforth it was the green and purple
banner of Rashid and not the red and white standard of the Wahabis
that ruled all central Arabia.
Mohammed bin Rashid had shown supreme diplomatic ability in all
his dealings with the Turks from the day of his power until his death.
He humored their vanity by professing himself an ally of the Porte;
he paid a small annual tribute to the Sherif of Mecca in recognition
of the Sultan. But for the rest he never loved the Turk except at a
good distance. None of the Arabs of the interior have forgotten the
perfidy, treachery and more than Arab cruelty of the Egyptian Pashas
in their campaigns.
In 1890 a final attempt was made by the partisans of the old
dynasty to rebel against the Amir and secure the independence of
Riad. It was fruitless; and the severe defeat of the rebels proved it
final. In the year 1897 Mohammed bin Rashid died and his successor
Abd-el-Aziz bin Mitaab now rules his vast dominions. He is less stern
but not less able than his illustrious predecessor.
XX
THE RULERS OF OMAN

Before we turn to the history of the Turks in Arabia a word is


necessary regarding the rulers of Oman—that province unique in
Arabia for its isolation from all the other provinces in the matter of
politics. Prior to the appearance of the Portuguese in the Persian
Gulf (1506) Oman had been governed for nine hundred successive
years by independent rulers called Imams; elected by popular choice
and not according to family descent. From that time until 1650 the
Portuguese remained in power at Muscat. In 1741 Ahmed bin Said, a
man of humble origin, a camel-driver, rose by his bravery to be
governor of Sohar, drove the Persians who had succeeded the
Portuguese, out of Muscat and founded the dynasty that has ever
since ruled Oman. As early as 1798 the East India Company made a
treaty with the Sultan of Muscat to exclude the French from Oman.
This fact is important to show the character of the recent incident at
Muscat.
Seyid Said, who ruled from 1804 to 1856, had constant struggles
against the Wahabi power who threatened his territory. With
England he joined the war against the Wahabi pirates; and made
treaties in 1822, 1840 and 1845 to suppress the slave-trade. On the
death of Said the Sultanate of Oman and Zanzibar was divided.
Seyid Thowani reigned at Muscat while a younger brother reigned at
Zanzibar. Thowani was assassinated at Sohar in 1866. Salim, his son,
succeeded him, although he was suspected of patricide. Then there
was an interregnum under a usurper until Seyid Turki another son of
Said took the throne in 1871. Continual rebellion marked his period
of rule. But he was friendly to the English and in return for the
abolition of free traffic of slaves between Africa and Zanzibar the
English government allowed him an annual subsidy of a little over
£6,000 a year. In 1888 the Sultan died and his son, Feysul bin Turki,
succeeded him. His rule was mild, from the palace at Muscat his
influence was not far-reaching; rebellions, inter-tribal wars and plots
of one mountain-chief against another mark all the years of his reign
up to date. In February, 1895, there was a serious Bedouin uprising
in which the Arabs took the town and looted it. The Sultan himself
barely escaped and was for a time a prisoner in his fort while the
town was in the hands of the enemy. The cause of the trouble was a
difference as to the amount of yearly tribute a certain Sheikh Saleh
of Samed should pay the Muscat ruler. From November, 1894, the
rebels collected arms and strengthened their numbers until on
February 12th of the following year they were ready to strike the
desired blow. As this episode was characteristic of all Arab warfare
we quote a brief account of it sent at the time by a resident at
Muscat to the Bombay press:
“On February 12th Abdullah, the leader of his father’s
(Sheikh Saleh’s) troops, with a retinue of perhaps 200
armed Bedouins arrived at Muscat in a scattered and
peaceable manner, and obtained an audience with the
Sultan. A musket salute was fired, and no attack was
thought of. The Sultan presented the leader with a purse
of $400 and a liberal allowance of rice, dates, coffee, and
the famous Muscat “halwa” for the men. The Bedouins
although armed were allowed to go and come as they
choose and no attack was feared. Sheikh Abdullah himself
sat for a time in the bazaar and received the salaams of
the people who kissed his hand in respect. When evening
came the Sultan requested the men to encamp outside of
the gates, the only means of entrance and exit through
the old Portuguese walls. Although failing to comply with
the request the Bedouins claimed none but peaceful
intentions. At 8 p. m. when according to custom the gates
were closed, perhaps one-half of the Bedouins were within
the walls. This was their Trojan horse. Shortly after
midnight the gates were attacked, the few customary
guards being easily overcome, and thrown open to the
large numbers of Bedouins who up to this time had been
hiding in a neighboring mosque. Both the small gate
leading to the bazaar and the larger one to the west of
the town were easily taken, and the Bedouins then
advanced to the Sultan’s palace, effected an entrance and
rudely awoke the Sultan and his family from their sleep.
Seyyidi Esel after a courageous struggle of a few minutes,
(in which he shot two of the attacking party,) escaped by
a small door opening to the sea and fled to one of the two
forts which command the city as well as the harbor. His
brother escaped to the other. Each of these forts is
manned by a force of perhaps fifty men and has several
old twelve pounder Portuguese guns.
“The forts opened fire at once upon the palace which
the Bedouins now occupied. The Bedouins took
possession of the town closing the gates and stationing
armed men through the bazaar and streets in the early
hours of the 13th of February.
“A few shops containing muskets and ammunition were
opened, and the contents robbed. The Sultan’s palace was
completely looted and all his personal property either
destroyed or sold at any price. On account of the
suddenness of the attack there was but a small number of
the Sultan’s soldiers in readiness. These repaired to the
forts and opened fire upon the Bedouin invaders with both
the guns of the foils and muskets. For three days we were
the witnesses of the extraordinary spectacle of a Sultan
bombarding his own palace; no attempt was made to
meet the rebels on the streets. By order of the invading
captain the portion of the town inhabited by British
subjects was not entered. Until Sunday evening things
remained about the same. The attack from the forts was
continued day and night. The Bedouins did not answer the
fire but remained in the palace and streets holding
possessions but making no attack on the forts. Within the
town, although it is in possession of the enemy, all was
orderly and quiet. Unarmed people were allowed to pass
to and fro and guards were stationed in the bazaar to
prevent plunder. Reinforcements were expected by both
parties. On Monday morning a body of about 1,000
arrived from the coast towns in aid of the Sultan. They
encamped beneath the fort in command of the Sultan,
and at about 8 a. m. made an attack on the invaders, which
became so serious a danger to the British subjects that
the Political Agent Major J. H. Sadler ordered a cessation
of hostilities at 1 p. m. until 8 p. m. giving the British
subjects an opportunity to sojourn to the sheltered village
of Makalla. More reinforcements to the Sultan’s troops
arrived at 6 p. m. and encamped beneath the fort throwing
temporary barricades across the streets at several
advantageous points. The main body of the Bedouins
were waiting to reinforce just outside Matral which village
was however still in the hands of the Sultan. At 8 a. m. on
Monday H. M. S. Sphina arrived from Bushire and at 2 p. m.
the R. I. M. S. Lawrence.”
The British gunboats, contrary to the expectations and
fond hopes of the population of Muscat, did not interfere
in the matter. For reasons of diplomacy they left the
Sultan to fight his own battles and when the rebels were
finally persuaded to leave saddled the poor Sultan with a
large bill for the damage incurred by British subjects
during the attack.
In 1894 a French consulate was established at Muscat;
as the French have no commerce to speak of in this part
of the world the object of the consulate was evidently
political. Of the intrigues that resulted, the alleged sale of
a coaling-station to France and the British attitude toward
the matter we will speak later.
XXI
THE STORY OF THE TURKS IN ARABIA

“No one travels in Turkey with his eyes open


without seeing that her government is a curse on
mankind. Fears, feuds and fightings make
miserable the councils of her rulers. They are
bloodsuckers fastened on the people throughout
her dominions drawing from each and all the last
drop of blood that can be extracted. Turkey
skillfully and systematically represses what
Christian nations make it their business to nurture
in all mankind as manhood. In her cities there are
magnificent palaces for her sultans and her
favorites. But one looks in vain through her realm
for statues of public benefactors. There are no
halls where her citizens could gather to discuss
policies of government or mutual obligations.
Their few newspapers are emasculated by
government censors. Not a book in any language
can cross her borders without permission of
public officers, most of whom are incapable of
any intelligent judgment of its contents. Art is
scorned. Education is bound. Freedom is a crime.
The tax gatherer is omnipotent. Law is a farce.
Turkey has prisons instead of public halls for the
education of her people. Instruments of torture
are the stimulus to their industries.”—The
Congregationalist, April 8, 1897.
In reviewing the story of the Turks in Arabia, we will
begin with Hejaz, the most important province of Turkey
in Arabia, continue with Yemen, the most populous, and
end with the Mesopotamian vilayets which were her
richest possessions.
It is not generally understood how highly the Sultan
values his Arabian provinces. It is on them and on them
alone that he can base his claim to the title of caliph. The
possession of the Holy Cities in the hands of the Sultan
makes him the chief Mohammedan ruler; there his name
is blessed daily in the great mosques; in the eyes of all
the pilgrims from every part of the Moslem world Turkey is
the guardian of the Kaaba. How many thousands of
Mohammedans daily in the mosques of India and Java call
for blessings on the head of Abd-ul-Hamid the Caliph who
would never pray for Abd-ul-Hamid the Sultan.
Mecca, and Hejaz generally, was governed by the early
Caliphs until 980 a. d., when it passed under the rule of
the first Sherif, Jaafar.[70] Under Suleiman the magnificent
(1520-1566) the Ottoman Empire reached the zenith of its
power and greatness; at that time Arabia too was
reckoned a Turkish possession, and the entire peninsula
was included on the maps of Turkish Asia. But, as we have
seen, at the beginning of the present century the Wahabis
and not the Turks were the real rulers of Arabia. The
Arabs have never taken kindly to the rule of the Turk, but
the province of Hejaz, once snatched from the hand of the
Wahabis, has ever since been held by the Sublime Porte.
Plots of rebellion have been thick and Sherifs have
succeeded Sherifs but the fort that frowns over Mecca has
always a strong Turkish garrison and the Pashas eat the
fat of the land at the expense of the people.
Actual Turkish rule was declared over the whole of
Hejaz in 1840. At that time Abd-el-Mutalib was made
Great Sherif of Mecca, but there was continual trouble
between the Sherif and the Pasha. The religious head of
the holy city would not bow to the political head; the anti-
slave trade regulations although only very slightly
enforced caused riots. The Sherif was deposed and
Mohammed bin ’Aun declared ruler in his place. On June
15th, 1858, the murder of certain Christians at Jiddah
brought England into collision with the rulers of Hejaz.
Jiddah was bombarded and the gate to the holy city was
held by the Christian powers until the required indemnity
was paid and the murderers punished. The next Sherif
appointed was Abdullah. During his time the opening of
the Suez Canal brought Turkey much nearer to Mecca and
inspired the religious zealots with the fear that now the
Christian fleets would attack the whole coast of Hejaz! For
had not the vizier of Haroun el Rashid dissuaded that
monarch from his plan to dig the canal lest the gateway to
the Holy Cities would then be too accessible to the
infidels?
The Ottoman government introduced other horrors into
the quiet seclusion of the ancient city of Mecca; Jiddah
was connected with the Red Sea cable; a wire carried the
world to Mecca and put the Pasha in daily touch with the
Sublime Porte; afterward it was extended to Taif, and the
Turks were masters of their own army corps, so that the
Sherifs could not act in secret. It was even attempted to
raise a Meccan regiment for the Russian war.
In 1869 the whole complicated bureaucratic system was
introduced at Medina, Jiddah, Mecca and Taif. Abdullah
was a great favorite as Sherif, both to the Arabs and the
Turks; he was mild and given to all sorts of compromise so
that he managed to please both parties which are always
at war in Mecca. His brother Husein succeeded as Sherif
but was murdered in 1880. In the same year the aged
Abd-el-Mutalib for the third time became Sherif and
although at first very popular he soon won the hatred of
the conservative Meccans by his cruelty and of the Turks
by his double-dealing. On request of the people of Mecca
for his deposition, Othman Pasha came to Hejaz and
although he did not depose the aged Sherif, managed to
outwit him in governing the city. In 1882 Aun-er-Rafik, a
brother of Husein, became Sherif. Troubles between the
dual powers of government became thick and the Bedouin
tribes took the occasion for a general uprising. Rafik fled
to Medina and could not return until Othman Pasha was
deposed. Since then the old struggle continues.
The Arabs in Hejaz have no love for the Turks or for any
Turkish ruler; the Bedouin tribes hate the very sight of a
red fez and the town-dweller is ground down with
taxation. Aside from militarism there have been no public
improvements in either of the Holy Cities since the Star
and Crescent waved from their forts. The “pantaloon-
wearing” Turks are considered little better than “Christian
dogs” by the pious folk of Mecca. Have they not
introduced the abomination of quarantine instead of the
old time simple trust in Allah? Have they not acquiesced to
the residence of Christian consuls at Jiddah? And what is
worse, have they not interfered with the free importation
of slaves and the manufacture of eunuchs for the
residents of Mecca?
The following literal translation of a placard posted
everywhere in Mecca, at the end of the year 1885, may
give the best insight into the relations that exist between
the Turk and the Arab in the cradle of Islam:
“‘And who does not rule according to the
revelation of Allah he is an infidel.’—Koran v. 48.
“Be it known to you, ye people of Mecca, that
this accursed Wali intends to introduce Turkish
laws into the holy city of Allah, therefore beware
of sloth and awake from sleep. Do not suffer the
laws to be executed for they are only the opening
of the door to further legislation. Our proof is that
the Wali Othman Pasha proposed his plan to
divide Mecca into four quarters and to appoint
three officers for each quarter. This plan he laid
before the city council and when they declared it
was impossible to do this in Mecca the accursed
replied, Is Mecca better than Constantinople? We
will carry the plan through by force. For this
reason, O Meccans, an association has been
formed called the Moslem Club and whoever
desires to enter it let him make inquiries. The
object of the association is to assassinate this
cursed Wali and his chief of police. He who
cannot join us let him utter his complaint before
Allah in the holy house that the public safety is
endangered while the present ruler lives. And this
cursed Wali also attempts to secure the
administration of the annual corn-shipment from
Egypt. And remember also how the accursed
butchered the sons of the Sherif and his slaves
and exposed their heads at Mecca. What sort of
deeds are these? More atrocious than those at
Zeer. So that whoever kills this man will enter
paradise without rendering an account. The
purpose of dividing the city appointing Sheikhs
for each quarter is nothing else than a pretext for
new taxations as the Cursed himself let out
before the council.
“In the name of the
“Jemiat-el-Islamiyeh.”
The same people who promised paradise to the
murderer of Othman Pasha rebelled against his successor
Safwet Pasha and will rebel as long as the character of the
Meccan remains what it is. Those who dream that the
Turk will make Mecca the centre of their power when
Constantinople falls, know not the condition of affairs
among the proud fanatics of Hejaz who will never allow
Mecca to become anything but the city of the Sherifs. And
as for the Bedouin tribes, they blackmail every pilgrim
caravan and draw heavy subsidies from Constantinople to
keep the peace. Jiddah is in decay and the pilgrim-traffic
is not as flourishing as it was a decade ago. Even in Hejaz
the days of Ottoman rule are numbered.
Between Hejaz and Yemen is the region of Asir. Its
population has been celebrated from the earliest times for
personal bravery and courage. Mountain-dwellers they
love freedom; belonging to the Zaidee sect they hate the
Sunnites. And these two reasons united made them
abominate the Turks. In order to extend Ottoman power
southward and reconquer Yemen for the Sublime Porte it
was necessary to pass through the territory of the Asir
Arabs. From 1824 to 1827 the Turkish troops carried six
successive campaigns against the brave highlanders but
were in every case repulsed with great loss. In 1833 and
1834 the attempt was again made; a desperate battle was
fought on August 21st of the latter year, the Turkish
troops were victorious. But the Arabs rallied, made sorties
on the garrisons, famine reigned, fever killed off many and
in September the Turks again withdrew, defeated. In 1836
a final attempt was made to conquer Asir; this was with
greater loss than ever before. To this day the entire region
between Taiz and Roda (a few miles north of Sana) is
really independent, although marked as Turkish on the
maps. The Ottoman troops are bold to fight the Yemen
Arabs to the very gate of Sana but they grow pale when
they hear of an expedition against the dare-devil Bedouins
of Asir who fight with the ferocity of the American Indian
and the boldness of a Scotch Highlander.
The story of the Turks in Yemen is very modern. In
1630 they were compelled to evacuate Yemen by the
Arabs and they did not set foot in the capital again until
1873. In 1871 the Imam of Yemen lived his life in peace,
secluded and sensual like an oriental despot in the palace
at Sana. Looked upon by the Arabs as a spiritual Sultan he
was great, but also powerless to hold in check the
depredations and robberies of the many tribes under his
nominal sway. Things went from bad to worse. Trade
almost ceased on account of the attacks on the caravans
that left for the coast. The Sana merchants, quiet and
respectable Arabs, saw nothing but ruin before them, and
considering solely the benefits that would accrue to
themselves by such a step invited the Turks to take the
place. They did not consult the large agricultural
population or the effect of Turkish rule on the peasantry,
otherwise there would have been an equally cordial
invitation to the Turks to stay out of Yemen.
The Turks needed no urging at this time, when they
were strengthening their hold on Mesopotamia, extending
their conquests in Hassa and trying to obtain the mastery
of the Hejaz Bedouins. It fell in most admirably with their
plans, and an expedition set out at once. In March, 1872,
an army under command of Ahmed Mukhtar Pasha
reached Hodeidah. On April 25th the army entered Sana
twenty thousand strong and the city opened its gates
without a battle. The conquest of the country now
proceeded; a force was sent to the region of Kaukeban,
north of Sana, another to the southern district of Anes
and still another to Taiz and Mocha. The conquest toward
the south was limited by the presence of England at Aden.
For when the Turkish army advanced to the domain of the
independent Sultan of Lahaj who had a treaty with
England, the British Resident at Aden sent a small force of
artillery and cavalry to occupy the Lahaj territory. In
consequence of representations made at the same time by
the English government to the Sublime Porte, the Turkish
army withdrew in December, 1873. In 1875 the tribes
bordering the southern boundary of Yemen rebelled
against Turkey but the rebellion was crushed.
When the army took Sana the Imam was deposed, but
on account of his religious influence over the Arabs was
permitted to reside in the city, receiving a pension on
condition that he would exert himself in behalf of Ottoman
rule. This he fulfilled until his death when the birthright as
Imam passed to his relative Ahmed-ed-Din who also was
nothing loth to receive the honor of the Arabs and the
money of the Turks.
Sana received a certain amount of civilization, more
prestige and still more commercial prosperity than in the
older days. As for the country in general it was divided
and subdivided into provincial districts and sub-districts;
the peasantry were taxed and taxed again; military roads
were constructed by forced labor. The hill-tribes, who in
the times of the Imam had been left undisturbed in their
agriculture and who boasted an independence of
centuries, were now little better than slaves. Extortion
ruined them, they hated the personality of the Turks
whose religion was not as their own; discontent
smouldered everywhere and was ready to burst into a
flame. And this discontent was increased from year to
year as the caravan-drivers returned from their long
journeys to Aden and told of the greatest marvel ever
heard of—a righteous government and a place where
justice could not be bought, but belonged to every one—
even the black skinned ignorant Somali. When we
remember that over 300,000 camels with their drivers
enter Aden from the north every year we can realize how
widespread was this news. I can testify to the world-wide
difference between the municipal government of Aden
cantonment and that of the capital of Yemen under the
Turks as I saw it in 1891. When the Turks accused
England of fomenting the recent rebellions in Yemen they
were right to the extent that if the Yemen peasantry had
not seen the blessed union of liberty and law at Aden they
would not seek to rise against the Turks.
In the summer of 1892 a body of 400 Turkish troops
were sent to collect by force the taxes due from the Bni
Meruan who inhabit the coast north of Hodeidah. The
Turks were surprised by a large body of Arabs and nearly
annihilated. Wherever the news travelled the people rose
in arms. Tribal banners long laid away were unfurled and
the cry “long live the Imam” rang through mountain and
valley. A new Jehad was proclaimed and Ahmed-ed-Din
was unwillingly forced to take the leadership against the
Turks. When the rebellion broke out the Turks had only
about 15,000 men in the whole of Yemen; and cholera
had wrought havoc among these. Ill-fed, ill-clothed, and
unpaid; badly housed in the rainy and cold mountain
villages, they could nevertheless fight like devils when led
by their commanders. The Imam escaped from Sana, and
a few days later the capital was besieged by an enormous
force of Arabs. All the unwalled cities fell an easy prey to
the rebels, Menakha was taken after a short struggle; Ibb,
Jibleh, Taiz, and Yerim all declared themselves for the
Imam. The Arabs treated their foes with respect after their
victory;[71] they were feeding Turkish prisoners at the
Imam’s expense and in many cases money was given the
soldiers to enable them to escape to Aden.
Meanwhile telegrams were sent to Constantinople from
Sana and Hodeidah beseeching assistance. The whole of
Yemen, with the exception of the capital and two smaller
towns in the north with Hodeidah on the coast, was in the
hands of the rebels. An expedition reached Hodeidah,
under command of Ahmed Feizi Pasha, formerly governor
of Mecca, which after bombarding the villages on the
coast north of Hodeidah, marched to the relief of Sana.
Without opposition the army reached Menakha and took
the town by storm; matchlocks and fuse-guns could not
hold out against field-guns and trained troops. About
thirty miles beyond a desperate attempt was made to stop
the army of relief; in a narrow defile the rebels under
Seyid es-Sherai took up their position and for twelve days
withstood cavalry, infantry and artillery assaults; then they
were driven back and retired into the mountains. By
hurried marches the troops reached Sana and took the
city. Military law was proclaimed and a universal massacre
of prisoners took place. A reward was offered for the head
of every rebel. Camel-loads of heads were brought into
Sana every day. The troops were turned loose to plunder
the villages. There is no nation in the world that can put
down a rebellion as rapidly as the Turks when they have a
good-sized army, but they have great objection to any one
seeing the process.
By the end of January, 1893, all the cities of Yemen
were reconquered and the main roads were again open.
But the spirit of rebellion lived on and the brave
mountaineers withdrew to the inaccessible defiles and
peaks only to plot further mischief. Telegraph-wires were
cut; soldiers were shot on the road; and once and again
bold attempts were made to blow up the Pasha’s house in
Sana with gunpowder. In 1895 there was rebellion in the
north. In 1897-98 all Yemen was again in arms and the
uncertain and conflicting reports that reach the coast only
emphasize the serious character of the uprising.
On the map and in Turkish official reports the
boundaries of Yemen join those of Hejaz and extend many
miles east of Sana. This has never been and is not now
correct. Twenty-five miles north and east of Sana there is
Welcome to our website – the ideal destination for book lovers and
knowledge seekers. With a mission to inspire endlessly, we offer a
vast collection of books, ranging from classic literary works to
specialized publications, self-development books, and children's
literature. Each book is a new journey of discovery, expanding
knowledge and enriching the soul of the reade

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.

Let us accompany you on the journey of exploring knowledge and


personal growth!

ebookgate.com

You might also like