100% found this document useful (2 votes)
34 views64 pages

Instant Ebooks Textbook Data Structures Other Objects Using Java 4th Edition Michael Mann Download All Chapters

ebook

Uploaded by

takaliako
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
Download as pdf or txt
100% found this document useful (2 votes)
34 views64 pages

Instant Ebooks Textbook Data Structures Other Objects Using Java 4th Edition Michael Mann Download All Chapters

ebook

Uploaded by

takaliako
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
Download as pdf or txt
Download as pdf or txt
You are on page 1/ 64

Full download ebook at ebookgate.

com

Data Structures Other Objects using Java 4th


Edition Michael Mann

https://ebookgate.com/product/data-structures-
other-objects-using-java-4th-edition-michael-mann/

Download more ebook from https://ebookgate.com


More products digital (pdf, epub, mobi) instant
download maybe you interests ...

Data Structures and Other Objects Using C 4th Edition


Michael Main

https://ebookgate.com/product/data-structures-and-other-objects-
using-c-4th-edition-michael-main/

Data Structures Problem Solving Using Java 4th Edition


Mark Allen Weiss

https://ebookgate.com/product/data-structures-problem-solving-
using-java-4th-edition-mark-allen-weiss/

Java Software Structures Designing and Using Data


Structures 3rd Edition John Lewis

https://ebookgate.com/product/java-software-structures-designing-
and-using-data-structures-3rd-edition-john-lewis/

Data Structures and Algorithms Using C 1st Edition


Michael Mcmillan

https://ebookgate.com/product/data-structures-and-algorithms-
using-c-1st-edition-michael-mcmillan/
Java Structures Data Structures in Java for the
Principled Programmer 2nd edition Duane Bailey

https://ebookgate.com/product/java-structures-data-structures-in-
java-for-the-principled-programmer-2nd-edition-duane-bailey/

Data Structures Outside In with Java 1st Edition Sesh


Venugopal

https://ebookgate.com/product/data-structures-outside-in-with-
java-1st-edition-sesh-venugopal/

Data structures and abstractions with Java 2nd ed


Edition Carrano

https://ebookgate.com/product/data-structures-and-abstractions-
with-java-2nd-ed-edition-carrano/

Data Structures Using C 2nd Edition D. S. Malik

https://ebookgate.com/product/data-structures-using-c-2nd-
edition-d-s-malik/

C Programming Data Structures 4th Edition E.


Balagurusamy

https://ebookgate.com/product/c-programming-data-structures-4th-
edition-e-balagurusamy/
Preface i

USING
J2SE 7.0
FOURTH
EDITION DATA
STRUCTURES
&
OTHER
OBJECTS
Using Java™

MICHAEL MAIN
University of Colorado at Boulder
ii Preface

Editorial Director: Marcia Horton Manufacturing Manage: Nick Sklitsis


Editor in Chief: Michael Hirsch Operations Specialist: Lisa McDowell
Acquisitions Editor: Tracy Dunkelberger Creative Director: Jayne Conte
Editorial Assistants: Stephanie Sellinger/Emma Snider Cover Designer: Bruce Kenselaar
Director of Marketing: Patrice Jones Manager, Rights and Permissions: Karen Sanatar
Marketing Manager: Yezan Alayan Cover Art: © Shutterstock/Ford Prefect
Marketing Coordinator: Kathryn Ferranti Media Editor: Dan Sandin
Vice President, Production: Vince O’Brien Printer/Binder: RR Donnelley, Harrisonburg
Managing Editor: Jeff Holcomb Cover Printer: RR Donnelley, Harrisonburg
Associate Managing Editor: Robert Engelhardt

Credits and acknowledgments borrowed from other sources and reproduced, with permission, in this textbook
appear on the appropriate page within text.

Java is a trademark of the Oracle Corporation, 500 Oracle Parkway, Redwood Shores, CA 94065.

Copyright © 2012, 2006, 2003, 1999 by Pearson Education, Inc., publishing as Addison-Wesley. All rights
reserved. Manufactured in the United States of America. This publication is protected by Copyright, and
permission should be obtained from the publisher prior to any prohibited reproduction, storage in a retrieval
system, or transmission in any form or by any means, electronic, mechanical, photocopying, recording, or
likewise. Tp obtain permission(s) to use material from this work, please submit a written request to Pearson
Education, Inc., Permissions Department, One Lake Street, Upper Saddle River, New Jersey 07458, or you
may fax your request to 201-236-3290.

Many of the designations by manufacturers and sellers to distinguish their products are claimed as trademarks.
Where those designations appear in this book, and the publisher was aware of a trademark claim, the
designations have been printed in initial caps or all caps.

Library of Congress Cataloging-in-Publication Data

Main, M. (Michael)
Data structures & other objects using Java : using J2SE 7.0 / Michael
Main.-- 4th ed.
p. cm.
Includes bibliographic references and index.
ISBN 978-0-13-257624-6 (alk. paper)
1. Java (Computer program language) 2. Data structures (Computer
science)
I. Title. II. Title: Data structures and other objects using Java.
QA76.73.J38M33 2012
005.13'3--dc23
2011037942

10 9 8 7 6 5 4 3 2 1

ISBN-10: 0-13-257624-4
ISBN-13: 978-0-13257624-6
Preface

J ava provides programmers with an immediately attractive


forum. With Java and the World Wide Web, a programmer’s work can have
quick global distribution with appealing graphics and a marvelous capability for
feedback, modification, software reuse, and growth. Certainly, Java’s other
qualities have also contributed to its rapid adoption: the capability to implement
clean, object-oriented designs; the familiarity of Java’s syntactic constructs; the
good collection of ready-to-use features in the Java Class Libraries. But it’s the
winsome ways of the World Wide Web that have pulled Java to the front for
both experienced programmers and the newcomer entering a first-year com-
puter science course.
With that said, it’s satisfying to see that the core of the first-year courses
remains solid even as courses start using Java. The proven methods of represent-
ing and using data structures remain vital to beginning programmers in a data
structures course, even as the curriculum is shifting to accommodate an object-
oriented approach.
This book is written for just such an evolving data structures course, with the
students’ programming carried out in Java. The text’s emphasis is on the speci-
fication, design, implementation, and use of the basic data types that are normally
covered in a second-semester, object-oriented course. There is wide coverage of
important programming techniques in recursion, searching, and sorting. The text
also provides coverage of big-O time analysis of algorithms, an optional appen-
dix on writing an interactive applet to test an implementation of a data structure,
using Javadoc to specify precondition/postcondition contracts, and a new intro-
duction to the increasingly important topic of concurrency.
The text assumes that the student has already had an introductory computer
science and programming class, but we do include coverage of those topics (such
as the Java Object type and a precise description of parameter passing) that are
not always covered completely in a first course. The rest of this preface discusses
ways that this material can be covered, starting with a brief review of how con-
temporary topics from earlier editions are intermixed with new material from the
new Java 2 Standard Edition 7.0. iii
iv Preface

New to the Fourth Edition


This edition retains contemporary topics from earlier editions that define a
coherent approach to the implementation and use of data structures in Java.
These topics, listed below, have been updated to align with the latest software
engineering practices suggested by the designers and implementors of Java 2
Standard Edition 7.0. The most important of these topics are listed here:
• Better input/output support (Chapter 1 and Appendix B) continues in
this edition, including formatted output (with the System.out.printf
method) and the input of primitive values (with the java.util.Scanner
class). Our earlier input and output classes (EasyReader and Format-
Writer) are still available online at www.cs.colorado.edu/~main/edu/
colorado/io.
• Earlier integration of the Java Class Libraries begins in Chapter 2 of
this edition. Although the emphasis of this textbook remains on the under-
lying design and implementation of classic data structures, we’ve found it
increasingly important to give students significant exposure to the ele-
ments of class libraries. We begin this process in Section 2.5 with the
easy-to-use BigInteger class. Chapters 3 to 5 give more examples that
use the Java Class Libraries, including Arrays, HashSet, ArrayList,
LinkedList, ListIterator, and others.
• A modified approach to generic collection classes occurs in Chapter 5
of this edition. Starting with J2SE 5.0, generic methods and generic
classes allowed libraries to depend on an unspecified underlying data type
(that we’ll call E). Originally, collection classes were often implemented
with arrays in which the component type was an unspecified generic type
(i.e., a private member variable of type E[ ]).
Over the years, it was recognized that the E[ ] practice had a potential
pitfall: We could use a typecast to pretend that we had that kind of array,
but at run time, the program really had an array of Java objects (i.e., a pri-
vate member variable of type Object[ ], which by design contains only E
objects). Within the generic class itself, this type mismatch did not cause a
problem (because generic types are not checked at run time). But if the
generic class provides the array to an outside application, then the possi-
bility of a runtime type error existed.
The solution, eloquently written about by Neal Gafter, is for the
generic class to use an array of Java objects (rather than an array of type
E[ ]) along with specific programming practices (described in Chapter 5)
that ensure that unchecked typecasts cannot lead to runtime type errors.
Starting in Chapter 5 and continuing throughout the rest of the textbook,
we now use this new approach for all of our generic classes.
• Variable arity methods (Chapter 3) allow a method to have a variable
number of arguments. Generic classes have special considerations for
Preface v

variable arity methods that are newly discussed in Chapter 5 of this edi-
tion.
• Enhanced for-loops (Chapters 3 and 5) were introduced in the previous
edition of this textbook. They allow easy iteration through the elements of
an array, through a collection of elements that has implemented the Iter-
able interface, or through the elements of an enum type.
• Autoboxing and auto-unboxing of primitive values (Chapter 5) continue
to be used in this edition to allow the storage and retrieval of primitive
data values (such as an int) in Java’s generic collections (such as the
Vector).
• Java’s priority queue (Chapter 7) has been added as a new topic in the
fourth edition.
• The binary search and sort methods from the Java Class Libraries
have a new presentation in Chapters 11 (searching) and 12 (sorting).
• The important new topic of concurrency is introduced through a con-
current sort in Chapter 12. The approach uses the RecursiveAction and
ForkJoinPool classes from Java2SE 7, which provides an extremely
clean introduction with very few distractions for the first-year student.
• Covariant return types allow the return type of an overridden inherited
method to be any descendant class of the original return type. We use this
idea for clone methods throughout the text, thereby avoiding a typecast
with each use of a clone method and increasing type security. The larger
use of the technique is postponed until the chapter on inheritance (Chapter
13).
• Enum types (Chapter 13) provide a convenient way to define a new data
type whose objects may take on a small set of discrete values.

Beyond these new, coherent language features, the fourth edition of this text
presents the same foundational data structures material as the earlier editions. In
particular, the data structures curriculum emphasizes the ability to specify,
design, and analyze data structures independently of any particular language, as
well as the ability to implement new data structures and use existing data struc-
tures in any modern language. You’ll see this approach in the first four chapters
as students review Java and then go on to study and implement the most funda-
mental data structures (bags and sequence classes) using both arrays and linked-
list techniques that are easily applied to any high-level language.
Chapter 5 is a bit of a departure, bringing forward several Java-specific tech- new material on
niques that are particularly relevant to data structures: how to build generic col- Java interfaces
lection classes based on Java’s new generic types, using Java interfaces and the and the API
API classes, and building and using Java iterators. Although much of the subse- classes
vi Preface

quent material can be taught without these Java features, this is a natural time for
students to learn them.
Later chapters focus on particular data structures (stacks, queues, trees, hash
tables, graphs) or programming techniques (recursion, sorting techniques, inher-
itance). The introduction of recursion is delayed until just before the study of
trees. This allows us to introduce recursion with some simple but meaningful
examples that do more than just tail recursion. This avoids the mistaken first
impression that some students get of recursion being some kind of magic loop.
After the first simple examples (including one new example for this edition), stu-
dents see significant examples involving two recursive calls in common situa-
tions with binary trees.
new projects for Trees are particularly emphasized in this text, with Chapter 10 taking the stu-
trees and other dents through two meaningful examples of data structures that use balanced trees
areas (the heap project and the B-tree project). Additional projects for trees and other
areas have also been added online at http://cssupport.pearsoncmg.com..
Other new Java features have been carried over from the third edition of the
text as needed: the use of assertions to check preconditions, a more complete
coverage of inheritance, a new example of an abstract class to build classes that
play two-player strategy games such as Othello or Connect Four, an introduction
to new classes of the Java API (now in the generic form of ArrayList, Vector,
HashMap, and Hashtable), and new features of Javadoc.
All these new bells and whistles of Java are convenient, and students need to
be up-to-date—but it’s the approaches to designing, specifying, documenting,
implementing, using, and analyzing the data structures that will have the most
enduring effect on your students.

The Five Steps for Each Data Type


The book’s core consists of the well-known data types: sets, bags (or multisets),
sequential lists, stacks, queues, tables, and graphs. There are also additional
supplemental data types, such as a priority queue. Some of the types are
approached in multiple ways, such as the bag class that is first implemented by
storing the elements in an array and is later reimplemented using a binary search
tree. Each of the data types is introduced following a pattern of five steps.

Step 1: Understand the Data Type Abstractly. At this level, a student gains
an understanding of the data type and its operations through concepts and pic-
tures. For example, a student can visualize a stack and its operations of pushing
and popping elements. Simple applications are understood and can be carried
out by hand, such as using a stack to reverse the order of letters in a word.

