Instant Ebooks Textbook Data Structures Other Objects Using Java 4th Edition Michael Mann Download All Chapters
Instant Ebooks Textbook Data Structures Other Objects Using Java 4th Edition Michael Mann Download All Chapters
com
https://ebookgate.com/product/data-structures-
other-objects-using-java-4th-edition-michael-mann/
https://ebookgate.com/product/data-structures-and-other-objects-
using-c-4th-edition-michael-main/
https://ebookgate.com/product/data-structures-problem-solving-
using-java-4th-edition-mark-allen-weiss/
https://ebookgate.com/product/java-software-structures-designing-
and-using-data-structures-3rd-edition-john-lewis/
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/
https://ebookgate.com/product/data-structures-outside-in-with-
java-1st-edition-sesh-venugopal/
https://ebookgate.com/product/data-structures-and-abstractions-
with-java-2nd-ed-edition-carrano/
https://ebookgate.com/product/data-structures-using-c-2nd-
edition-d-s-malik/
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
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.
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
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.
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
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.
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.
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).
Chapter Dependencies
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)
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.
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.
Chapter List
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
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
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
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.
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:
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.
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.
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.
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.
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
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.
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).
(continued)
12 Chapter 1 / The Phases of Software Development
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("----------------------");
}
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."
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:
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.
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.”
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.
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:
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
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:
= n + 2(1 + 2 + … + n)
= n + 2 ⎛ n-------------------
( n + 1 )-⎞ Plug in the formula for ( 1 + 2 + … + n )
⎝ 2 ⎠
= n + n2 + n Multiply out
= n2 + 2n Combine terms
1 + 2 + … + (n – 1) + n
+ n + (n – 1) + … + 2 + 1
(n + 1) + (n + 1) + … + (n + 1) + (n + 1)
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
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.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.
• 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 comply with all other terms of this agreement for free
distribution of Project Gutenberg™ works.
1.F.