The urge to sit down and start writing code is programs more correct and general-purpose... It is difficult to write correct, efficient, general-purpose programs in a reasonable amount o
Trang 1Print ISBN-13 : 978-0-13-146914-3 eText ISBN-10 : 0-13-174690-1 eText ISBN-13 : 978-0-13-174690-9
Pages : 592
An abundance of unique, interesting examples, use of the Unified Modeling Language throughout, and the newest Java 1.5 features characterize this text Drake provides a concise and engaging introduction to Java and object-oriented programming, assuming familiarity with the basic control structures of Java or C and only
a pre-calculus level of mathematics.
Trang 2Print ISBN-13 : 978-0-13-146914-3 eText ISBN-10 : 0-13-174690-1 eText ISBN-13 : 978-0-13-174690-9
Trang 3Section 3.1 Extending a Class 67 Section 3.2 The Object Class 77 Section 3.3 Packages and Access Levels 79
Trang 4Section 7.1 Timing 183 Section 7.2 Asymptotic Notation 186
Section 7.4 Best, Worst, and Average Case 197 Section 7.5 Amortized Analysis 199
Trang 5Chapter 11 Sets 283 Section 11.1 The Set Interface 283
Trang 6Section 15.2 Representation 413
Section 15.4 Topological Sorting 422 Section 15.5 Shortest Paths 427 Section 15.6 Minimum Spanning Trees 432
Trang 7Appendix B Unified Modeling Language 543
Section B.2 Instance Diagrams 547 Appendix C Summation Formulae 551
Section C.2 Sum of Constants 552 Section C.3 Sum of First n Integers 553 Section C.4 Sums of Halves and Doubles 554 Section C.5 Upper Limit on Sum of a Function 554 Section C.6 Constant Factors 555
Trang 10The author and publisher of this book have used their bestefforts in preparing this book These efforts include the
development, research, and testing of the theories and
programs to determine their effectiveness The author andpublisher make no warranty of any kind, expressed or implied,with regard to these programs or the documentation contained
in this book The author and publisher shall not be liable in anyevent for incidental or consequential damages in connectionwith, or arising out of, the furnishing, performance, or use ofthese programs
Trang 11[Page xi]
Trang 12Intended Audience
Trang 13Intended Audience
This book is intended for a second undergraduate course incomputer science I assume that the reader is familiar with thebasic control structures of Java or C and with elementary
concepts such as variables and decomposing a problem intofunctions (methods) Only a pre-calculus level of mathematics
is expected
Why Choose This Book?
This book has everything you would ever want in a data
structures textbook: plentiful exercises, crystal-clear prose,code available on-line, and just the right amount of depth Ofcourse, every author claims as much What makes this bookdifferent?
Trang 14Version 1.5 of Java adds several long-awaited features to thelanguage These new features are explained and used in manyexamples throughout this book Specifically:
In explaining concepts, I use many diagrams Long stretches oftext, code, and equations make for dry reading A good diagramcan explain a new concept clearly, provide an instant review,and serve as a landmark when reviewing the text Since theUnified Modeling Language has become the de facto standardfor software diagrams, the diagrams in this book are drawn in asubset of the UML I have deliberately left out even
intermediate UML features, such as access level tags and
Trang 15This book is written in the "inverted pyramid" style taught tojournalists: the most important material is at the front, withfiner details and more advanced topics introduced with eachchapter A course could reasonably be stopped after any
chapter This gives instructors the freedom to speed up or slowdown as necessary, without fear of not getting to an importanttopic before the end of the course
Many texts overwhelm the reader with too much abstraction upfront This is an easy mistake to make for fully trained
computer scientists, who prefer to read about the big picture
before delving into details On the other hand, students whomust absorb inheritance, polymorphism, recursion, and analysis
of algorithms before they've written a single "real" program arelikely to lose interest, if not consciousness I constantly hearstudents asking for more concrete examples, and I've neverheard one complain about too many examples
[Page xiii]
With this tension in mind, I have tried to provide examples
early in each chapter Let the students have complete, working
Trang 16Difficult concepts are also introduced as gradually as possible.For example, the call stack is discussed before it appears in thecontext of recursion
Most of my examples are games, often involving dice, cards,and boards Games capture the students' imagination, givingthem some reason to care about the data structure or algorithmbeing discussed While simple enough to program without pagesand pages of code, games offer a more realistic challenge thanantiseptic tasks such as finding a greatest common divisor Nearthe midpoint of the text, games involving a dictionary of tens ofthousands of words provide compelling motivation for efficientdata structures and algorithms
Especially near the beginning of the book, I work through thedevelopment of each project, often providing multiple versions
an exercise It's all here, even code for B-trees; I know of noother undergraduate text that presents this material at this
level of completeness
No classes have to be downloaded in advance to use the code inthis book Later classes make use of earlier classes If desired,these later classes can be easily adapted to use built-in classesfrom the Java collections framework; the method names for theclasses developed in the book are congruent
Trang 17skipped altogether (although there are few students who
wouldn't benefit from a review of this material) At other
institutions, where CS1 is taught in C or some other language,more time may be spent on this material Alternately, this part
of the book (along with Appendix A) is good for a short courseintroducing object-oriented programming
Part II covers stacks, queues, and lists, in both array-based andlinked implementations The reader is shown how these
structures are used and how to build them, then where to findthem in the Java collections framework
In Part III, the reader begins the journey from mere
programming to computer science Analysis of algorithms isintroduced, including asymptotic notation and a step-by-stepprocedure for analyzing simple algorithms After this difficultmaterial, the reader gets a break with a relatively short chapter
on the simplest searching and sorting algorithms By the timerecursion is introduced, the reader has been prepared with anunderstanding of the call stack, an understanding of the sortingproblem, and the ability to appreciate the better performance
Trang 18advanced linear structures, strings, advanced trees, graphs,memory management, and issues involved with disk storage
Finally, one or more projects are given at the end of each
chapter These will usually take an hour or more, and makegood stand-alone homework or lab assignments
Acknowledgments
I wish to thank: my wife Heather, for proofreading above andbeyond the call of duty and for reminding me to eat; Dan
Friedman, for convincing me that I wasn't joking when I beganwriting an early version of this book in graduate school; James
Trang 19allowing me to use his game designs; Alan Apt, for his guidanceand for giving me a shot at the big time; Paul Purdom and
David Wise, for illuminating some of the darker corners of datastructures and algorithms; and all those who have providedcomments, suggestions, and proofreading through the years,including Kevin and Rebecca Djang, Jerry Franke, Matt Jadud,Sid Kitchel, Jim Levenick, countless computer science studentsboth at Indiana University and at Lewis & Clark College, and theanonymous reviewers
PETER DRAKE
Portland, Oregon
Trang 20
[Page 1]
Trang 21Chapter 1 Encapsulation
Chapter 2 Polymorphism
Chapter 3 Inheritance
Trang 22[Page 3]
Trang 23This chapter introduces the object-oriented approach to
software development Section 1.1 discusses the software
development process and the idea of encapsulation: dividing aprogram into distinct components which have limited
interaction In Sections 1.2 and 1.3, we develop a program toplay the game of Beetle Section 1.2 introduces terminologyand concepts related to objects as we write a class to model thedie used in the game Section 1.3 expands on this, developingtwo more classes to complete the program
Some readers may wish to read Appendix A before beginningthis chapter
Trang 25navigation, and nuclear power plant control, lives may literallydepend on the correctness of software In others, such as
games and web browsers, the occasional crash may be merely
an annoyance The best way to ensure correctness is to
precisely specify how the program is supposed to behave andthen thoroughly test the program to verify that it does so
Data structures and algorithms are intimately intertwined Adata structure may support efficient algorithms for some
operations (such as checking whether some item is present) butnot for others (such as removing an item) Conversely, a fastalgorithm may require that data be stored in a particular way
To make the best choices, we would like to know as much aspossible about how our program will be used What kinds ofdata are we likely to encounter? Which operations will be mostcommon? Some of the most efficient data structures and
Trang 26pasting code from previous programs Sometimes the new
program requires changes to the code To minimize the time wespend changing our old code, we try to write general-purposecomponents For example, rather than writing a method to sort
an array of five numbers, we write a method which can sort anarray of any length, containing any values of any comparabletype (numbers, letters, strings, and so on) This general-
purpose code tends to be less efficient than code written for aspecific use It can also take a little more time to make sure it is
correct On the other hand, once it is written and thoroughly
documented we never need to think about its inner workings
againit is a trusty power tool that we can bring out whenever
we need it Established programming languages like Java havehuge, general-purpose libraries for graphics, file handling,
networking, and so on
[Page 5]
Development time is a precious resource to employers (whomust pay their programmers) and students (who are notoriousfor procrastination) As you have probably learned by now frombitter experience, most development time is spent debugging.The way to reduce debugging time is to invest time in designand testing The urge to sit down and start writing code is
programs more correct and general-purpose
Trang 27It is difficult to write correct, efficient, general-purpose
programs in a reasonable amount of time because computerprograms are among the most complex things people have everconstructed Computer scientists have put a great deal of
thought into dealing with this complexity The approach used bythe Java programming language is object-oriented
programming Object-oriented programming is characterized
by three principles:
Encapsulation is the division of a program into distinctcomponents which have limited interaction A method is anexample of an encapsulated component: other methodsinteract with it only through the arguments they pass to itand the value it returns Each component can be tested
separately, improving correctness, and components can berecombined into new programs, improving generality anddevelopment speed This chapter focuses on encapsulation
Polymorphism is the ability of the same word or symbol tomean different things in different contexts For example, inJava, the symbol + means one thing (addition) when
dealing with numbers, but means something else
(concatenation) when dealing with Strings Polymorphismgreatly improves generality, which in turn improves
Inheritance makes code reuse easier, improving
correctness, generality, and development speed
Trang 28None of these features directly improves efficiency Indeed,
there may be some loss of efficiency The consensus amongobject-oriented programmers is that this price is well worth
paying The trouble with software today is not that it runs tooslowly, but that it is buggy and takes too long to develop
on Both jobs are made easier through encapsulation
Encapsulation makes it easier to rapidly develop correct
programs because a programmer only has to consider a fewthings when writing any one component of the program This isparticularly important in projects involving several
programmers: once the programmers have agreed on how thecomponents will interact, each is free to do whatever he wantswithin his component
Trang 29improvements within a component If the stocker had to think
about purchasing, running the cash register, and so on, thenshe might not have time to learn to balance five crates of
rutabagas on a handtruck
We have already seen encapsulation in at least one sense Bydividing a class into methods, we can concentrate on one
method at a time Any variables declared inside a method arevisible only inside that method When we invoke another
method, we only need to know the information in the methodsignature (what arguments it expects and what it returns) andassociated documentation We don't have to know what
happens inside the method
We don't merely have the option to ignore the innards of a
method We actually cannot access variables declared inside a
method from outside that method This is in keeping with theprinciple of information hiding: the workings of a componentshould not be visible from the outside Information hiding
enforces encapsulation Continuing the grocery store analogy,
we don't give the stocker access to the bank account and wedon't give the purchaser the keys to the forklift
Information hiding may seem counterintuitive Isn't it better foreveryone to have as much information as possible? Experiencehas shown that the answer is "no." If someone can see the
inner workings of a component, they may be tempted to takeshortcuts in the name of efficiency With access to the bankaccount, the stocker may reason, "The purchaser is on vacationthis week I'll just order more rutabagas myself." If she doesnot follow proper accounting procedures, or does not realize
Trang 30relatively small programs we will write in this book On the
other hand, our programs are now sufficiently sophisticated thatsome examination of the software development process is inorder If we just sit down and start writing code, we will likelyget into trouble
We can think of the process of writing a program in terms of the
software development cycle (Figure 1-2) We divide the
process into three major phases: design, implementation, andtesting (Many software engineers divide the process into morephases.)
Figure 1-2 The software development cycle.
Trang 31stating precisely what a program is supposed to do In a
programming class, the problem specification is often given asthe assignment In real life, problem specification involves
working with the end user (for example, the customer,
employer, or scientific community) to decide what the programshould do
The design phase also includes breaking the program down intocomponents What are the major components of the program?What is each component supposed to do? How do the
components interact? It is a good idea to write a comment foreach component at this point, so that we have a very clear
understanding of what the component does Commenting firstalso avoids the danger that we'll put off commenting until ourprogram has become hopelessly complicated
The implementation phase is the writing of code This is
where we move from a description of a program to a (hopefully)
working program Many students erroneously believe that this isthe only phase in which actual programming is occurring, so theother two phases are unimportant In fact, the more time spent
on the other two phases, the less is needed in implementation
If we rush to the keyboard to start coding, we may end up
having to throw away some of our work because it doesn't fit inwith the rest of the program or doesn't meet the problem
specification
Trang 32element, and where it is not present at all
The French poet Paul Valéry wrote, "A poem is never finished,only abandoned." The same can be said of computer programs.There is some point when the software is released, but there isoften maintenance to be performed: changes to make, newfeatures to add, bugs to fix This maintenance is just more
iterations of the software development cycle This is why thecycle has no point labeled "end" or "finished." In a
we put off our design decisions, we avoid wasting time
redesigning the program if we discover that, for example, we
Trang 33In practice, most software development falls between these twoextremes In this chapter, we will lean toward the bottom-upend of the spectrum When we are first learning to program, wedon't yet have the experience to envision the structure of anentire program We are also likely to make a lot of coding
errors, so we should test early and often
Encapsulation allows us to break up the software developmentcycle (Figure 1-3)
(This item is displayed on page 9 in the print version)
Once we divide the program into encapsulated components, wecan work on each one separately In a project with several
Trang 34concentrate on a single component makes it much easier torapidly develop correct, efficient, general-purpose code Oncethe components are "complete," we integrate them in a high-level implementation phase and then test the entire system
Trang 351.2 Classes and Objects
This section illustrates the software development cycle andintroduces some concepts from object-oriented programming
As an extended example, we develop a program to play thegame of Beetle (Figure 1-4)
Trang 366 If your beetle already has a tail or has no body, pass the die to
the next player Otherwise, add a tail and roll again.
Classes
In Appendix A, we use the word "class" as a rough synonym for
"program." While each program needs to have a main() method
Breaking our program down into classes is the first step in
design For the Beetle game, we will need three classes: theclass of beetles, the class of dice, and the class of Beetle
games (We create one instance of the last class each time weplay the game.) This organization is illustrated in Figure 1-5.This type of diagram is called a UML class diagram The UML(Unified Modeling Language) is a widely used set of notationsfor diagramming many aspects of software development, fromuser interactions to relationships between methods Most of theUML is beyond the scope of this book, but we will use these
Trang 37case letter The three classes we need to build are thereforecalled Die, Beetle, and BeetleGame Each class is defined in aseparate file, which must have the same name as the class and
Trang 38The methods of the object are actions it can perform Inobject-oriented programming, we don't do things to objects
Trang 39don't roll a die, we ask it to roll itself All instances of a
given class have the same methods
In order to make our development cycle for the Die class asshort as possible, we start by thinking, "It will have to keep
track of which face is on top." We'll design other features, such
as the method for rolling, later In a top-down approach to
software development, on the other hand, we would specify all
of the methods before thinking about implementation detailssuch as fields
A first shot at implementing the Die class is shown in
Figure 1-9
Figure 1-9 A first shot at implementing the Die class It compiles, but it doesn't run.
Trang 40accessed by methods in other classes When other classes dothings with Die instances, code in those classes can't accessprivate fields directly This is an example of information hiding.Let's put in an empty main() method (Figure 1-10)
Figure 1-10 The class can now be run, although it still doesn't do anything.
in the new code By making such small, incremental changes tothe code, we can avoid spending a lot of time hunting for bugs
We have now completed one iteration of the software
development cycledesign, implementation, and testingfor theDie class
Constructors