Step 2: Write a Specification of the Data Type as a Java Class. In this step,
the student sees and learns how to write a specification for a Java class that can
implement the data type. The specification, written using the Javadoc tool,
includes headings for the constructors, public methods, and sometimes other
public features (such as restrictions tied to memory limitations). The heading of
Preface vii

each method is presented along with a precondition/postcondition contract that


completely specifies the behavior of the method. At this level, it’s important for
the students to realize that the specification is not tied to any particular choice of
implementation techniques. In fact, this same specification may be used several
times for several different implementations of the same data type.

Step 3: Use the Data Type. With the specification in place, students can write
small applications or applets to show the data type in use. These applications are
based solely on the data type’s specification because we still have not tied down
the implementation.

Step 4: Select Appropriate Data Structures and Proceed to Design and


Implement the Data Type. With a good abstract understanding of the data
type, we can select an appropriate data structure, such as an array, a linked list of
nodes, or a binary tree of nodes. For many of our data types, a first design and
implementation will select a simple approach, such as an array. Later, we will
redesign and reimplement the same data type with a more complicated underly-
ing structure.
Because we are using Java classes, an implementation of a data type will have
the selected data structures (arrays, references to other objects, etc.) as private
instance variables of the class. In my own teaching, I stress the necessity for a
clear understanding of the rules that relate the private instance variables to the
abstract notion of the data type. I require each student to write these rules in clear
English sentences that are called the invariant of the abstract data type. Once the
invariant is written, students can proceed to implementing various methods. The
invariant helps in writing correct methods because of two facts: (a) Each method
(except the constructors) knows that the invariant is true when the method begins
its work; and (b) each method is responsible for ensuring that the invariant is
again true when the method finishes.

Step 5: Analyze the Implementation. Each implementation can be analyzed


for correctness, flexibility, and time analysis of the operations (using big-O
notation). Students have a particularly strong opportunity for these analyses
when the same data type has been implemented in several different ways.

Where Will the Students Be at the End of the Course?


At the end of our course, students understand the data types inside out. They
know how to use the data types and how to implement them in several ways.
They know the practical effects of the different implementation choices. The
students can reason about efficiency with a big-O analysis and can argue for the
correctness of their implementations by referring to the invariant of the ADT.
viii Preface

the data types in One of the lasting effects of the course is the specification, design, and imple-
this book are mentation experience. The improved ability to reason about programs is also
cut-down important. But perhaps most important of all is the exposure to classes that are
versions of the easily used in many situations. The students no longer have to write everything
Java Class from scratch. We tell our students that someday they will be thinking about a
Libraries problem, and they will suddenly realize that a large chunk of the work can be
done with a bag, a stack, a queue, or some such. And this large chunk of work is
work that they won’t have to do. Instead, they will pull out the bag or stack or
queue that they wrote this semester—using it with no modifications. Or, more
likely, they will use the familiar data type from a library of standard data types,
such as the proposed Java Class Libraries. In fact, the behavior of some data
types in this text is a cut-down version of the JCL, so when students take the step
to the real JCL, they will be on familiar ground—from the standpoint of how to
use the class and also having a knowledge of the considerations that went into
building the class.

Other Foundational Topics


Throughout the course, we also lay a foundation for other aspects of “real pro-
gramming,” with coverage of the following topics beyond the basic data struc-
tures material.

Object-Oriented Programming. The foundations of object-oriented pro-


gramming are laid by giving students a strong understanding of Java classes.
The important aspects of classes are covered early: the notion of a method, the
separation into private and public members, the purpose of constructors, and a
small exposure to cloning and testing for equality. This is primarily covered in
Chapter 2, some of which can be skipped by students with a good exposure to
Java classes in the CS1 course.
Further aspects of classes are introduced when the classes first use dynamic
arrays (Chapter 3). At this point, the need for a more sophisticated clone method
is explained. Teaching this OOP method with the first use of dynamic memory
has the effect of giving the students a concrete picture of how an instance vari-
able is used as a reference to a dynamic object such as an array.
Conceptually, the largest innovation of OOP is the software reuse that occurs
via inheritance. There are certainly opportunities for introducing inheritance
right from the start of a data structures course (such as implementing a set class
as a descendant of a bag class). However, an early introduction may also result
in students juggling too many new concepts at once, resulting in a weaker under-
standing of the fundamental data structures. Therefore, in my own course, I intro-
duce inheritance at the end as a vision of things to come. But the introduction to
inheritance (Sections 13.1 and 13.2) could be covered as soon as classes are
understood. With this in mind, some instructors may wish to cover Chapter 13
earlier, just before stacks and queues, so that stacks and queues can be derived
from another class.
Preface ix

Another alternative is to identify students who already know the basics of


classes. These students can carry out an inheritance project (such as the ecosys-
tem of Section 13.3), while the rest of the students first learn about classes.

Java Objects. The Java Object type lies at the base of all the other Java
types—or at least almost all the other types. The eight primitive types are not
Java objects, and for many students, the CS1 work has been primarily with the
eight primitive types. Because of this, the first few data structures are collec-
tions of primitive values, such as a bag of integers or a sequence of double num-
bers.

Iterators. Iterators are an important part of the Java Class Libraries, allowing
a programmer to easily step through the elements in a collection class. The
Iteratable interface is introduced in Chapter 5. Throughout the rest of the
text, iterators are not directly used, although they provide a good opportunity for
programming projects, such as using a stack to implement an iterator for a
binary search tree (Chapter 9).

Recursion. First-semester courses often introduce students to recursion. But


many of the first-semester examples are tail recursion, where the final act of the
method is the recursive call. This may have given students a misleading impres-
sion that recursion is nothing more than a loop. Because of this, I prefer to avoid
early use of tail recursion in a second-semester course.
So, in our second-semester course, we emphasize recursive solutions that use
more than tail recursion. The recursion chapter provides four examples along
these lines. Two of the examples—generating random fractals and traversing a
maze—are big hits with the students. The fractal example runs as a graphical
applet, and although the maze example is text based, an adventurous student can
convert it to a graphical applet. These recursion examples (Chapter 8) appear just
before trees (Chapter 9) since it is within recursive tree algorithms that recursion
becomes vital. However, instructors who desire more emphasis on recursion can
move that topic forward, even before Chapter 2.
In a course that has time for advanced tree projects (Chapter 10), we analyze
the recursive tree algorithms, explaining the importance of keeping the trees
balanced—both to improve worst-case performance and to avoid potential
execution stack overflow.

Searching and Sorting. Chapters 11 and 12 provide fundamental coverage of


searching and sorting algorithms. The searching chapter reviews binary search
of an ordered array, which many students will have seen before. Hash tables are
also introduced in the search chapter by implementing a version of the JCL hash
table and also a second hash table that uses chaining instead of open addressing.
The sorting chapter reviews simple quadratic sorting methods, but the majority
of the chapter focuses on faster algorithms: the recursive merge sort (with
worst-case time of O(n log n)), Tony Hoare’s recursive quicksort (with average-
time O(n log n)), and the tree-based heapsort (with worst-case time of O(n log n)).
x Preface

Advanced Projects, Including Concurrency


The text offers good opportunities for optional projects that can be undertaken
by a more advanced class or by students with a stronger background in a large
class. Particular advanced projects include the following:
• Interactive applet-based test programs for any of the data structures (out-
lined in Appendix I).
• Implementing an iterator for the sequence class (see Chapter 5 Program-
ming Projects).
• Writing a deep clone method for a collection class (see Chapter 5 Pro-
gramming Projects).
• Writing an applet version of an application program (such as the maze tra-
versal in Section 8.2 or the ecosystem in Section 13.3).
• Using a stack to build an iterator for the binary search tree (see Chapter 9
Programming Projects).
• A priority queue implemented as an array of ordinary queues (Section
7.4) or implemented using a heap (Section 10.1).
• A set class implemented with B-trees (Section 10.2). I have made a partic-
ular effort on this project to provide sufficient information for students to
implement the class without need of another text. Advanced students have
successfully completed this project as independent work.
• Projects to support concurrent sorting in the final section of Chapter 12.
• An inheritance project, such as the ecosystem of Section 13.3.
• A graph class and associated graph algorithms in Chapter 14. This is
another case in which advanced students may do work on their own.

Java Language Versions


All the source code in the book has been tested to work correctly with Java 2
Standard Edition Version 7.0, including new features such as generics and new
concurrency support. Information on all of the Java products from Sun Micro-
systems is available at http://java.sun.com/products/index.html.
Flexibility of Topic Ordering
This book was written to give instructors latitude in reordering the material to
meet the specific background of students or to add early emphasis to selected
topics. The dependencies among the chapters are shown on the next page. A line
joining two boxes indicates that the upper box should be covered before the
lower box.
Here are some suggested orderings of the material:
Typical Course. Start with Chapters 1–9, skipping parts of Chapter 2 if the
students have a prior background in Java classes. Most chapters can be covered
in a week, but you may want more time for Chapter 4 (linked lists), Chapter 8
(recursion), or Chapter 9 (trees). Typically, I cover the material in 13 weeks,
Preface xi

Chapter Dependencies

At the start of the course, students should be comfortable writing


application programs and using arrays in Java.

Chapter 1
Introduction

Chapters 2–3
Classes
Reference variables
Collection classes Chapter 8
Recursion
Chapter 2 can be skipped by students
with a good background in Java classes.

Section 11.1
Chapter 4
Binary search
Linked lists
Chapter 13
Extended classes
Sections 5.1–5.4 Sec. 11.2–11.3
Generic programming Hash tables
(Also requires
Chapter 5)
Sections 5.5–5.7 Chapter 6
The Java API Stacks
Chapter 12
Iterators Sorting
Java collections (Heapsort also
Java maps Chapter 7 Chapter 9
needs Section
Queues Trees
10.1)

Section 10.1 Section 10.2 Section 10.3


Heaps B-trees Java trees

The shaded boxes provide


Section 10.4 Chapter 14
good opportunities for
Detailed tree analysis Graphs
advanced work.
xii Preface

including time for exams and extra time for linked lists and trees. Remaining
weeks can be spent on a tree project from Chapter 10 or on binary search (Sec-
tion 11.1) and sorting (Chapter 12).
Heavy OOP Emphasis. If students will cover sorting and searching else-
where, then there is time for a heavier emphasis on object-oriented program-
ming. The first three chapters are covered in detail, and then derived classes
(Section 13.1) are introduced. At this point, students can do an interesting OOP
project, perhaps based on the ecosystem of Section 13.3. The basic data struc-
tures (Chapters 4 –7) are then covered, with the queue implemented as a derived
class (Section 13.4). Finish up with recursion (Chapter 8) and trees (Chapter 9),
placing special emphasis on recursive methods.
Accelerated Course. Assign the first three chapters as independent reading in
the first week and start with Chapter 4 (linked lists). This will leave two to three
extra weeks at the end of the term so that students can spend more time on
searching, sorting, and the advanced topics (shaded in the chapter dependencies
list).
I also have taught the course with further acceleration by spending no lecture
time on stacks and queues (but assigning those chapters as reading).
Early Recursion / Early Sorting. One to three weeks may be spent at the
start of class on recursive thinking. The first reading will then be Chapters 1 and
8, perhaps supplemented by additional recursive projects.
If the recursion is covered early, you may also proceed to cover binary search
(Section 11.1) and most of the sorting algorithms (Chapter 12) before introduc-
ing collection classes.

Supplements Via the Internet


The following materials are available to all readers of this text at cssup-
port.pearsoncmg.com (or alternatively at www.cs.colorado.edu/~main/
dsoj.html):
• Source code
• Errata
In addition, the following supplements are available to qualified instructors.
Visit Addison-Wesley’s Instructor Resource Center (www.aw.com/irc) or con-
tact your local Addison-Wesley representative for access to these:
• PowerPoint® presentations
• Exam questions
• Solutions to selected programming projects
• Speaker notes
• Sample assignments
• Suggested syllabi
Preface xiii

Acknowledgments
This book grew from joint work with Walter Savitch, who continues to be an
ever-present and enthusiastic supporter, colleague, and friend. My students from
the University of Colorado at Boulder serve to provide inspiration and joy at
every turn, particularly the spring seminars in Natural Computing and Ideas in
Computing. During the past few years, the book has also been extensively
reviewed by J.D. Baker, Philip Barry, Arthur Crummer, Herbert Dershem, Greg
Dobbins, Zoran Duric, Dan Grecu, Scott Grissom, Bob Holloway, Rod Howell,
Danny Krizanc, Ran Libeskind-Hadas, Meiliu Lu, Catherine Matthews, Robert
Moll, Robert Pastel, Don Slater, Ryan Stansifer, Deborah Trytten, and John
Wegis. I thank these colleagues for their excellent critique and their encourage-
ment.
At Addison-Wesley, I thank Tracy Dunkelberger, Michael Hirsch, Bob
Engelhardt, and Stephanie Sellinger, who have provided continual support and
knowledgeable advice.
I also thank my friends and colleagues who have given me daily
encouragement and friendship during the writing of this fourth edition: Andrzej
Ehrenfeucht, Marga Powell, Grzegorz Rozenberg, and Allison Thompson-
Brown, and always my family: Janet, Tim, Hannah, Michelle, and Paul.

Michael Main (main@colorado.edu)


Boulder, Colorado
xiv Preface

Chapter List

Chapter 1 THE PHASES OF SOFTWARE DEVELOPMENT 1


Chapter 2 JAVA CLASSES AND INFORMATION HIDING 38
Chapter 3 COLLECTION CLASSES 103
Chapter 4 LINKED LISTS 175
Chapter 5 GENERIC PROGRAMMING 251
Chapter 6 STACKS 315
Chapter 7 QUEUES 360
Chapter 8 RECURSIVE THINKING 409
Chapter 9 TREES 453
Chapter 10 TREE PROJECTS 520
Chapter 11 SEARCHING 567
Chapter 12 SORTING 614
Chapter 13 SOFTWARE REUSE WITH EXTENDED CLASSES 675
Chapter 14 GRAPHS 728

APPENDIXES 775
INDEX 815
Contents xv

Contents
CHAPTER 1 THE PHASES OF SOFTWARE DEVELOPMENT 1
1.1 Specification, Design, Implementation 4
Design Technique: Decomposing the Problem 5
How to Write a Specification for a Java Method 6
Pitfall: Throw an Exception to Indicate a Failed Precondition 9
Temperature Conversion: Implementation 10
Programming Tip: Use Javadoc to Write Specifications 13
Programming Tip: Use Final Variables to Improve Clarity 13
Programming Tip: Make Exception Messages Informative 14
Programming Tip: Format Output with System.out.printf 14
Self-Test Exercises for Section 1.1 15
1.2 Running Time Analysis 16
The Stair-Counting Problem 16
Big-O Notation 21
Time Analysis of Java Methods 23
Worst-Case, Average-Case, and Best-Case Analyses 25
Self-Test Exercises for Section 1.2 26
1.3 Testing and Debugging 26
Choosing Test Data 27
Boundary Values 27
Fully Exercising Code 28
Pitfall: Avoid Impulsive Changes 29
Using a Debugger 29
Assert Statements 29
Turning Assert Statements On and Off 30
Programming Tip: Use a Separate Method for Complex Assertions 32
Pitfall: Avoid Using Assertions to Check Preconditions 34
Static Checking Tools 34
Self-Test Exercises for Section 1.3 34
Chapter Summary 35
Solutions to Self-Test Exercises 36

CHAPTER 2 JAVA CLASSES AND INFORMATION HIDING 38


2.1 Classes and Their Members 40
Defining a New Class 41
Instance Variables 41
Constructors 42
No-Arguments Constructors 43
Methods 43
Accessor Methods 44
Programming Tip: Four Reasons to Implement Accessor Methods 44
Pitfall: Division Throws Away the Fractional Part 45
Programming Tip: Use the Boolean Type for True or False Values 46
Modification Methods 46
Pitfall: Potential Arithmetic Overflows 48
Complete Definition of Throttle.java 48
Methods May Activate Other Methods 51
Self-Test Exercises for Section 2.1 51
xvi Contents

2.2 Using a Class 52


Creating and Using Objects 52
A Program with Several Throttle Objects 53
Null References 54
NullPointerException 55
Assignment Statements with Reference Variables 55
Clones 58
Testing for Equality 58
Terminology Controversy: “The Throttle That t Refers To” 59
Self-Test Exercises for Section 2.2 59
2.3 Packages 60
Declaring a Package 60
The Import Statement to Use a Package 63
The JCL Packages 63
More about Public, Private, and Package Access 63
Self-Test Exercises for Section 2.3 65
2.4 Parameters, Equals Methods, and Clones 65
The Location Class 66
Static Methods 72
Parameters That Are Objects 73
Methods May Access Private Instance Variables of Objects in Their Own Class 74
The Return Value of a Method May Be an Object 75
Programming Tip: How to Choose the Names of Methods 76
Java’s Object Type 77
Using and Implementing an Equals Method 77
Pitfall: ClassCastException 80
Every Class Has an Equals Method 80
Using and Implementing a Clone Method 81
Pitfall: Older Java Code Requires a Typecast for Clones 81
Programming Tip: Always Use super.clone for Your Clone Method 85
Programming Tip: When to Throw a Runtime Exception 85
A Demonstration Program for the Location Class 85
What Happens When a Parameter Is Changed Within a Method? 86
Self-Test Exercises for Section 2.4 89
2.5 The Java Class Libraries 90
Chapter Summary 92
Solutions to Self-Test Exercises 93
Programming Projects 95
Contents xvii

CHAPTER 3 COLLECTION CLASSES 103


3.1 A Review of Java Arrays 104
Pitfall: Exceptions That Arise from Arrays 106
The Length of an Array 106
Assignment Statements with Arrays 106
Clones of Arrays 107
The Arrays Utility Class 108
Array Parameters 110
Programming Tip: Enhanced For-Loops for Arrays 111
Self-Test Exercises for Section 3.1 112
3.2 An ADT for a Bag of Integers 113
The Bag ADT—Specification 114
OutOfMemoryError and Other Limitations for Collection Classes 118
The IntArrayBag Class—Specification 118
The IntArrayBag Class—Demonstration Program 122
The IntArrayBag Class—Design 125
The Invariant of an ADT 126
The IntArrayBag ADT—Implementation 127
Programming Tip: Cloning a Class That Contains an Array 136
The Bag ADT—Putting the Pieces Together 137
Programming Tip: Document the ADT Invariant in the Implementation File 141
The Bag ADT—Testing 141
Pitfall: An Object Can Be an Argument to Its Own Method 142
The Bag ADT—Analysis 142
Self-Test Exercises for Section 3.2 144
3.3 Programming Project: The Sequence ADT 145
The Sequence ADT—Specification 146
The Sequence ADT—Documentation 150
The Sequence ADT—Design 150
The Sequence ADT—Pseudocode for the Implementation 156
Self-Test Exercises for Section 3.3 158
3.4 Programming Project: The Polynomial 159
Self-Test Exercises for Section 3.4 162
3.5 The Java HashSet and Iterators 162
The HashSet Class 162
Some of the HashSet Members 162
Iterators 163
Pitfall: Do Not Access an Iterator’s next Item When hasNext Is False 164
Pitfall: Changing a Container Object Can Invalidate Its Iterator 164
Invalid Iterators 164
Self-Test Exercises for Section 3.5 165
Chapter Summary 165
Solutions to Self-Test Exercises 166
Programming Projects 169
xviii Contents

CHAPTER 4 LINKED LISTS 175


4.1 Fundamentals of Linked Lists 176
Declaring a Class for Nodes 177
Head Nodes, Tail Nodes 177
The Null Reference 178
Pitfall: NullPointerExceptions with Linked Lists 179
Self-Test Exercises for Section 4.1 179
4.2 Methods for Manipulating Nodes 179
Constructor for the Node Class 180
Getting and Setting the Data and Link of a Node 180
Public Versus Private Instance Variables 181
Adding a New Node at the Head of a Linked List 182
Removing a Node from the Head of a Linked List 183
Adding a New Node That Is Not at the Head 185
Removing a Node That Is Not at the Head 188
Pitfall: NullPointerExceptions with removeNodeAfter 191
Self-Test Exercises for Section 4.2 191
4.3 Manipulating an Entire Linked List 192
Computing the Length of a Linked List 193
Programming Tip: How to Traverse a Linked List 196
Pitfall: Forgetting to Test the Empty List 197
Searching for an Element in a Linked List 197
Finding a Node by Its Position in a Linked List 198
Copying a Linked List 200
A Second Copy Method, Returning Both Head and Tail References 204
Programming Tip: A Method Can Return an Array 205
Copying Part of a Linked List 206
Using Linked Lists 207
Self-Test Exercises for Section 4.3 214
4.4 The Bag ADT with a Linked List 215
Our Second Bag—Specification 215
The grab Method 219
Our Second Bag—Class Declaration 219
The Second Bag—Implementation 220
Programming Tip: Cloning a Class That Contains a Linked List 223
Programming Tip: How to Choose between Different Approaches 225
The Second Bag—Putting the Pieces Together 229
Self-Test Exercises for Section 4.4 232
4.5 Programming Project: The Sequence ADT with a Linked List 232
The Revised Sequence ADT—Design Suggestions 232
The Revised Sequence ADT—Clone Method 235
Self-Test Exercises for Section 4.5 238
4.6 Beyond Simple Linked Lists 239
Arrays Versus Linked Lists and Doubly Linked Lists 239
Dummy Nodes 240
Java’s List Classes 241
ListIterators 242
Making the Decision 243
Self-Test Exercises for Section 4.6 244
Chapter Summary 244
Solutions to Self-Test Exercises 245
Programming Projects 248
Contents xix

CHAPTER 5 GENERIC PROGRAMMING 251


5.1 Java’s Object Type and Wrapper Classes 252
Widening Conversions 253
Narrowing Conversions 254
Wrapper Classes 256
Autoboxing and Auto-Unboxing Conversions 256
Advantages and Disadvantages of Wrapper Objects 257
Self-Test Exercises for Section 5.1 257
5.2 Object Methods and Generic Methods 258
Object Methods 259
Generic Methods 259
Pitfall: Generic Method Restrictions 260
Self-Test Exercises for Section 5.2 261
5.3 Generic Classes 262
Writing a Generic Class 262
Using a Generic Class 262
Pitfall: Generic Class Restrictions 263
Details for Implementing a Generic Class 263
Creating an Array to Hold Elements of the Unknown Type 263
Retrieving E Objects from the Array 264
Warnings in Generic Code 264
Programming Tip: Suppressing Unchecked Warnings 265
Using ArrayBag as the Type of a Parameter or Return Value 266
Counting the Occurrences of an Object 266
The Collection Is Really a Collection of References to Objects 267
Set Unused References to Null 269
Steps for Converting a Collection Class to a Generic Class 269
Deep Clones for Collection Classes 271
Using the Bag of Objects 279
Details of the Story-Writing Program 282
Self-Test Exercises for Section 5.3 282
5.4 Generic Nodes 283
Nodes That Contain Object Data 283
Pitfall: Misuse of the equals Method 283
Other Collections That Use Linked Lists 285
Self-Test Exercises for Section 5.4 285
5.5 Interfaces and Iterators 286
Interfaces 286
How to Write a Class That Implements an Interface 287
Generic Interfaces and the Iterable Interface 287
How to Write a Generic Class That Implements a Generic Interface 288
The Lister Class 289
Pitfall: Don’t Change a List While an Iterator Is Being Used 291
The Comparable Generic Interface 292
Parameters That Use Interfaces 293
Using instanceof to Test Whether a Class Implements an Interface 294
The Cloneable Interface 295
Self-Test Exercises for Section 5.5 295
xx Contents

5.6 A Generic Bag Class That Implements the Iterable Interface (Optional Section) 296
Programming Tip: Enhanced For-Loops for the Iterable Interface 297
Implementing a Bag of Objects Using a Linked List and an Iterator 298
Programming Tip: External Iterators Versus Internal Iterators 298
Summary of the Four Bag Implementations 299
Self-Test Exercises for Section 5.6 299
5.7 The Java Collection Interface and Map Interface (Optional Section) 300
The Collection Interface 300
The Map Interface and the TreeMap Class 300
The TreeMap Class 302
The Word Counting Program 305
Self-Test Exercises for Section 5.7 306
Chapter Summary 309
Solutions to Self-Test Exercises 310
Programming Projects 312

CHAPTER 6 STACKS 315


6.1 Introduction to Stacks 316
The Stack Class—Specification 317
We Will Implement a Generic Stack 319
Programming Example: Reversing a Word 319
Self-Test Exercises for Section 6.1 320
6.2 Stack Applications 320
Programming Example: Balanced Parentheses 320
Programming Tip: The Switch Statement 324
Evaluating Arithmetic Expressions 325
Evaluating Arithmetic Expressions—Specification 325
Evaluating Arithmetic Expressions—Design 325
Implementation of the Evaluate Method 329
Evaluating Arithmetic Expressions—Testing and Analysis 333
Evaluating Arithmetic Expressions—Enhancements 334
Self-Test Exercises for Section 6.2 334
6.3 Implementations of the Stack ADT 335
Array Implementation of a Stack 335
Linked List Implementation of a Stack 341
Self-Test Exercises for Section 6.3 344
6.4 More Complex Stack Applications 345
Evaluating Postfix Expressions 345
Translating Infix to Postfix Notation 348
Using Precedence Rules in the Infix Expression 350
Correctness of the Conversion from Infix to Postfix 353
Self-Test Exercises for Section 6.4 354
Chapter Summary 354
Solutions to Self-Test Exercises 355
Programming Projects 356
Contents xxi

CHAPTER 7 QUEUES 360


7.1 Introduction to Queues 361
The Queue Class 362
Uses for Queues 364
Self-Test Exercises for Section 7.1 365
7.2 Queue Applications 365
Java Queues 365
Programming Example: Palindromes 366
Programming Example: Car Wash Simulation 369
Car Wash Simulation—Specification 369
Car Wash Simulation—Design 369
Car Wash Simulation—Implementing the Car Wash Classes 374
Car Wash Simulation—Implementing the Simulation Method 375
Self-Test Exercises for Section 7.2 375
7.3 Implementations of the Queue Class 383
Array Implementation of a Queue 383
Programming Tip: Use Helper Methods to Improve Clarity 386
Linked List Implementation of a Queue 393
Pitfall: Forgetting Which End Is Which 398
Self-Test Exercises for Section 7.3 398
7.4 Deques and Priority Queues (Optional Section) 399
Double-Ended Queues 399
Priority Queues 400
Priority Queue ADT—Specification 400
Priority Queue Class—An Implementation That Uses an Ordinary Queue 402
Priority Queue ADT—A Direct Implementation 403
Java’s Priority Queue 403
Self-Test Exercises for Section 7.4 404
Chapter Summary 404
Solutions to Self-Test Exercises 404
Programming Projects 406

CHAPTER 8 RECURSIVE THINKING 409


8.1 Recursive Methods 410
Tracing Recursive Calls 413
Programming Example: An Extension of writeVertical 413
A Closer Look at Recursion 415
General Form of a Successful Recursive Method 418
Self-Test Exercises for Section 8.1 419
8.2 Studies of Recursion: Fractals and Mazes 420
Programming Example: Generating Random Fractals 420
A Method for Generating Random Fractals—Specification 421
The Stopping Case for Generating a Random Fractal 426
Putting the Random Fractal Method in an Applet 426
Programming Example: Traversing a Maze 429
Traversing a Maze—Specification 429
Traversing a Maze—Design 432
Traversing a Maze—Implementation 433
The Recursive Pattern of Exhaustive Search with Backtracking 435
Programming Example: The Teddy Bear Game 437
Self-Test Exercises for Section 8.2 437
xxii Contents

8.3 Reasoning about Recursion 439


How to Ensure That There Is No Infinite Recursion in the General Case 442
Inductive Reasoning about the Correctness of a Recursive Method 444
Self-Test Exercises for Section 8.3 445
Chapter Summary 446
Solutions to Self-Test Exercises 446
Programming Projects 448

CHAPTER 9 TREES 453


9.1 Introduction to Trees 454
Binary Trees 454
Binary Taxonomy Trees 457
More Than Two Children 458
Self-Test Exercises for Section 9.1 459
9.2 Tree Representations 459
Array Representation of Complete Binary Trees 459
Representing a Binary Tree with a Generic Class for Nodes 462
Self-Test Exercises for Section 9.2 464
9.3 A Class for Binary Tree Nodes 464
Programming Example: Animal Guessing 473
Animal-Guessing Program—Design and Implementation 475
Animal-Guessing Program—Improvements 481
Self-Test Exercises for Section 9.3 481
9.4 Tree Traversals 484
Traversals of Binary Trees 484
Printing a Tree with an Indentation to Show the Depths 488
BTNode, IntBTNode, and Other Classes 497
Self-Test Exercises for Section 9.4 497
9.5 Binary Search Trees 498
The Binary Search Tree Storage Rules 498
The Binary Search Tree Bag—Implementation of Some Simple Methods 503
Counting the Occurrences of an Element in a Binary Search Tree 504
Adding a New Element to a Binary Search Tree 505
Removing an Element from a Binary Search Tree 506
The addAll, addMany, and union Methods 510
Pitfall: Violating the addTree Precondition 511
Implementing addAll 512
Time Analysis and an Internal Iterator 513
Self-Test Exercises for Section 9.5 513
Chapter Summary 514
Solutions to Self-Test Exercises 514
Programming Projects 517
Contents xxiii

CHAPTER 10 TREE PROJECTS 520


10.1 Heaps 521
The Heap Storage Rules 521
The Priority Queue Class with Heaps 522
Adding an Element to a Heap 523
Removing an Element from a Heap 524
Self-Test Exercises for Section 10.1 527
10.2 B-Trees 527
The Problem of Unbalanced Trees 527
The B-Tree Rules 528
An Example B-Tree 529
The Set Class with B-Trees 530
Searching for an Element in a B-Tree 535
Programming Tip: Private Methods to Simplify Implementations 537
Adding an Element to a B-Tree 537
The Loose Addition Operation for a B-Tree 538
A Private Method to Fix an Excess in a Child 540
Back to the add Method 541
Employing Top-Down Design 543
Removing an Element from a B-Tree 543
The Loose Removal from a B-Tree 544
A Private Method to Fix a Shortage in a Child 546
Removing the Biggest Element from a B-Tree 549
Programming Tip: Write and Test Small Pieces 549
External B-Trees 550
Self-Test Exercises for Section 10.2 551
10.3 Java Support for Trees 552
The DefaultMutableTreeNode from javax.swing.tree 552
Using the JTree Class to Display a Tree in an Applet 552
The JApplet Class 552
Programming Tip: Adding a Component to a JApplet 553
What the TreeExample Applet Displays 553
Self-Test Exercises for Section 10.3 553
10.4 Trees, Logs, and Time Analysis 558
Time Analysis for Binary Search Trees 559
Time Analysis for Heaps 559
Logarithms 562
Logarithmic Algorithms 563
Self-Test Exercises for Section 10.4 563
Chapter Summary 563
Solutions to Self-Test Exercises 564
Programming Projects 566
xxiv Contents

CHAPTER 11 SEARCHING 567


11.1 Serial Search and Binary Search 568
Serial Search 568
Serial Search—Analysis 568
Binary Search 571
Binary Search—Design 572
Pitfall: Common Indexing Errors in Binary Search Implementations 574
Binary Search—Analysis 574
Java’s Binary Search Methods 579
Self-Test Exercises for Section 11.1 581
11.2 Open-Address Hashing 581
Introduction to Hashing 581
Noninteger Keys and Java’s hashCode Method 583
Pitfall: Classes Often Need a New hashCode Method 584
The Table ADT—Specification 584
The Table ADT—Design 587
The Table ADT—Implementation 589
A Practical Illustration of Open-Address Hashing 594
Choosing a Hash Function to Reduce Collisions 596
Double Hashing to Reduce Clustering 596
Self-Test Exercises for Section 11.2 598
11.3 Using Java’s Hashtable Class 599
11.4 Chained Hashing 600
Self-Test Exercises for Section 11.4 601
11.5 Programming Project: A Table Class Implemented with Java’s Vector and LinkedList 603
A New Table Class 603
Data Structures for the New Table Class 603
Implementing the New Table Class 604
Self-Test Exercises for Section 11.6 605
11.6 Time Analysis of Hashing 605
The Load Factor of a Hash Table 607
Self-Test Exercises for Section 11.5 609
Chapter Summary 609
Solutions to Self-Test Exercises 610
Programming Projects 612

CHAPTER 12 SORTING 614


12.1 Quadratic Sorting Algorithms 615
Selectionsort—Specification 615
Selectionsort—Design 616
Selectionsort—Testing 619
Selectionsort—Analysis 620
Programming Tip: Rough Estimates Suffice for Big-O 622
Insertionsort 622
Insertionsort—Analysis 626
Self-Test Exercises for Section 12.1 629
Contents xxv

12.2 Recursive Sorting Algorithms 629


Divide-and-Conquer Using Recursion 629
Mergesort 630
The merge Function 631
Mergesort—Analysis 638
Mergesort for Files 640
Quicksort 640
The Partition Method 643
Quicksort—Analysis 646
Quicksort—Choosing a Good Pivot Element 648
Self-Test Exercises for Section 12.2 648
12.3 An O(n log n) Algorithm Using a Heap 649
Heapsort 649
Making the Heap 656
Reheapification Downward 657
Heapsort—Analysis 658
Self-Test Exercise for Section 12.3 659
12.4 Java’s Sort Methods 660
Self-Test Exercises for Section 12.4 660
12.5 Concurrent Recursive Sorting 660
Mergesort with a Threshold 661
Pitfall: The RecursiveAction Class Did Not Appear Until Java 7 662
Java’s RecursiveAction Class 662
The Sorter’s Constructor 663
The Sorter’s compute Method 664
Programming Tip: Using InvokeAll 664
Using a ForkJoinPool to Get Concurrent Recursion Started 665
Beyond the Simple Sorter Class 668
Self-Test Exercises for Section 12.5 668
Chapter Summary 669
Solutions to Self-Test Exercises 669
Programming Projects 671

CHAPTER 13 SOFTWARE REUSE WITH EXTENDED CLASSES 675


13.1 Extended Classes 676
How to Declare an Extended Class 678
The Constructors of an Extended Class 679
Using an Extended Class 680
Descendants and Ancestors 681
Overriding Inherited Methods 682
Covariant Return Values 684
Widening Conversions for Extended Classes 684
Narrowing Conversions for Extended Classes 685
Self-Test Exercises for Section 13.1 686
13.2 Generic Type Parameters and Inheritance 686
Self-Test Exercise for Section 13.2 688
xxvi Contents

13.3 Simulation of an Ecosystem 688


Programming Tip: When to Use an Extended Class 689
Implementing Part of the Organism Object Hierarchy 689
The Organism Class 689
The Animal Class: An Extended Class with New Private Instance Variables 693
How to Provide a New Constructor for an Extended Class 693
The Other Animal Methods 695
Self-Test Exercises for the Middle of Section 13.3 696
The Herbivore Class 700
The Pond Life Simulation Program 703
Pond Life—Implementation Details 708
Using the Pond Model 708
Self-Test Exercises for the End of Section 13.3 709
13.4 Abstract Classes and a Game Class 710
Introduction to the AbstractGame Class 710
Protected Methods 716
Final Methods 716
Abstract Methods 717
An Extended Class to Play Connect Four 718
The Private Member Variables of the Connect Four Class 718
Three Connect Four Methods That Deal with the Game’s Status 720
Three Connect Four Methods That Deal with Moves 721
The clone Method 722
Writing Your Own Derived Games from the AbstractGame Class 723
Self-Test Exercises for Section 13.4 724
Chapter Summary 724
Further Reading 724
Solutions to Self-Test Exercises 725
Programming Projects 727

CHAPTER 14 GRAPHS 728


14.1 Graph Definitions 729
Undirected Graphs 729
Programming Example: Undirected State Graphs 730
Directed Graphs 733
More Graph Terminology 734
Airline Routes Example 735
Self-Test Exercises for Section 14.1 736
14.2 Graph Implementations 736
Representing Graphs with an Adjacency Matrix 736
Using a Two-Dimensional Array to Store an Adjacency Matrix 737
Representing Graphs with Edge Lists 738
Representing Graphs with Edge Sets 739
Which Representation Is Best? 739
Programming Example: Labeled Graph ADT 740
The Graph Constructor and size Method 741
Methods for Manipulating Edges 742
Methods for Manipulating Vertex Labels 743
Labeled Graph ADT—Implementation 743
Self-Test Exercises for Section 14.2 749
Contents xxvii

14.3 Graph Traversals 749


Depth-First Search 750
Breadth-First Search 754
Depth-First Search—Implementation 756
Breadth-First Search—Implementation 758
Self-Test Exercises for Section 14.3 759
14.4 Path Algorithms 759
Determining Whether a Path Exists 759
Graphs with Weighted Edges 759
Shortest-Distance Algorithm 760
Shortest-Path Algorithm 770
Self-Test Exercises for Section 14.4 771
Chapter Summary 771
Solutions to Self-Test Exercises 772
Programming Projects 773

APPENDIXES
A. JAVA’S PRIMITIVE TYPES AND ARITHMETIC OVERFLOW 775
B. JAVA INPUT AND OUTPUT 778
C. THROWING AND CATCHING JAVA EXCEPTIONS 782
D. ARRAYLIST, VECTOR, HASHTABLE, AND HASHMAP CLASSES 787
E. A CLASS FOR NODES IN A LINKED LIST 791
F. A CLASS FOR A BAG OF OBJECTS 799
G. FURTHER BIG-O NOTATION 805
H. JAVADOC 807
I. APPLETS FOR INTERACTIVE TESTING 814

INDEX 815
This page intentionally left blank
CHAPTER 1
The Phases of Software
Development

LEARNING OBJECTIVES
When you complete Chapter 1, you will be able to ...
• use Javadoc to write a method’s complete specification, including a
precondition/postcondition contract.
• recognize quadratic, linear, and logarithmic runtime behavior in simple
algorithms, and write bigO expressions to describe this behavior.
• create and recognize test data that is appropriate for a problem, including
testing boundary conditions and fully exercising code.

CHAPTER CONTENTS
1.1 Specification, Design, Implementation
1.2 Running Time Analysis
1.3 Testing and Debugging
Chapter Summary
Solutions to SelfTest Exercises
CHAPTER
The Phases of Software Development
1 Chapter the first which explains how, why, when, and where
there was ever any problem in the first place
NOEL LANGLEY
The Land of Green Ginger

T his chapter illustrates the phases of software development.


These phases occur for all software, including the small programs you’ll see in
this first chapter. In subsequent chapters, you’ll go beyond these small pro-
grams, applying the phases of software development to organized collections of
data. These organized collections of data are called data structures, and the
main topics of this book revolve around proven techniques for representing and
manipulating such data structures.

Data Structure
A data structure is a collection of data, organized so that items
can be stored and retrieved by some fixed techniques. For
example, a Java array is a simple data structure that allows
individual items to be stored and retrieved based on an index
([0], [1], [2], ...) that is assigned to each item.

Throughout this book, you will be presented with many forms


of data structures with organizations that are motivated by
considerations such as ease of use or speed of inserting and
removing items from the structure.

Years from now, you may be a software engineer writing large systems in
a specialized area, perhaps artificial intelligence or computational biology. Such
futuristic applications will be exciting and stimulating, and within your work you
will still see the data structures that you learn and practice now. You will still
be following the same phases of software development that you learned when
designing and implementing your first programs. Here is a typical list of the
software development phases:

The Phases of Software Development


• Specification of the task
• Design of a solution
• Implementation (coding) of the solution
• Analysis of the solution
• Testing and debugging
• Maintenance and evolution of the system
• Obsolescence
3

You don’t need to memorize this list; throughout the book, your practice of the phases blur
these phases will achieve far better familiarity than mere memorization. Also, into each other
memorizing an “official list” is misleading because it suggests that there is a
single sequence of discrete steps that always occur one after another. In practice,
the phases blur into each other. For instance, the analysis of a solution’s
efficiency may occur hand in hand with the design, before any coding, or low-
level design decisions may be postponed until the implementation phase. Also,
the phases might not occur one after another. Typically, there is back and forth
travel between the phases.
Most work in software development does not depend on any particular pro-
gramming language. Specification, design, and analysis can all be carried out
with few or no ties to a particular programming language. Nevertheless, when we
get down to implementation details, we do need to decide on one particular pro-
gramming language. The language we use in this book is JavaTM, and the partic-
ular version we use is Java Standard Edition 7.

What You Should Know About Java Before Starting This Text
The Java language was conceived by a group of programmers at Sun Micro- the origin of
systemsTM in 1991. The group, led by James Gosling, had an initial design Java
called Oak that was motivated by a desire for a single language in which pro-
grams could be developed and easily moved from one machine to another. Over
the next four years, many Sun programmers contributed to the project, and Gos-
ling’s Oak evolved into the Java language. Java’s goal of easily moving pro-
grams between machines was met by introducing an intermediate form called
byte codes. To run a Java program, the program is first translated into byte
codes; the byte codes are then given to a machine that runs a controlling pro-
gram called the Java Runtime Environment (JRE). Because the JRE is freely
available for a wide variety of machines, Java programs can be moved from one
machine to another. Because the JRE controls all Java programs, there is an
added level of security that comes from avoiding potential problems from run-
ning unknown programs.
In addition to the original goals of program transportability and security, the
designers of Java also incorporated ideas from other modern programming lan-
guages. Most notably, Java supports object-oriented programming (OOP) in a
manner that was partly taken from the C++ programming language. OOP is a
programming approach that encourages strategies of information hiding and
component reuse. In this book, you will be introduced to these important OOP this book gives
principles to use in your designs and implementations. an introduction
All of the programs in this book have been developed and tested with Sun’s to OOP
Java Development Kit (JDK 7), but many other Java programming environ- principles for
ments may be successfully used with this text. You should be comfortable writ- information
hiding and
ing, compiling, and running short Java application programs in your en-
component
vironment. You should know how to use the Java primitive types (the number
reuse
types, char, and boolean), and you should be able to use arrays.
The rest of this chapter will prepare you to tackle the topic of data structures
in Java. Section 1.1 focuses on a technique for specifying program behavior, and
4 Chapter 1 / The Phases of Software Development

you’ll also see some hints about design and implementation. Section 1.2 illus-
trates a particular kind of analysis: the running time analysis of a program. Sec-
tion 1.3 provides some techniques for testing and debugging Java programs.

1.1 SPECIFICATION, DESIGN, IMPLEMENTATION


One begins with a list of difficult design decisions which are likely to
change. Each module is then designed to hide such a decision from
the others.
you should
already know D. L. PARNAS
“On the Criteria to Be Used in Decomposing Systems into Modules”
how to write,
compile, and run As an example of software development in action, let’s examine the specifica-
short Java tion, design, and implementation for a particular problem. The specification is a
programs in precise description of the problem; the design phase consists of formulating the
some
steps (or algorithm) to solve the problem;
programming TEMPERATURE CONVERSION and the implementation is the actual Java
environment ---------------------- code to carry out the design.
Celsius Fahrenheit The problem we have in mind is to dis-
-50.00C
The equivalent play a table for converting Celsius tempera-
-40.00C
Fahrenheit tures to Fahrenheit, similar to the table
-30.00C
temperatures will be shown here. For a small problem, a sample
-20.00C
of the desired output is a reasonable specifi-
-10.00C computed and
cation. Such a sample is precise, leaving no
0.00C displayed on this side doubt as to what the program must accom-
10.00C of the table.
20.00C plish. The next step is to design a solution.
30.00C An algorithm is a procedure or
40.00C sequence of directions for solving a prob-
50.00C lem. For example, an algorithm for the tem-
---------------------- perature problem will tell how to produce
the conversion table. An algorithm can be
expressed in many different ways, such as in English, in a mixture of English and
mathematical notation, or in a mixture of English with a programming language.
This mixture of English and a programming language is called pseudocode.
Using pseudocode allows us to avoid programming language details that may
obscure a simple solution, but at the same time we can use Java code (or another
language) when the code is clear. Keep in mind that the reason for pseudocode
is to improve clarity.

Algorithm
An algorithm is a procedure or sequence of instructions for
solving a problem. Any algorithm may be expressed in many
different ways: in English, in a particular programming
language, or (most commonly) in a mixture of English and
programming called pseudocode.
Specification, Design, Implementation 5

We’ll use pseudocode to design a solution for the temperature problem, and
we’ll also use the important design technique of decomposing the problem,
which we’ll discuss now.

Design Technique: Decomposing the Problem


Key Design
A good technique for designing an algorithm is to break down the problem at Concept
hand into a few subtasks, then decompose each subtask into smaller subtasks, then Break down a task
replace the smaller subtasks with even smaller subtasks, and so forth. Eventually into a few subtasks;
the subtasks become so small that they are trivial to implement in Java or what- then decompose each
ever language you are using. When the algorithm is translated into Java code, subtask into smaller
each subtask is implemented as a separate Java method. In other programming subtasks.
languages, methods are called “functions” or “procedures,” but it all boils down
to the same thing: The large problem is decomposed into subtasks, and subtasks
are implemented as separate pieces of your program.
For example, the temperature problem has at least two good subtasks: con-
verting a temperature from Celsius degrees to Fahrenheit and printing a number
with a specified accuracy (such as rounding to the nearest hundredth). Using
these two subproblems, the first draft of our pseudocode might look like this:
1. Display the labels at the top of the table.
2. For each line in the table (using variables celsius and fahrenheit):
2a. Set celsius equal to the next Celsius temperature of the table.
2b. fahrenheit = the celsius temperature converted to Fahrenheit.
2c. Print one line of the output table with each temperature rounded to the
nearest hundredth and labeled (by the letter C or F).
3. Print the line of dashes at the bottom of the table.
The underlined steps (2b and 2c) are the major subtasks. But aren’t there other what makes a
ways to decompose the problem into subtasks? What are the aspects of a good good
decomposition? One primary guideline is that the subtasks should help you pro- decomposition?
duce short pseudocode—no more than a page of succinct description to solve
the entire problem and ideally much less than a page. In your first designs, you
can also keep in mind two considerations for selecting good subtasks: the poten-
tial for code reuse and the possibility of future changes to the program. Let’s see
how our subtasks embody these considerations.
Step 2c is a form of a common task: printing some information with a speci- the printf method
fied format. This task is so common that newer versions of Java have included a
method, System.out.printf, that can be used by any program that produces
formatted output. We’ll discuss and use this function when we implement Step
2c.
The printf method is an example of code reuse, in which a single method code reuse
can be used by many programs for similar tasks. In addition to Java’s many pack-
ages of reusable methods, programmers often produce packages of their own
Java methods that are intended to be reused over and over with many different
application programs.
6 Chapter 1 / The Phases of Software Development

easily modified Decomposing problems also produces a good final program in the sense that
code the program is easy to understand, and subsequent maintenance and modifica-
tions are relatively easy. For example, our temperature program might later be
modified to convert to Kelvin degrees instead of Fahrenheit. Since the conver-
sion task is performed by a separate Java method, most of the modification will
be confined to this one method. Easily modified code is vital since real-world
studies show that a large proportion of programmers’ time is spent maintaining
and modifying existing programs.
For a problem decomposition to produce easily modified code, the Java meth-
ods you write need to be genuinely separated from one another. An analogy can
help explain the notion of “genuinely separated.” Suppose you are moving a bag
of gold coins to a safe hiding place. If the bag is too heavy to carry, you might
divide the coins into three smaller bags and carry the bags one by one. Unless
you are a character in a comedy, you would not try to carry all three bags at once.
That would defeat the purpose of dividing the coins into three groups. This strat-
egy works only if you carry the bags one at a time. Something similar happens in
problem decomposition. If you divide your programming task into three subtasks
and solve these subtasks by writing three Java methods, you have traded one hard
problem for three easier problems. Your total job has become easier—provided
that you design the methods separately. When you are working on one method,
you should not worry about how the other methods perform their jobs. But the
methods do interact. So when you are designing one method, you need to know
something about what the other methods do. The trick is to know only as much
as you need but no more. This is called information hiding. One technique for
information hiding involves specifying your methods’ behavior using precondi-
tions and postconditions, which we discuss next.

How to Write a Specification for a Java Method


When you implement a method in Java, you give complete instructions for how
the method performs its computation. However, when you are using a method in
your pseudocode or writing other Java code, you only need to think about what
the method does. You need not think about how the method does its work. For
example, suppose you are writing the temperature-conversion program and you
are told that the following method is available for you to use:
// Convert a Celsius temperature c to Fahrenheit degrees.
public static double celsiusToFahrenheit(double c)

signature of a This information about the method is called its signature. A signature includes
method the method name (celsiusToFahrenheit), its parameter list (double c), its
return type (a double number), and any modifiers (public and static).
In your program, you might have a double variable called celsius that con-
tains a Celsius temperature. Knowing this description, you can confidently write
the following statement to convert the temperature to Fahrenheit degrees, storing
the result in a double variable called fahrenheit:
fahrenheit = celsiusToFahrenheit(celsius);
Specification, Design, Implementation 7

When you use the celsiusToFahrenheit method, you do not need to know the
details of how the method carries out its work. You need to know what the
method does, but you do not need to know how the task is accomplished.
When we pretend that we do not know how a method is implemented, we are procedural
using a form of information hiding called procedural abstraction. This simpli- abstraction
fies your reasoning by abstracting away irrelevant details (that is, by hiding
them). When programming in Java, it might make more sense to call it “method
abstraction” since you are abstracting away irrelevant details about how a
method works. However, computer scientists use the term procedure for any
sequence of instructions, so they also use the term procedural abstraction. Pro-
cedural abstraction can be a powerful tool. It simplifies your reasoning by allow-
ing you to consider methods one at a time rather than all together.
To make procedural abstraction work for us, we need some techniques for
documenting what a method does without indicating how the method works. We
could just write a short comment as we did for celsiusToFahrenheit. However,
the short comment is a bit incomplete; for instance, the comment doesn’t indicate
what happens if the parameter c is smaller than the lowest Celsius temperature
(−273.15°C, also called absolute zero). For better completeness and consis-
tency, we will follow a fixed format that is guaranteed to provide the same kind
of information about any method you may write. The format has five parts, which
are illustrated below and on the next page for the celsiusToFahrenheit
method.
♦ celsiusToFahrenheit
public static double celsiusToFahrenheit(double c)
Convert a temperature from Celsius degrees to Fahrenheit degrees.
Parameters:
c – a temperature in Celsius degrees
Precondition:
c >= -273.15.
Returns:
the temperature c converted to Fahrenheit degrees
Throws: IllegalArgumentException
Indicates that c is less than the smallest Celsius temperature (−273.15).

This documentation is called the method’s specification. Let’s look at the five
parts of this specification.

1. Short Introduction. The specification’s first few lines are a brief introduc-
tion. The introduction includes the method’s name, the complete heading
(public static double celsiusToFahrenheit(double c)), and a short
description of the action that the method performs.

2. Parameter Description. The specification’s second part is a list of the


method’s parameters. We have one parameter, c, which is a temperature in
Celsius degrees.
8 Chapter 1 / The Phases of Software Development

3. Precondition. A precondition is a condition that is supposed to be true when


a method is called. The method is not guaranteed to work correctly unless the
precondition is true. Our method requires that the Celsius temperature c be no
less than the smallest valid Celsius temperature (−273.15°C).

4. The Returns Condition or Postcondition. A returns condition specifies


the meaning of a method’s return value. We used a returns condition for
celsiusToFahrenheit, specifying that the method “returns the temperature c
converted to Fahrenheit degrees.” More complex methods may have additional
effects beyond a single return value. For example, a method may print values or
alter its parameters. To describe such effects, a general postcondition can be pro-
vided instead of just a returns condition. A postcondition is a complete statement
describing what will be true when a method finishes. If the precondition was true
when the method was called, then the method will complete and the postcondi-
tion will be true when the method completes. The connection between a precon-
dition and a postcondition is given here:

A Method’s Precondition and Postcondition


A precondition is a statement giving the condition that is
supposed to be true when a method is called. The method
is not guaranteed to perform as it should unless the
precondition is true.

A postcondition is a statement describing what will be true


when a method call is completed. If the method is correct
and the precondition was true when the method was called,
then the method will complete and the postcondition will be
true when the method’s computation is completed.

For small methods that merely return a calculated value, the specification pro-
vides a precondition and a returns condition. For more complex methods, the
specification provides a precondition and a general postcondition.
programming Preconditions and postconditions are even more important when a group of
teams programmers work together. In team situations, one programmer often does not
know how a function written by another programmer works. In fact, sharing
knowledge about how a function works can be counterproductive. Instead, the
precondition and postcondition provide all the interaction that’s needed. In
effect, the precondition/postcondition pair forms a contract between the pro-
grammer who uses a function and the programmer who writes that function. To
aid the explanation of this “contract,” we’ll give these two programmers names.
Judy is the head of a programming team that is writing a large piece of software.
Jervis
Specification, Design, Implementation 9

Jervis is one of her programmers,


who writes various functions for Whereas Jervis Pendleton has written
Judy to use in large programs. If Judy celsius_to_fahrenheit (henceforth known
and Jervis were lawyers, the contract as “the method”) and Judy Abbott is going
might look like the scroll shown in to use the method, we hereby agree that:
the margin. As a programmer, the
(i) Judy will never call the method
contract tells them precisely what the unless she is certain that the precondition
function does. It states that if Judy is true, and
makes sure that the precondition is
met when the function is called, then (ii) Whenever the method is called and
Jervis ensures that the function re- the precondition is true when the method
turns with the postcondition satisfied. is called, then Jervis guarantees that:
the a. the method will eventually end
Before long, we will provide both
the specification and the implemen- precondition/ (infinite loops are forbidden!), and

tation of the celsiusToFahrenheit postcondition b. when the method ends, the


contract postcondition will be true.
method. But keep in mind that we
Judy Abbott
need only the specification in order
J Pendleton
to know how to use the method.

5. The Throws List. It is always the responsibility of the programmer who uses
a method to ensure that the precondition is valid. Calling a method without ensur-
ing a valid precondition is a programming error. Once the precondition fails, the
method’s behavior is unpredictable—the method could do anything at all. None-
theless, the person who writes a method should make every effort to avoid the
more unpleasant behaviors, even if the method is called incorrectly. As part of
this effort, the first action of a method is often to check that its precondition has
been satisfied. If the precondition fails, then the method throws an exception.
You may have used exceptions in your previous programming, or maybe not. In
either case, the next programming tip describes the exact meaning of throwing
an exception to indicate that a precondition has failed.

PROGRAMMING TIP 
THROW AN EXCEPTION TO INDICATE A FAILED PRECONDITION
It is a programming error to call a method when the precondition is invalid.
For example, celsiusToFahrenheit should not be called with an argument
that is below -273.15. Despite this warning, some programmer may try
celsiusToFahrenheit(-9001) or celsiusToFahrenheit(-273.16). In such
a case, our celsiusToFahrenheit method will detect that the precondition has
been violated, immediately halt its own work, and pass a “message” to the call
ing program to indicate that an illegal argument has occurred. Such messages for
programming errors are called exceptions. The act of halting your own work
and passing a message to the calling program is known as throwing an
exception.
10 Chapter 1 / The Phases of Software Development

how to throw an The Java syntax for throwing an exception is simple. You begin with the key
exception word throw and follow this pattern:
throw new _____________________ (" _____________________ ");

This is the type of exception we are throwing. To begin This is an error message that will be passed as
with, all of our exceptions will be the type part of the exception. The message should
IllegalArgumentException, which is describe the error in a way that will help the
provided as part of the Java language. This type of programmer fix the programming error.
exception tells a programmer that one of the method’s
arguments violated a precondition.

what happens When an exception is thrown in a method, the method stops its computation.
when an A new “exception object” is created, incorporating the indicated error message.
exception is The exception, along with its error message, is passed up to the method or pro
thrown? gram that made the illegal call in the first place. At that point, where the illegal
call was made, there is a Java mechanism to “catch” the exception, try to fix the
error, and continue with the program’s computation. You can read about excep
tion catching in Appendix C. However, exceptions that arise from precondition
violations should never be caught because they indicate programming errors that
must be fixed. When an exception is not caught, the program halts, printing the
error message along with a list of the method calls that led to the exception. This
error message can help the programmer fix the programming error.
Now you know the meaning of the specification’s “throws list.” It is a list of all
the exceptions that the method can throw, along with a description of what
causes each exception. Certain kinds of exceptions must also be listed in a
method’s implementation, after the parameter list, but an IllegalArgument-
Exception is listed only in the method’s specification.

Temperature Conversion: Implementation

Our specification and design are now in place. The subtasks are small enough to
implement, though during the implementation you may need to finish small
design tasks such as finding the conversion formula. In particular, we can now
implement the temperature program as a Java application program with two
methods:
• a main method that follows the pseudocode from page 5. This main
method prints the temperature conversion table using the method
celsiusToFahrenheit to carry out some of its work.
• the celsiusToFahrenheit method.
Specification, Design, Implementation 11

The Java application program with these two methods appears in Figure 1.1.
The program produces the output from our initial specification on page 4.
A few features of the implementation might be new to you, so we will discuss
these in some programming tips after the figure.

FIGURE 1.1 Specification and Implementation for the Temperature Conversion Application

Class TemperatureConversion

♦♦
♦ public class TemperatureConversion
The TemperatureConversion Java application prints a table converting Celsius to Fahrenheit
degrees.

Specification
♦ main
public static void main(String[ ] args)
The main method prints a Celsius-to-Fahrenheit conversion table. The String arguments
(args) are not used in this implementation. The bounds of the table range from –50C to +50C
in 10-degree increments.
♦ celsiusToFahrenheit
public static double celsiusToFahrenheit(double c)
Convert a temperature from Celsius degrees to Fahrenheit degrees.
Parameters:
c – a temperature in Celsius degrees
Precondition:
c >= -273.15.
Returns:
the temperature c converted to Fahrenheit degrees
Throws: IllegalArgumentException
Indicates that c is less than the smallest Celsius temperature (−273.15).

These specifications were


automatically produced by the
Javadoc tool. Appendix H
describes how to use Javadoc
to produce similar information.

(continued)
12 Chapter 1 / The Phases of Software Development

(FIGURE 1.1 continued)


The actual implementation includes
Javadoc comments that are omitted here
Java Application Program but are listed in Appendix H. The
comments allow Javadoc to produce
// File: TemperatureConversion.java from
nicely formatted information
// www.cs.colorado.edu/~main/applications/
automatically. See Appendix H to read
// A Java application to print a
about using Javadoc for your programs.
// temperature conversion table.
// Additional Javadoc information is available on page 11 or at
// http://www.cs.colorado.edu/~main/docs/TemperatureConversion.html.

public class TemperatureConversion


{
public static void main(String[ ] args)
{
// Declare values that control the table’s bounds.
final double TABLE_BEGIN = -50.0; // The table’s first Celsius temperature
final double TABLE_END = 50.0; // The table’s final Celsius temperature
final double TABLE_STEP = 10.0; // Increment between temperatures in table

double celsius; // A Celsius temperature


double fahrenheit; // The equivalent Fahrenheit temperature

System.out.println("TEMPERATURE CONVERSION");
System.out.println("----------------------");
System.out.println("Celsius Fahrenheit");
for (celsius = TABLE_BEGIN; celsius <= TABLE_END; celsius += TABLE_STEP)
{ // The for-loop has set celsius equal to the next Celsius temperature of the table.
fahrenheit = celsiusToFahrenheit(celsius);
System.out.printf("%6.2fC", celsius);
System.out.printf("%14.2fF\n", fahrenheit);
}
System.out.println("----------------------");
}

public static double celsiusToFahrenheit(double c)


{
final double MINIMUM_CELSIUS = -273.15;
if (c < MINIMUM_CELSIUS)
throw new IllegalArgumentException("Argument " + c + " is too small.");
return (9.0/5.0) * c + 32;
}
}
Specification, Design, Implementation 13

PROGRAMMING TIP 
USE JAVADOC TO WRITE SPECIFICATIONS
The specification at the start of Figure 1.1 was produced in an interesting way. the Javadoc tool
Most of it was automatically produced from the Java code by a tool called automatically
Javadoc. With a web browser, you can access this specification over the Internet produces nicely
at: http://www.cs.colorado.edu/~main/docs/TemperatureConversion.html. formatted
To use Javadoc, the .java file that you write needs special Javadoc information
comments. These necessary comments are not listed in Figure 1.1, but Appen about a class
dix H is a short manual on how to write these comments. Before you go on to
Chapter 2, you should read through the appendix and be prepared to produce
Javadoc comments for your own programs.

PROGRAMMING TIP 
USE FINAL VARIABLES TO IMPROVE CLARITY
The method implementation in Figure 1.1 has a local variable declared this way:
final double MINIMUM_CELSIUS = -273.15;
This is a declaration of a double variable called MINIMUM_CELSIUS, which is
given an initial value of −273.15. The keyword final, appearing before the
declaration, makes MINIMUM_CELSIUS more than just an ordinary declaration. It
is a final variable, which means that its value will never be changed while the
program is running. A common programming style is to use all capital letters for
the names of final variables. This makes it easy to determine which variables are
final and which may have their values changed.
There are several advantages to defining MINIMUM_CELSIUS as a final vari
able rather than using the constant −273.15 directly in the program. Using the
name MINIMUM_CELSIUS makes the comparison (c < MINIMUM_CELSIUS) easy
to understand; it’s clear that we are testing whether c is below the minimum valid
Celsius temperature. If we used the direct comparison (c < −273.15) instead, a
person reading our program would have to stop to remember that −273.15 is
“absolute zero,” the smallest Celsius temperature.
To increase clarity, some programmers declare all constants as final variables.
This is a good rule, particularly if the same constant appears in several different
places in the program or if you plan to later compile the program with a different
value for the constant. However, wellknown formulas may be more easily recog
nized in their original form. For example, the conversion from Celsius to Fahren
heit is recognizable as F = 9--5- C + 32. Thus, Figure 1.1 uses this statement:
return (9.0/5.0) * c + 32;
This return statement is clearer and less error prone than a version that uses final
variables for the constants --95- and 32.
Advice: Use final variables instead of constants. Make exceptions when con
stants are clearer or less error prone. When in doubt, write both solutions and
interview several colleagues to decide which is clearer.
14 Chapter 1 / The Phases of Software Development

 PROGRAMMING TIP
MAKE EXCEPTION MESSAGES INFORMATIVE
If the celsiusToFahrenheit method detects that its parameter, c, is too small,
then it throws an IllegalArgumentException. The message in the exception is:
"Argument " + c + " is too small."

The parameter, c, is part of the message. If a programmer attempts to call


celsiusToFahrenheit(-300), the message will be “Argument -300 is too small.”

 PROGRAMMING TIP
FORMAT OUTPUT WITH SYSTEM.OUT.PRINTF
Our pseudocode for the temperature problem includes a step to print the Celsius
and Fahrenheit temperatures rounded to a specified accuracy. Java has a
method, System.out.printf, that we can use to print formatted output such as
rounded numbers. The method, which is based on a similar function in the C lan
guage, always has a “format string” as its first argument. The format string tells
how subsequent arguments should be printed to System.out (which is usually
the computer monitor). For example, you could create an appropriate format
string and print two numbers called age and height:

System.out.println( format string , age, height);

Two things can appear in a format string:


1. Most ordinary characters are just printed as they appear in the format
string. For example, if the character F appears in the format string, then this
will usually just print an F. Some sequences of characters are special, such
as \n (which moves down to start the next new line). The complete list of
special characters is in Appendix B.
2. Parts of the format string that begin with the % character are called format
specifiers. Each format specifier indicates how the next item should be
printed. Some of the common format specifiers are shown here:
Format specifier Causes the next item to be printed as ...

%d ... a decimal (base 10) whole number


%f ... a floating point number with six digits after the
decimal point
%g ... a floating point number using scientific notation
for large exponents
%s ... a string

The format specifiers have several additional options that are described in
Appendix B. For our program, we used a format specifier of the form %6.2f,
Specification, Design, Implementation 15

which means that we want to print a floating point number using six total spaces,
two of which are after the decimal point. Within these six spaces, the number will
be rounded to two decimal points and right justified. For example, the number
42.129 will print these six characters (the first of which is a blank space):

4 2 . 1 3

In the format specifier %6.2f, the number 6 is the field width, and the number
2 is the precision.
As an example, System.out.println("%14.2fF\n", fahrenheit) prints
the value of the fahrenheit variable using a field width of 14 and a precision of
2. After printing this number, the character F and a new line will appear.

Self-Test Exercises for Section 1.1


Each section of this book finishes with a few self-test exercises. Answers to
these exercises are given at the end of each chapter. The first exercise refers to a
method that Judy has written for you to use. Here is the specification:
♦ dateCheck
public static int dateCheck(int year, int month, int day)
Compute how long until a given date will occur.
Parameters:
year – the year for a given date
month – the month for a given date (using 1 for Jan, 2 for Feb, etc.)
day – the day of the month for the given date
Precondition:
The three arguments are a legal year, month, and day of the month in the
years 1900 to 2099.
Returns:
If the given date has been reached on or before today, the return value is
zero. Otherwise, the return value is the number of days until the given
date returns.
Throws: IllegalArgumentException
Indicates the arguments are not a legal date in the years 1900 to 2099.

1. Suppose you call the method dateCheck(2013, 7, 29). What is the


return value if today is July 22, 2013? What if today is July 30, 2013?
What about February 1, 2014?
2. Can you use dateCheck even if you don’t know how it is implemented?
3. Suppose that boodle is a double variable. Write two statements that will
print boodle to System.out in the following format: $ 42,567.19
The whole dollars part of the output can contain up to nine characters
(including the comma), so this example has three spaces before the six
characters of 42,567. The fractional part has just two digits. Appendix B
describes the format string that you’ll need in order to have the number
include a comma separator between the thousands and hundreds.
16 Chapter 1 / The Phases of Software Development

4. Consider a method with this heading:


public static void printSqrt(double x)
The method prints the square root of x to the standard output. Write a
reasonable specification for this method and compare your answer to the
solution at the end of the chapter. The specification should forbid a nega-
tive argument.
5. Consider a method with this heading:
public static double sphereVolume(double radius)
The method computes and returns the volume of a sphere with the given
radius. Write a reasonable specification for this method and compare
your answer to the solution at the end of the chapter. The specification
should require a positive radius.
6. Write an if-statement to throw an IllegalArgumentException when x
is less than zero. (Assume that x is a double variable.)
7. When can a final variable be used?
8. How was the specification produced at the start of Figure 1.1?
9. What are the components of a Java signature?
10. Write a Java statement that will print two variables called age and height.
The age should be printed as a whole number using 10 output spaces; the
height should be printed using 12 output spaces and three decimal digits.
Label each part of the output as “Age” and “Height”. Use Appendix B if
necessary.

1.2 RUNNING TIME ANALYSIS


Time analysis consists of reasoning about an algorithm’s speed. Does the algo-
rithm work fast enough for my needs? How much longer does the algorithm take
when the input gets larger? Which of several different algorithms is fastest?
These questions can be asked at any stage of software development. Some anal-
ysis of an algorithm is useful before any implementation is done to avoid the
wasted work of implementing inappropriately slow solutions. Further analysis
can be carried out during or after an implementation. This section discusses time
analysis, starting with an example that involves no implementation in the usual
sense.

The Stair-Counting Problem


Suppose you and your friend Judy are standing at the top of the Eiffel Tower.
As you gaze out over the French landscape, Judy turns to you and says, “I
wonder how many steps there are to the bottom?” You, of course, are the ever-
accommodating host, so you reply, “I’m not sure ... but I’ll find out.” We’ll look
at three techniques that you could use and analyze the time requirements of each.
Running Time Analysis 17

Technique 1: Walk Down and Keep a Tally. In the first technique, Judy
gives you a pen and a sheet of paper. “I’ll be back in a moment,” you say as you
dash down the stairs. Each time you take a step down, you make a mark on the
sheet of paper. When you reach the bottom, you run back up, show Judy the
piece of paper, and say, “There are this many steps.”

Technique 2: Walk Down, but Let Judy Keep the Tally. In the second tech-
nique, Judy is unwilling to let her pen or paper out of her sight. But you are
undaunted. Once more you say, “I’ll be back in a moment,” and you set off
down the stairs. But this time you stop after one step, lay your hat on the step,
and run back to Judy. “Make a mark on the piece of paper!” you exclaim. Then
you run back to your hat, pick it up, take one more step, and lay the hat down on
the second step. Then back up to Judy: “Make another mark on the piece of
paper!” you say. You run back down the two stairs, pick up your hat, move to
the third step, and lay down the hat. Then back up the stairs to Judy: “Make
another mark!” you tell her. This continues until your hat reaches the bottom,
and you speed back up the steps one more time. “One more mark, please.” At
this point, you grab Judy’s piece of paper and say, “There are this many steps.”

Technique 3: Jervis to the Rescue. In the third technique, Il y a 2689


you don’t walk down the stairs at all. Instead, you spot your marches
friend Jervis by the staircase, holding the sign shown here. The dans cet
translation is There are 2689 steps in this stairway (really!). So escalier
you take the paper and pen from Judy, write the number 2689,
(vraiment!)
and hand the paper back to her, saying, “There are this many
steps.”

This is a silly example, but even so, it does illustrate the


issues that arise when performing a time analysis for an algo-
rithm or program. The first issue is deciding exactly how you
will measure the time spent carrying out the work or executing the program. At
first glance, the answer seems easy: For each of the three stair-counting tech-
niques, just measure the actual time it takes to carry out the work. You could do
this with a stopwatch. But there are some drawbacks to measuring actual time.
Actual time can depend on various irrelevant details, such as whether you or
somebody else carried out the work. The actual elapsed time may vary from per-
son to person, depending on how fast each person can run the stairs. Even if we
decide that you are the runner, the time may vary depending on other factors decide what
such as the weather, what you had for breakfast, and what other things are on operations to
your mind. count
So, instead of measuring the actual elapsed time, we count certain operations
that occur while carrying out the work. In this example, we will count two kinds
of operations:
1. Each time you walk up or down one step, that is one operation.
2. Each time you or Judy marks a symbol on the paper, that is also one
operation.
18 Chapter 1 / The Phases of Software Development

Of course, each of these operations takes a certain amount of time, and making a
mark may take a different amount of time than taking a step. But this doesn’t
concern us because we won’t measure the actual time taken by the operations.
Instead, we will ask: How many operations are needed for each of the three
techniques?
For the first technique, you take 2689 steps down, another 2689 steps up, and
you also make 2689 marks on the paper, for a total of 3 × 2689 operations—that
is 8067 total operations.
For the second technique, there are also 2689 marks made on Judy’s paper,
but the total number of operations is much greater. You start by going down one
step and back up one step. Then down two and up two. Then down three and up
three, and so forth. The total number of operations taken is shown below.

Downward steps = 3,616,705 (which is 1 + 2 + … + 2689 )

Upward steps = 3,616,705

Marks made = 2689

Total operations = Downward steps


+ Upward steps
+ Marks made
= 7,236,099

The third technique is the quickest of all: Only four marks are made on the
paper (that is, we’re counting one “mark” for each digit of 2689), and there is no
going up and down stairs. The number of operations used by each of the tech-
niques is summarized here:

Technique 1 8067 operations


Technique 2 7,236,099 operations
Technique 3 4 operations

Doing a time analysis for a program is similar to the analysis of the stair-
counting techniques. For a time analysis of a program, usually we do not mea-
sure the actual time taken to run the program, because the number of seconds
can depend on too many extraneous factors—such as the speed of the processor
and whether the processor is busy with other tasks. Instead, the analysis counts
the number of operations required. There is no precise definition of what consti-
tutes an operation, although an operation should satisfy your intuition of a
“small step.” An operation can be as simple as the execution of a single program
statement. Or we could use a finer notion of operation that counts each arith-
metic operation (addition, multiplication, etc.) and each assignment to a variable
as a separate operation.
Running Time Analysis 19

For most programs, the number of operations depends on the program’s input. dependence on
For example, a program that sorts a list of numbers is quicker with a short list input size
than with a long list. In the stairway example, we can view the Eiffel Tower as
the input to the problem. In other words, the three different techniques all work
on the Eiffel Tower, but the techniques also work on Toronto’s CN Tower or on
the stairway to the top of the Statue of Liberty or on any other stairway.
When a time analysis depends on the size of the input, then the time can be
given as an expression, where part of the expression is the input’s size. The time
expressions for our three stair-counting techniques are:

Technique 1 3n
Technique 2 n + 2 (1 + 2 + … + n)
Technique 3 The number of digits in the number n

The expressions in this list give the number of operations performed by each
technique when the stairway has n steps.
The expression for the second technique is not easy to interpret. It needs to be
simplified to become a formula that we can easily compare to other formulas. So
let’s simplify it. We start with the following subexpression:

(1 + 2 + … + n)

There is a trick that will enable us to find a simplified form for this expression. simplification of
The trick is to compute twice the amount of the expression and then divide the the time analysis
result by 2. Unless you’ve seen this trick before, it sounds crazy. But it works for Technique 2
fine. The trick is illustrated in Figure 1.2. Let’s go through the computation of
that figure step by step.
We write the expression ( 1 + 2 + … + n ) twice and add the two expressions.
But as you can see in Figure 1.2, we also use another trick: When we write the
expression twice, we write the second expression backward. After we write down
the expression twice, we see the following:

(1 + 2 + … + n)
+( n + … + 2 + 1 )
We want the sum of the numbers on these two lines. That will give us twice the
value of ( 1 + 2 + … + n ) , and we can then divide by 2 to get the correct value
of the subexpression ( 1 + 2 + … + n ) .
Now, rather than proceeding in the most obvious way, we instead add pairs of
numbers from the first and second lines. We add the 1 and the n to get n + 1.
Then we add the 2 and the n – 1 to again get n + 1. We continue until we reach
the last pair consisting of an n from the top line and a 1 from the bottom line. All
the pairs add up to the same amount, namely n + 1. Now that is handy! We get n
numbers, and all the numbers are the same, namely n + 1. So the total of all the
numbers on the preceding two lines is:

n(n + 1)
20 Chapter 1 / The Phases of Software Development

The value of twice the expression is n multiplied by n + 1. We are now essen-


tially done. The number we computed is twice the quantity we want. So, to
obtain our simplified formula, we only need to divide by 2. The final simplifica-
tion is thus:

n(n + 1)
( 1 + 2 + … + n ) = --------------------
2
We will use this simplified formula to rewrite the Technique 2 time expres-
sion, but you’ll also find that the formula occurs in many other situations. The
simplification for the Technique 2 expression is as follows:

Number of operations for Technique 2

= n + 2(1 + 2 + … + n)

= n + 2 ⎛ n-------------------
( n + 1 )-⎞ Plug in the formula for ( 1 + 2 + … + n )
⎝ 2 ⎠

= n + n(n + 1) Cancel the 2s

= n + n2 + n Multiply out

= n2 + 2n Combine terms

So, Technique 2 requires n2 + 2n operations.

FIGURE 1.2 Deriving a Handy Formula

( 1 + 2 + … + n ) can be computed by first computing the sum of twice ( 1 + 2 + … + n ) , as


shown here:

1 + 2 + … + (n – 1) + n
+ n + (n – 1) + … + 2 + 1
(n + 1) + (n + 1) + … + (n + 1) + (n + 1)

The sum is n ( n + 1 ) , so ( 1 + 2 + … + n ) is half this amount:

n( n + 1)
( 1 + 2 + … + n ) = --------------------
2
Running Time Analysis 21

The number of operations for Technique 3 is just the number of digits in the simplification of
integer n when written down in the usual way. The usual way of writing down time analysis for
numbers is called base 10 notation. As it turns out, the number of digits in a Technique 3
number n, when written in base 10 notation, is approximately equal to another
mathematical quantity known as the base 10 logarithm of n. The notation for the
base 10 logarithm of n is written:

log10 n

The base 10 logarithm does not always give a whole number. For example, the base 10 notation
actual base 10 logarithm of 2689 is about 3.43 rather than 4. If we want the and base 10
actual number of digits in an integer n, we need to carry out some rounding. In logarithms
particular, the exact number of digits in a positive integer n is obtained by
rounding log10 n downward to the next whole number and then adding 1. The
notation for rounding down and adding 1 is obtained by adding some symbols to
the logarithm notation as follows:

log 10 n + 1

This is all fine if you already know about logarithms, but what if some of this is
new to you? For now, you can simply define the notation to mean the number of
digits in the base 10 numeral for n. You can do this because if others use any of
the other accepted definitions for this formula, they will get the same answers
that you do. You will be right! (And they will also be right.) In Section 10.3 of
this book, we will show that the various definitions of the logarithm function are
all equivalent. For now, we will not worry about all that detail. We have larger
issues to discuss first. The table of the number of operations for each technique
can now be expressed concisely as shown here:

Technique 1 3n
Technique 2 n2 + 2n
Technique 3 log 10 n + 1

Big-O Notation
The time analyses we gave for the three stair-counting techniques were precise.
They computed the exact number of operations for each technique. But such
precision is not always needed. Often it is enough to know in a rough manner
how the number of operations is affected by the input size. In the stair example,
we started by thinking about a particular tower, the Eiffel Tower, with a particu-
lar number of steps. We expressed our formulas for the operations in terms of n,
which stood for the number of steps in the tower. Now suppose we apply our
various stair-counting techniques to a tower with 10 times as many steps as the
Eiffel Tower. If n is the number of steps in the Eiffel Tower, then this taller
Another random document with
no related content on Scribd:
THE FULL PROJECT GUTENBERG LICENSE
PLEASE READ THIS BEFORE YOU DISTRIBUTE OR USE THIS WORK

To protect the Project Gutenberg™ mission of promoting the


free distribution of electronic works, by using or distributing this
work (or any other work associated in any way with the phrase
“Project Gutenberg”), you agree to comply with all the terms of
the Full Project Gutenberg™ License available with this file or
online at www.gutenberg.org/license.

Section 1. General Terms of Use and


Redistributing Project Gutenberg™
electronic works
1.A. By reading or using any part of this Project Gutenberg™
electronic work, you indicate that you have read, understand,
agree to and accept all the terms of this license and intellectual
property (trademark/copyright) agreement. If you do not agree
to abide by all the terms of this agreement, you must cease
using and return or destroy all copies of Project Gutenberg™
electronic works in your possession. If you paid a fee for
obtaining a copy of or access to a Project Gutenberg™
electronic work and you do not agree to be bound by the terms
of this agreement, you may obtain a refund from the person or
entity to whom you paid the fee as set forth in paragraph 1.E.8.

1.B. “Project Gutenberg” is a registered trademark. It may only


be used on or associated in any way with an electronic work by
people who agree to be bound by the terms of this agreement.
There are a few things that you can do with most Project
Gutenberg™ electronic works even without complying with the
full terms of this agreement. See paragraph 1.C below. There
are a lot of things you can do with Project Gutenberg™
electronic works if you follow the terms of this agreement and
help preserve free future access to Project Gutenberg™
electronic works. See paragraph 1.E below.
1.C. The Project Gutenberg Literary Archive Foundation (“the
Foundation” or PGLAF), owns a compilation copyright in the
collection of Project Gutenberg™ electronic works. Nearly all the
individual works in the collection are in the public domain in the
United States. If an individual work is unprotected by copyright
law in the United States and you are located in the United
States, we do not claim a right to prevent you from copying,
distributing, performing, displaying or creating derivative works
based on the work as long as all references to Project
Gutenberg are removed. Of course, we hope that you will
support the Project Gutenberg™ mission of promoting free
access to electronic works by freely sharing Project Gutenberg™
works in compliance with the terms of this agreement for
keeping the Project Gutenberg™ name associated with the
work. You can easily comply with the terms of this agreement
by keeping this work in the same format with its attached full
Project Gutenberg™ License when you share it without charge
with others.

1.D. The copyright laws of the place where you are located also
govern what you can do with this work. Copyright laws in most
countries are in a constant state of change. If you are outside
the United States, check the laws of your country in addition to
the terms of this agreement before downloading, copying,
displaying, performing, distributing or creating derivative works
based on this work or any other Project Gutenberg™ work. The
Foundation makes no representations concerning the copyright
status of any work in any country other than the United States.

1.E. Unless you have removed all references to Project


Gutenberg:

1.E.1. The following sentence, with active links to, or other


immediate access to, the full Project Gutenberg™ License must
appear prominently whenever any copy of a Project
Gutenberg™ work (any work on which the phrase “Project
Gutenberg” appears, or with which the phrase “Project
Gutenberg” is associated) is accessed, displayed, performed,
viewed, copied or distributed:

This eBook is for the use of anyone anywhere in the United


States and most other parts of the world at no cost and
with almost no restrictions whatsoever. You may copy it,
give it away or re-use it under the terms of the Project
Gutenberg License included with this eBook or online at
www.gutenberg.org. If you are not located in the United
States, you will have to check the laws of the country
where you are located before using this eBook.

1.E.2. If an individual Project Gutenberg™ electronic work is


derived from texts not protected by U.S. copyright law (does not
contain a notice indicating that it is posted with permission of
the copyright holder), the work can be copied and distributed to
anyone in the United States without paying any fees or charges.
If you are redistributing or providing access to a work with the
phrase “Project Gutenberg” associated with or appearing on the
work, you must comply either with the requirements of
paragraphs 1.E.1 through 1.E.7 or obtain permission for the use
of the work and the Project Gutenberg™ trademark as set forth
in paragraphs 1.E.8 or 1.E.9.

1.E.3. If an individual Project Gutenberg™ electronic work is


posted with the permission of the copyright holder, your use and
distribution must comply with both paragraphs 1.E.1 through
1.E.7 and any additional terms imposed by the copyright holder.
Additional terms will be linked to the Project Gutenberg™
License for all works posted with the permission of the copyright
holder found at the beginning of this work.

1.E.4. Do not unlink or detach or remove the full Project


Gutenberg™ License terms from this work, or any files
containing a part of this work or any other work associated with
Project Gutenberg™.

1.E.5. Do not copy, display, perform, distribute or redistribute


this electronic work, or any part of this electronic work, without
prominently displaying the sentence set forth in paragraph 1.E.1
with active links or immediate access to the full terms of the
Project Gutenberg™ License.

1.E.6. You may convert to and distribute this work in any binary,
compressed, marked up, nonproprietary or proprietary form,
including any word processing or hypertext form. However, if
you provide access to or distribute copies of a Project
Gutenberg™ work in a format other than “Plain Vanilla ASCII” or
other format used in the official version posted on the official
Project Gutenberg™ website (www.gutenberg.org), you must,
at no additional cost, fee or expense to the user, provide a copy,
a means of exporting a copy, or a means of obtaining a copy
upon request, of the work in its original “Plain Vanilla ASCII” or
other form. Any alternate format must include the full Project
Gutenberg™ License as specified in paragraph 1.E.1.

1.E.7. Do not charge a fee for access to, viewing, displaying,


performing, copying or distributing any Project Gutenberg™
works unless you comply with paragraph 1.E.8 or 1.E.9.

1.E.8. You may charge a reasonable fee for copies of or


providing access to or distributing Project Gutenberg™
electronic works provided that:

• You pay a royalty fee of 20% of the gross profits you derive
from the use of Project Gutenberg™ works calculated using the
method you already use to calculate your applicable taxes. The
fee is owed to the owner of the Project Gutenberg™ trademark,
but he has agreed to donate royalties under this paragraph to
the Project Gutenberg Literary Archive Foundation. Royalty
payments must be paid within 60 days following each date on
which you prepare (or are legally required to prepare) your
periodic tax returns. Royalty payments should be clearly marked
as such and sent to the Project Gutenberg Literary Archive
Foundation at the address specified in Section 4, “Information
about donations to the Project Gutenberg Literary Archive
Foundation.”

• You provide a full refund of any money paid by a user who


notifies you in writing (or by e-mail) within 30 days of receipt
that s/he does not agree to the terms of the full Project
Gutenberg™ License. You must require such a user to return or
destroy all copies of the works possessed in a physical medium
and discontinue all use of and all access to other copies of
Project Gutenberg™ works.

• You provide, in accordance with paragraph 1.F.3, a full refund of


any money paid for a work or a replacement copy, if a defect in
the electronic work is discovered and reported to you within 90
days of receipt of the work.

• You comply with all other terms of this agreement for free
distribution of Project Gutenberg™ works.

1.E.9. If you wish to charge a fee or distribute a Project


Gutenberg™ electronic work or group of works on different
terms than are set forth in this agreement, you must obtain
permission in writing from the Project Gutenberg Literary
Archive Foundation, the manager of the Project Gutenberg™
trademark. Contact the Foundation as set forth in Section 3
below.

1.F.

1.F.1. Project Gutenberg volunteers and employees expend


considerable effort to identify, do copyright research on,
transcribe and proofread works not protected by U.S. copyright
law in creating the Project Gutenberg™ collection. Despite these
efforts, Project Gutenberg™ electronic works, and the medium
on which they may be stored, may contain “Defects,” such as,
but not limited to, incomplete, inaccurate or corrupt data,
transcription errors, a copyright or other intellectual property
infringement, a defective or damaged disk or other medium, a
computer virus, or computer codes that damage or cannot be
read by your equipment.

1.F.2. LIMITED WARRANTY, DISCLAIMER OF DAMAGES - Except


for the “Right of Replacement or Refund” described in
paragraph 1.F.3, the Project Gutenberg Literary Archive
Foundation, the owner of the Project Gutenberg™ trademark,
and any other party distributing a Project Gutenberg™ electronic
work under this agreement, disclaim all liability to you for
damages, costs and expenses, including legal fees. YOU AGREE
THAT YOU HAVE NO REMEDIES FOR NEGLIGENCE, STRICT
LIABILITY, BREACH OF WARRANTY OR BREACH OF CONTRACT
EXCEPT THOSE PROVIDED IN PARAGRAPH 1.F.3. YOU AGREE
THAT THE FOUNDATION, THE TRADEMARK OWNER, AND ANY
DISTRIBUTOR UNDER THIS AGREEMENT WILL NOT BE LIABLE
TO YOU FOR ACTUAL, DIRECT, INDIRECT, CONSEQUENTIAL,
PUNITIVE OR INCIDENTAL DAMAGES EVEN IF YOU GIVE
NOTICE OF THE POSSIBILITY OF SUCH DAMAGE.

1.F.3. LIMITED RIGHT OF REPLACEMENT OR REFUND - If you


discover a defect in this electronic work within 90 days of
receiving it, you can receive a refund of the money (if any) you
paid for it by sending a written explanation to the person you
received the work from. If you received the work on a physical
medium, you must return the medium with your written
explanation. The person or entity that provided you with the
defective work may elect to provide a replacement copy in lieu
of a refund. If you received the work electronically, the person
or entity providing it to you may choose to give you a second
opportunity to receive the work electronically in lieu of a refund.
If the second copy is also defective, you may demand a refund
in writing without further opportunities to fix the problem.

1.F.4. Except for the limited right of replacement or refund set


forth in paragraph 1.F.3, this work is provided to you ‘AS-IS’,
WITH NO OTHER WARRANTIES OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO WARRANTIES OF
MERCHANTABILITY OR FITNESS FOR ANY PURPOSE.

1.F.5. Some states do not allow disclaimers of certain implied


warranties or the exclusion or limitation of certain types of
damages. If any disclaimer or limitation set forth in this
agreement violates the law of the state applicable to this
agreement, the agreement shall be interpreted to make the
maximum disclaimer or limitation permitted by the applicable
state law. The invalidity or unenforceability of any provision of
this agreement shall not void the remaining provisions.

1.F.6. INDEMNITY - You agree to indemnify and hold the


Foundation, the trademark owner, any agent or employee of the
Foundation, anyone providing copies of Project Gutenberg™
electronic works in accordance with this agreement, and any
volunteers associated with the production, promotion and
distribution of Project Gutenberg™ electronic works, harmless
from all liability, costs and expenses, including legal fees, that
arise directly or indirectly from any of the following which you
do or cause to occur: (a) distribution of this or any Project
Gutenberg™ work, (b) alteration, modification, or additions or
deletions to any Project Gutenberg™ work, and (c) any Defect
you cause.

Section 2. Information about the Mission


of Project Gutenberg™
Project Gutenberg™ is synonymous with the free distribution of
electronic works in formats readable by the widest variety of
computers including obsolete, old, middle-aged and new
computers. It exists because of the efforts of hundreds of
volunteers and donations from people in all walks of life.

Volunteers and financial support to provide volunteers with the


assistance they need are critical to reaching Project
Gutenberg™’s goals and ensuring that the Project Gutenberg™
collection will remain freely available for generations to come. In
2001, the Project Gutenberg Literary Archive Foundation was
created to provide a secure and permanent future for Project
Gutenberg™ and future generations. To learn more about the
Project Gutenberg Literary Archive Foundation and how your
efforts and donations can help, see Sections 3 and 4 and the
Foundation information page at www.gutenberg.org.

Section 3. Information about the Project


Gutenberg Literary Archive Foundation
The Project Gutenberg Literary Archive Foundation is a non-
profit 501(c)(3) educational corporation organized under the
laws of the state of Mississippi and granted tax exempt status
by the Internal Revenue Service. The Foundation’s EIN or
federal tax identification number is 64-6221541. Contributions
to the Project Gutenberg Literary Archive Foundation are tax
deductible to the full extent permitted by U.S. federal laws and
your state’s laws.

The Foundation’s business office is located at 809 North 1500


West, Salt Lake City, UT 84116, (801) 596-1887. Email contact
links and up to date contact information can be found at the
Foundation’s website and official page at
www.gutenberg.org/contact
Section 4. Information about Donations to
the Project Gutenberg Literary Archive
Foundation
Project Gutenberg™ depends upon and cannot survive without
widespread public support and donations to carry out its mission
of increasing the number of public domain and licensed works
that can be freely distributed in machine-readable form
accessible by the widest array of equipment including outdated
equipment. Many small donations ($1 to $5,000) are particularly
important to maintaining tax exempt status with the IRS.

The Foundation is committed to complying with the laws


regulating charities and charitable donations in all 50 states of
the United States. Compliance requirements are not uniform
and it takes a considerable effort, much paperwork and many
fees to meet and keep up with these requirements. We do not
solicit donations in locations where we have not received written
confirmation of compliance. To SEND DONATIONS or determine
the status of compliance for any particular state visit
www.gutenberg.org/donate.

While we cannot and do not solicit contributions from states


where we have not met the solicitation requirements, we know
of no prohibition against accepting unsolicited donations from
donors in such states who approach us with offers to donate.

International donations are gratefully accepted, but we cannot


make any statements concerning tax treatment of donations
received from outside the United States. U.S. laws alone swamp
our small staff.

Please check the Project Gutenberg web pages for current


donation methods and addresses. Donations are accepted in a
number of other ways including checks, online payments and

You might also like