DATA STRUCTURES & OTHER OBJECTS
4TH EDITION
MICHAEL MAIN
Department of Computer Science University of Colorado at Boulder
WALTER SAVITCH
Department of Computer Science and Engineering University of California, San Diego
Addison-Wesley
Boston Columbus Indianapolis NewYork San Francisco Upper Saddle River
Amsterdam CapeTown Dubai London Madrid Milan Munich Paris Montreal Toronto
Delhi MexicoCity SaoPaulo Sydney HongKong Seoul Singapore Taipei Tokyo
ii Preface
Editor-in-Chief: Michael HirschMarketing Manager:Erin Davis
Editorial Assistant:Stephanie SellingerMarketing Coordinator:Kathryn Ferranti
Managing Editor:Jeffrey HolcombArt Director: Linda Knowles
Production Project Manager:Heather McNallyCover Designer:Elena Sidorova
Copy Editor: Sada Preisch Cover Artwork:© 2010 Stocksearch / Alamy
Proofreader: Genevieve d’EntremontSenior Manufacturing Buyer: Carol Melville
Access the latest information about all Pearson Addison-Wesley Computer Science titles from our World Wide Web site: http://www.pearsonhighered.com/cs
The programs and applications presented in this book have been included for their instructional value. They have been tested with care, but are not guaranteed for any particular purpose. The publisher does not offer any warranties or representations, nor does it accept any liabilities with respect to the programs or applications.
Credits and acknowledgments borrowed from other sources and reproduced, with permission, in this textbook appear on appropriate page within text.
UNIX® is a registered trademark in the United States and other countries, licensed exclusively through X-Open Company, Ltd. Pez® is a registered trademark of Pez Candy, Inc.
Copyright © 2011, 2005, 2001, 1997 Pearson Education, Inc., publishing as Addison-Wesley, 501 Boylston Street, Suite 900, Boston MA 02116. 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. To obtain permission(s) to use material from this work, please submit a written request to Pearson Education, Inc., Permissions Department, , 501 Boylston Street, Suite 900, Boston MA 02116.
Many of the designations by manufacturers and seller 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), 1956–
Data structures and other objects using C++ / Michael Main, Walter Savitch.-- 4th ed. p.cm. Includes index.
ISBN 978-0-13-212948-0 (pbk.)
1. C++ (Computer program language) 2. Data structures (Computer science) 3. Object-oriented programming (Computer science) I. Savitch, Walter J., 1943–II. Title.
QA76.73.C153M252010
005.13’3—dc22
1 2 3 4 5 6 7 8 9 10--CRS--14 13 12 11 10
2009049328 CIP
ISBN 10: 0-13-212948-5
ISBN 13: 978-0-13-212948-0
Preface
This book is written for a second course in computer science, the CS 2 course at many universities. The text’s emphasis is on the specification, design, implementation, and use of the basic data types that normally are covered in a second-semester course. In addition, we cover a range of important programming techniques and provide self-contained coverage of abstraction techniques, object-oriented programming, big-O time analysis of algorithms, and sorting.
We assume that the student has already had an introductory computer science and programming class, but we do include coverage of those topics (such as recursion and pointers) that are not always covered completely in a first course. The text uses C++, but our coverage of C++ classes begins from scratch, so the text may be used by students whose introduction to programming was in C rather than C++.In our experience, such students need a brief coverage of C++ input and output techniques (such as those provided in Appendix F) and some coverage of C++ parameter types (which we provide in Chapter 2). When C programmers are over the input/output hurdle and the parameter hurdle (and perhaps a small “fear” hurdle), they can step readily into classes and other object-oriented features of C++. As this indicates, there are several pathways through the text that can be tailored to different backgrounds, including some optional features for the student who comes to the class with a stronger than usual background.
New to This Edition
The C++ Standard Template Library (STL) plays a larger role in our curriculum than past editions, and we have added selected new material to support this. For us, it’s important that our students understand both how to use the STL classes in an application program and the possible approaches to imple- iii
menting these (or similar) classes. With this in mind, the primary changes that you’ll find for this edition are:
•A new Section 2.6 that gives an early introduction to the Standard Template Library using the pair class. We have been able to introduce students to the STL here even before they have a full understanding of templates.
•An earlier introduction of the multiset class and STL iterators in Section 3.4. This is a good location for the material because the students have just seen how to implement their first collection class (the bag), which is based on the multiset.
•We continue to introduce the STL string class in Section 4.5, where it’s appropriate for the students to implement their own string class with a dynamic array.
•A new Section 5.6 that compares three similar STL classes: the vector, the list, and the deque. At this point, the students have enough knowledge to understand typical vector and list implementations.
•A first introduction to the STL algorithms appears in Section 6.3, and this is now expanded on in Sections 11.2 (the heap algorithms) and 13.4 (expanded coverage of sorting and binary search in the STL).
•A new Section 8.4 provides typical implementation details for the STL deque class using an interesting combination of dynamic arrays and pointers.
•A discussion of hash tables in the proposed TR1 expansions for the STL is now given in Section 12.6.
Most chapters also include new programming projects, and you may also keep an eye on our project web site, www.cs.colorado.edu/~main/dsoc.html, for new projects as we develop them.
The Steps for Each Data Type
Overall, the fourth edition remains committed to the data types: sets, bags (or multisets), sequential lists, ordered lists (with ordering from a “less than” operator), stacks, queues, tables, and graphs. There are also additional supplemental data types such as a priority queue. Each of these data types is introduced following a consistent pattern:
Step 1: Understand the datatypeabstractly. At this level, a student gains an understanding of the data type and its operations at the level of concepts and pictures. 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 C++ class. In this step, the student sees and learns how to write a specification for a C++ class that can
implement the data type. The specification includes prototypes for the constructors, public member functions, and sometimes other public features (such as an underlying constant that determines the maximum size of a stack). The prototype of each member function is presented along with a precondition/postcondition contract that completely specifies the behavior of the function. 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 datatype. With the specification in place, students can write small applications or demonstration programs to show the data type in use. These applications are based solely on the data type’s specification, as we still have not tied down the implementation.
Step 4: Select appropriatedatastructures, and proceed to design and implement the datatype. With a good abstract understanding of the data type, we can select an appropriate data structure, such as a fixed-sized array, a dynamic 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 a fixed-sized array. Later, we will redesign and reimplement the same data type with a more complicated underlying structure.
Since we are using C++ classes, an implementation of a data type will have the selected data structures (arrays, pointers, etc.) as private member variables of the class. With each implemented class, we stress the necessity for a clear understanding of the rules that relate the private member variables to an abstract notion of the data type. We require each student to write these rules in clear English sentences that we call the invariant of the abstract data type. Once the invariant is written, students can proceed to implementing various member functions. The invariant helps in writing correct functions because of two facts: (a) Each function (except constructors) knows that the invariant is true when the function begins its work; and (b) each function (except the destructor) is responsible for ensuring that the invariant is again true when the function finishes.
Step 5: Analyze the implementation. Each implementation can be analyzed for correctness, flexibility (such as a fixed size versus dynamic size), 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, they know how to implement them several ways, and they know the practical effects of the different implementation choices. The students can reason about efficiency with a big-O analysis and
argue for the correctness of their implementations by referring to the invariant of the class.
One of the important lasting effects of the course is the specification, design, and implementation experience. The improved ability to reason about programs is also important. But perhaps most important of all is the exposure to classes that are easily used in many situations. The students no longer have to write everything from scratch. We tell our students that someday they will be thinking about a problem, and they will suddenly realize that a large chunk of the work can be done with a bag, or a stack, or 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 or some such 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 C++ Standard Template Library. In fact, the behavior of the data types in this text is a cut-down version of the Standard Template Library, so when students take the step to the real STL, they will be on familiar ground. And at that point of realization, knowing that a certain data type is the exact solution he or she needs, the student becomes a real programmer.
Other Foundational Topics
Throughout the course, we also lay a foundation for other aspects of “real programming,” with coverage of the following topics beyond the basic data structures material:
Object-orientedprogramming. The foundations of object-oriented programming (OOP) are laid by giving students a strong understanding of C++ classes. The important aspects of classes are covered early: the notion of a member function, the separation into private and public members, the purpose of constructors, and a small exposure to operator overloading. This is enough to get students going and excited about classes.
Further major aspects of classes are introduced when the students first use dynamic memory (Chapter 4). At this point, the need for three additional items is explained: the copy constructor, the overloaded assignment operator, and the destructor. Teaching these OOP aspects with the first use of dynamic memory has the effect of giving the students a concrete picture of dynamic memory as a resource that can be taken and must later be returned.
Conceptually, the largest innovation of OOP is the software reuse that occurs via inheritance. And 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 juggling too many new concepts at once, resulting in a weaker understanding of the fundamental data structures. Therefore, in our own course we introduce inheritance at the end as a vision of things to come. But the introduction to inheritance (Sections 14.1 and 14.2) could be covered as soon as copy constructors are
understood. With this in mind, some instructors may wish to cover Chapter 14 earlier, just before stacks and queues.
Another alternative is to identify students who already know the basics of classes. These students can carry out an inheritance project (such as the ecosystem of Section 14.2 or the game engine in Section 14.3) while the rest of the students first learn about classes.
Templates. Template functions and template classes are an important part of the proposed Standard Template Library, allowing a programmer to easily change the type of the underlying item in a container class. Template classes also allow the use of several different instantiations of a class in a single program. As such, we think it’s important to learn about and use templates (Chapter 6) prior to stacks (Chapter 7), since expression evaluation is an important application that uses two kinds of stacks.
Iterators. Iterators are another important part of the proposed Standard Template Library, allowing a programmer to easily step through the items in a container object (such as the elements of a set or bag). Such iterators may be internal (implemented with member functions of the container class) or external (implemented by a separate class that is a friend of the container class). We introduce internal iterators with one of the first container classes (a sequential list in Section 3.2). An internal iterator is added to the bag class when it is needed in Chapter 6. At that point, the more complex external iterators also are discussed, and students should be aware of the advantages of an external iterator. Throughout the text, iterators provide a good opportunity for programming projects, such as implementing an external bag iterator (Chapter 6) or using a stack to implement an internal iterator of a binary search tree (Chapter 10).
Recursion. First-semester courses sometimes introduce students to recursion. But many of the first-semester examples are tail recursion, where the final act of the function is the recursive call. This may have given students a misleading impression that recursion is nothing more than a loop. Because of this, we prefer to avoid early use of tail recursion in a second-semester course. For example, list traversal and other operations on linked lists can be implemented with tail recursion, but the effect may reinforce wrong impressions about recursion (and the tail recursive list operations may need to be unlearned when the students work with lists of thousands of items, running into potential run-time stack overflow).
So, in our second-semester course, we emphasize recursive solutions that use more than tail recursion. The recursion chapter provides three examples along these lines. Two of the examples—generating random fractals and traversing a maze—are big hits with the students. In our class, we teach recursion (Chapter 9) just before trees (Chapter 10), since it is in recursive tree algorithms that recursion becomes vital. However, instructors who desire more emphasis on recursion can move that topic forward, even before Chapter 2.
viii Preface
In a course that has time for advanced tree projects (Chapter 11), we analyze the recursive tree algorithms, explaining the importance of keeping the trees balanced—both to improve worst-case performance, and to avoid potential runtime stack overflow.
Searching and sorting. Chapters 12 and 13 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 also are introduced in the search chapter. 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 heap sort (with worst-case time of O(n log n)). There is also a new introduction to the C++ Standard Library sorting functions.
Advanced Projects
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:
•A polynomial class using dynamic memory (Section 4.6).
•An introduction to Standard Library iterators, culminating in an implementation of an iterator for the student’s bag class (Sections 6.3 through 6.5).
•An iterator for the binary search tree (Programming Projects in Chapter 10).
•A priority queue, implemented with a linked list (Chapter 8 projects), or implemented using a heap (Section 11.1).
•A set class, implemented with B-trees (Section 11.3). We have made a particular effort on this project to provide information that is sufficient for students to implement the class without need of another text. In our courses, we have successfully directed advanced students to do this project as independent work.
•An inheritance project, such as the ecosystem of Section 14.2.
•An inheritance project using an abstract base class such as the game base class in Section 14.3 (which allows easy implementation of two-player games such as Othello or Connect Four).
•A graph class and associated graph algorithms from Chapter 15. This is another case where advanced students may do work on their own.
C++ Language Features
C++ is a complex language with many advanced features that will not be touched in a second-semester course. But we endeavor to provide complete coverage for those features that we do touch. In the first edition of the text, we included coverage of two features that were new to C++ at the time: the new bool data type (Figure2.1 on page37) and static member constants (see page104). The requirements for using static member constants were changed in the 1998 Standard, and we have incorporated this change into the text (the constant must now be declared both inside and outside the class definition). The other primary new feature from the 1998 Standard is the use of namespaces, which were incorporated in the second edition. In each of these cases, these features might not be supported in older compilers. We provide some assistance in dealing with this (see Appendix E, “Dealing with Older Compilers”), and some assistance in downloading and installing the GNU g++ compiler (see Appendix K).
Flexibility of Topic Ordering
This book was written to allow 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 pagexi. 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:
Typicalcourse. Start with Chapters 1–10, skipping parts of Chapter 2 if the students have a prior background in C++ classes. Most chapters can be covered in a week, but you may want more time for Chapter 5 (linked lists), Chapter 6 (templates), Chapter 9 (recursion), or Chapter 10 (trees). Typically, we cover the material in 13 weeks, including time for exams and extra time for linked lists and trees. Remaining weeks can be spent on a tree project from Chapter 11, or on binary search (Section 12.1) and sorting (Chapter 13).
Heavy OOP emphasis. If students cover sorting and searching elsewhere, there will be time for a heavier emphasis on object-oriented programming. The first four chapters are covered in detail, and then derived classes (Section 14.1) are introduced. At this point, students can do an interesting OOP project, based on the ecosystem of Section 14.2 or the games in Section 14.3. The basic data structures are then covered (Chapters 5–8), with the queue implemented as a derived class (Section 14.3). Finish up with recursion (Chapter 9) and trees (Chapter 10), placing special emphasis on recursive member functions.
Acceleratedcourse. Assign the first three chapters as independent reading in the first week, and start with Chapter 4 (pointers). This will leave two to three
x Preface
extra weeks at the end of the term, so that students may spend more time on searching, sorting, and the advanced topics (shaded on pagexi.)
We also have taught the course with further acceleration by spending no lecture time on stacks and queues (but assigning those chapters as reading).
Earlyrecursion / earlysorting. One to three weeks may be spent at the start of class on recursive thinking. The first reading will then be Chapters 1 and 9, perhaps supplemented by additional recursive projects.
If recursion is covered early, you may also proceed to cover binary search (Section 12.1) and most of the sorting algorithms (Chapter 13) before introducing C++ classes.
Supplements via the Internet
The following supplemental materials for this text are available to all readers at www.aw-bc.com/cssupport:
•Source code. All the C++ classes, functions, and programs that appear in the book are available to readers.
•Errata.We have tried not to make mistakes, but sometimes they are inevitable. A list of detected errors is available and updated as necessary. You are invited to contribute any errors you find.
In addition, the following supplements are available to qualified instructors at www.pearsonhighered.com/irc. Please contact your Addison-Wesley sales representative, or send email to computing@aw.com, for information on how to access them:
•PowerPoint lecture slides
•Exam questions
•Solutions to selected programming projects
•Sample assignments and lab exercises
•Suggested syllabi
Preface xi
Chapter Dependencies
At the start of the course, students should be comfortable writing functions and using arrays in C++ or C. Those who have used only C should read Appendix F and pay particular attention to the discussion of reference parameters in Section 2.4.
Chapter 1 Introduction
Chapters 2, 3, and 4.1–4.4 Classes Container Classes Pointers and Dynamic Memory
Chapter 2 may be skipped by students with a good background in C++ classes.
Chapter 5 Linked Lists
Sections 4.5–4.6 Projects: String Class Polynomial
Sections 6.3–6.6 More Templates and Iterators
Sections 14.1–14.2 Derived Classes
Section 14.3 Virtual Methods
The shaded boxes provide good opportunities for advanced work.
Sections 6.1–6.2 Templates
Chapter 7 Stacks
Chapter 8 Queues
Section 11.1-2 Heaps
Chapter 9 Recursion
Chapter 10 Trees
Section 11.3 B-Trees
Section 11.4 Detailed Tree Analysis
Section 12.1 Binary Search
Sec. 12.2–12.3 HashTables (Also requires 6.1–6.2)
Chapter 13 Sorting (Heapsort also needs Sec. 11.1)
Chapter 15 Graphs
Acknowledgments
We started this book while Walter was visiting Michael at the Computer Science Department of the University of Colorado in Boulder. The work was completed afterWalter moved back to the Department of Engineering and Computer Science at the University of California, San Diego. We are grateful to these institutions for providing facilities, wonderful students, and interaction with congenial colleagues.
Our students have been particularly helpful—nearly 5000 of our students worked through the material, making suggestions, showing us how they learned. We thank the reviewers and instructors who used the material in their data structures courses and provided feedback: Zachary Bergen, Cathy Bishop, Martin Burtscher, Gina Cherry, Courtney Comstock, Stephen Davies, Robert Frohardt, John Gillett, Mike Hendricks, Ralph Hollingsworth, Yingdan Huang, Patrick Lynn, Ron McCarty, Shivakant Mishra, Evi Nemeth, Rick Osborne, Rachelle Reese, and Nicholas Tran. The book was also extensively reviewed by Wolfgang W. Bein, Bill Hankley, Michael Milligan, Paul Nagin, Jeff Parker, Andrew L. Wright, John R. Rose, and Evan Zweifel. We thank these colleagues for their excellent critique and their encouragement.
Thank you to Lesley McDowell and Chris Schenk, who are pleasant and enthusiastic every day in the computer science department at the University of Colorado. Our thanks also go to the editors and staff at Addison-Wesley. Heather McNally’s work has encouraged us and provided us with smooth interaction on a daily basis and eased every step of the production. Karin Dejamaer and Jessica Hector provided friendly encouragement in Boulder, and we offer our thanks to them. We welcome and appreciate Michael Hirsch in the role of editor, where he has shown amazing energy, enthusiasm, and encouragement. Finally, our original editor, Susan Hartman, has provided continual support, encouragement, and direction—the book wouldn’t be here without you!
In addition to the work and support from those who put the book together, we thank those who offered us daily interest and encouragement. Our deepest thanks go to Holly Arnold, Vanessa Crittenden, Meredith Boyles, Suzanne Church, Erika Civils, Lynne Conklin, Andrzej Ehrenfeucht, PaulEisenbrey, Skip Ellis, John Kennedy, Rick Lowell, George Main, Mickey Main, Jesse Nuzzi, Ben Powell, Marga Powell, Megan Powell, Grzegorz Rozenberg, Hannah, Timothy, and Janet.
MichaelMain
Walter Savitch main@colorado.edu wsavitch@ucsd.edu Boulder,Colorado SanDiego,California
CHAPTER 1 THE PHASES OF SOFTWARE DEVELOPMENT
1.1Specification, Design, Implementation3
Design Concept: Decomposing the Problem4 Preconditions and Postconditions6
Using Functions Provided by Other Programmers8
Implementation Issues for the ANSI/ISO C++ Standard8
C++ Feature: The Standard Library and the Standard Namespace9
Programming Tip: Use Declared Constants11
Clarifying the Const Keyword Part 1: Declared Constants12
Programming Tip: Use Assert to Check a Precondition12
Programming Tip: Use EXIT_SUCCESS in a Main Program14
C++ Feature: Exception Handling14
Self-Test Exercises for Section 1.114
1.2Running Time Analysis15
The Stair-Counting Problem15 Big-O Notation21
Time Analysis of C++ Functions23
Worst-Case, Average-Case, and Best-Case Analyses25 Self-Test Exercises for Section 1.225
1.3Testing and Debugging26
ChoosingTest Data26
Boundary Values27
Fully Exercising Code28
Debugging28
Programming Tip: How to Debug28
Self-Test Exercises for Section 1.329
Chapter Summary30
Solutions to Self-Test Exercises31
CHAPTER 2 ABSTRACT DATA TYPES AND C++ CLASSES
2.1Classes and Members34
Programming Example: The Throttle Class34
Clarifying the Const Keyword Part 2: Constant Member Functions38 Using a Class39
A Small Demonstration Program for the Throttle Class40
Implementing Member Functions42
Member Functions May Activate Other Members44
Programming Tip: Style for Boolean Variables44 Self-Test Exercises for Section 2.145
2.2Constructors45
The Throttle’s Constructor46
What Happens If You Write a Class with No Constructors?49
Programming Tip: Always Provide Constructors49 Revising the Throttle’s Member Functions49 Inline Member Functions49
Programming Tip: When to Use an Inline Member Function50 Self-Test Exercises for Section 2.251
2.3Using a Namespace, Header File, and Implementation File51 Creating a Namespace51
The Header File52
Describing the Value Semantics of a Class Within the Header File56
Programming Tip: Document the Value Semantics57
The Implementation File57
Using the Items in a Namespace59
Pitfall: Never Put a Using Statement Actually in a Header File60
Self-Test Exercises for Section 2.362
2.4Classes and Parameters63
Programming Example: The Point Class63 Default Arguments65
Programming Tip: A Default Constructor Can Be Provided by Using Default Arguments66 Parameters67
Pitfall: Using a Wrong Argument Type for a Reference Parameter70 Clarifying the Const Keyword Part 3: Const Reference Parameters72
Programming Tip: Use const Consistently73
When the Type of a Function’s Return Value Is a Class73
Self-Test Exercises for Section 2.474
2.5Operator Overloading74
Overloading Binary Comparison Operators75
Overloading Binary Arithmetic Operators76
Overloading Output and Input Operators77 Friend Functions80
Programming Tip: When to Use a Friend Function81 The Point Class—Putting Things Together82 Summary of Operator Overloading85
Self-Test Exercises for Section 2.585
2.6The Standard Template Libary and the Pair Class86 Chapter Summary87 Solutions to Self-Test Exercises88 Programming Projects90
CHAPTER 3 CONTAINER CLASSES
3.1The Bag Class97
The Bag Class—Specification98
C++ Feature: Typedef Statements Within a Class Definition99
C++ Feature: The std::size_t Data Type100
Clarifying the Const Keyword
Part 4: Static Member Constants104
Older Compilers Do Not Support Initialization of Static Member Constants105
The Bag Class—Documentation105
Documenting the Value Semantics107
The Bag Class—Demonstration Program107
The Bag Class—Design109
Pitfall: The value_type Must Have a Default Constructor110
The Invariant of a Class110
The Bag Class—Implementation111
Pitfall: Needing to Use the Full Type Name bag::size_type112
Programming Tip: Make Assertions Meaningful112
C++ Feature: The Copy Function from the C++ Standard Library116
The Bag Class—Putting the Pieces Together117
Programming Tip: Document the Class Invariant in the Implementation File117
The Bag Class—Testing121
Pitfall: An Object Can Be an Argument to Its Own Member Function121
The Bag Class—Analysis122
Self-Test Exercises for Section 3.1123
3.2Programming Project: The Sequence Class124
The Sequence Class—Specification124
The Sequence Class—Documentation127
The Sequence Class—Design127
The Sequence Class—Pseudocode for the Implementation130 Self-Test Exercises for Section 3.2132
3.3InteractiveTest Programs133
C++ Feature: Converting Input to Uppercase Letters134
C++ Feature: The Switch Statement138 Self-Test Exercises for Section 3.3138
3.4The STL Multiset Class and Its Iterator139
The Multiset Template Class 139
Some Multiset Members140 Iterators and the[...) Pattern140
Pitfall: Do Not Access an Iterator’s Item After Reaching end( )142 Testing Iterators for Equality143
Other Multiset Operations143 Invalid Iterators144
Clarifying the Const Keyword Part 5: Const Iterators144
Pitfall: Changing a Container Object Can Invalidate Its Iterators144
Self-Test Exercises for Section 3.4145
Chapter Summary146
Solutions to Self-Test Exercises146
Programming Projects149
CHAPTER 4 POINTERS AND DYNAMIC ARRAYS
4.1Pointers and Dynamic Memory155
PointerVariables156
Using the Assignment Operator with Pointers158
DynamicVariables and the new Operator159
Using new to Allocate Dynamic Arrays160
The Heap and the bad_alloc Exception163
The delete Operator163
Programming Tip: Define Pointer Types164
Self-Test Exercises for Section 4.1165
4.2 Pointers and Arrays as Parameters166
Clarifying the Const Keyword Part 6: Const Parameters That Are Pointers or Arrays171
Self-Test Exercises for Section 4.2173
4.3 The Bag Class with a Dynamic Array176
Pointer Member Variables176
Member Functions Allocate Dynamic Memory as Needed177
Programming Tip: Provide Documentation about Possible Dynamic Memory Failure181
Value Semantics181
The Destructor184
The Revised Bag Class—Class Definition185
The Revised Bag Class—Implementation187
Programming Tip: How to Check for Self-Assignment188
Programming Tip: How to Allocate Memory in a Member Function191
The Revised Bag Class—Putting the Pieces Together192
Self-Test Exercises for Section 4.3194
4.4Prescription for a Dynamic Class195
Four Rules195
Special Importance of the Copy Constructor195
Pitfall: Using Dynamic Memory Requires a Destructor, a Copy Constructor, and an Overloaded Assignment Operator196
Self-Test Exercises for Section 4.4197
4.5The STL String Class and a Project197
Null-Terminated Strings197
Initializing a String Variable198
The Empty String198
Reading and Writing String Variables199
Pitfall: Using = and == with Strings199
The strcpy Function199
The strcat Function200
Pitfall: Dangers of strcpy, strcat, and Reading Strings200
The strlen Function201
The strcmp Function201
The String Class—Specification201
Constructor for the String Class203
Overloading the Operator [ ]204
Some Further Overloading204
Other Operations for the String Class205
The String Class—Design205
The String Class—Implementation206
Demonstration Program for the String Class208
Chaining the Output Operator210
Declaring Constant Objects210
Constructor-Generated Conversions210
Using Overloaded Operations in Expressions211
Our String Class Versus the C++ Library String Class211
Self-Test Exercises for Section 4.5211
4.6Programming Project: The Polynomial212
Chapter Summary216
Solutions to Self-Test Exercises216
Programming Projects218
CHAPTER 5 LINKED LISTS
5.1A Fundamental Node Class for Linked Lists221
Declaring a Class for Nodes221
Using a Typedef Statement with Linked-List Nodes222
Head Pointers, Tail Pointers223
The Null Pointer224
The Meaning of a Null Head Pointer or Tail Pointer224
The Node Constructor224
The Node Member Functions225
The Member Selection Operator226
Clarifying the Const Keyword
Part 7: The Const Keyword with a Pointer to a Node, and theNeed for Two Versions of Some Member Functions227
Programming Tip: A Rule for a Node’s Constant Member Functions228
Pitfall: Dereferencing the Null Pointer230
Self-Test Exercises for Section 5.1230
5.2A Linked-List Toolkit231
Linked-ListToolkit—Header File232
Computing the Length of a Linked List232
Programming Tip: How to Traverse a Linked List235
Pitfall: Forgetting to Test the Empty List236 Parameters for Linked Lists236
Inserting a New Node at the Head of a Linked List238
Inserting a New Node That Is Not at the Head240
Pitfall: Unintended Calls to delete and new243
Searching for an Item in a Linked List245
Finding a Node by Its Position in a Linked List246
Copying a Linked List247
Removing a Node at the Head of a Linked List250
Removing a Node That Is Not at the Head251
Clearing a Linked List252
Linked-ListToolkit—Putting the Pieces Together253 Using the Linked-List Toolkit254
Self-Test Exercises for Section 5.2258
5.3The Bag Class with a Linked List259
Our Third Bag—Specification259
Our Third Bag—Class Definition259
How to Make the Bag value_type Match the Node value_type260
Following the Rules for Dynamic Memory Usage in a Class263
The Third Bag Class—Implementation264
Pitfall: The Assignment Operator Causes Trouble with Linked Lists265
Programming Tip: How to Choose Between Approaches267
The Third Bag Class—Putting the Pieces Together271
Self-Test Exercises for Section 5.3272
5.4Programming Project: TheSequenceClasswithaLinkedList275
The Revised Sequence Class—Design Suggestions275
The Revised Sequence Class—Value Semantics276
Self-Test Exercises for Section 5.4277
5.5 Dynamic Arrays vs. Linked Lists vs. DoublyLinkedLists277 Making the Decision279
Self-Test Exercises for Section 5.5279
5.6 STL Vectors vs. STL Lists vs. STL Deques280 Self-Test Exercises for Section 5.6282
Chapter Summary283
Solutions to Self-Test Exercises283
Programming Projects287
CHAPTER 6 SOFTWARE DEVELOPMENT WITH TEMPLATES, ITERATORS, AND THE STL
6.1Template Functions291
Syntax for a Template Function293
Programming Tip: Capitalize the Name of a Template Parameter293 Using a Template Function294 Pitfall: Failed Unification Errors294
A Template Function to Swap Two Values296
Programming Tip: Swap, Max, and Min Functions296 Parameter Matching for Template Functions296
A Template Function to Find the Biggest Item in an Array297 Pitfall: Mismatches for Template Function Arguments299 A Template Function to Insert an Item into a Sorted Array299 Self-Test Exercises for Section 6.1301
6.2Template Classes301
Syntax for a Template Class301
Programming Tip: Use the Name Item and the typename Keyword303 Pitfall: Do Not Place Using Directives in a Template Implementation304 More About the Template Implementation File304
Parameter Matching for Member Functions of Template Classes309 Using the Template Class309 Details of the Story-Writing Program312 Self-Test Exercises for Section 6.2312
6.3The STL’s Algorithms and Use of Iterators313 STL Algorithms313
Standard Categories of Iterators314 Iterators for Arrays316 Self-Test Exercises for Section 6.3317
6.4The Node Template Class317 Functions That Return a Reference Type318 What Happens When a Reference Return Value Is Copied Elsewhere320 The Data Member Function Now Requires Two Versions320 Header and Implementation Files for the New Node321 Self-Test Exercises for Section 6.4321
6.5An Iterator for Linked Lists328
The Node Iterator328
The Node Iterator Is Derived from std::iterator330 Pitfall: std::iterator Might Not Exist331
The Node Iterator’s Private Member Variable331 Node Iterator—Constructor331 Node Iterator—the * Operator331 Node Iterator—Two Versions of the ++ Operator332 Programming Tip: ++p Is More Efficient Than p++334 Iterators for Constant Collections334
Programming Tip: When to Use a Const Iterator336 Self-Test Exercises for Section 6.5336
Contents
6.6Linked-List Version of the Bag Template Class with an Iterator337 How to Provide an Iterator for a Container Class That You Write337
The Bag Iterator338 Why the Iterator Is Defined Inside the Bag339 Self-Test Exercises for Section 6.6339
Chapter Summary and Summary of the Five Bags347 Solutions to Self-Test Exercises348
Programming Projects350
CHAPTER 7 STACKS
7.1 The STL Stack Class353
The Standard Library Stack Class354
Programming Example: Reversing a Word355 Self-Test Exercises for Section 7.1356
7.2Stack Applications357
Programming Example: Balanced Parentheses357 Programming Example: Evaluating Arithmetic Expressions359 Evaluating Arithmetic Expressions—Specification359 Evaluating Arithmetic Expressions—Design360 Evaluating Arithmetic Expressions—Implementation366 Functions Used in the Calculator Program367 Evaluating Arithmetic Expressions—Testing and Analysis367 Evaluating Arithmetic Expressions—Enhancements368 Self-Test Exercises for Section 7.2368
7.3Implementations of the Stack Class369
Array Implementation of a Stack369 Linked-List Implementation of a Stack373 The Koenig Lookup374 Self-Test Exercises for Section 7.3374
7.4More Complex Stack Applications377 Evaluating Postfix Expressions377 Translating Infix to Postfix Notation379 Using Precedence Rules in the Infix Expression381 Correctness of the Conversion from Infix to Postfix383 Self-Test Exercises for Section 7.4387
Chapter Summary387
Solutions to Self-Test Exercises387
Programming Projects389
CHAPTER 8 QUEUES
8.1 The STL Queue394
The Standard Library Queue Class395 Uses for Queues395 Self-Test Exercises for Section 8.1397
8.2Queue Applications398
Programming Example: Recognizing Palindromes398 Self-Test Exercises for Middle of Section 8.2400
Programming Example: Car Wash Simulation401
Car Wash Simulation—Specification401 Car Wash Simulation—Design402
Car Wash Simulation—Implementing the Car Wash Classes405
Car Wash Simulation—Implementing the Simulation Function410 Self-Test Exercises for End of Section 8.2411
8.3Implementations of the Queue Class413 Array Implementation of a Queue413
Programming Tip: Use Small Helper Functions to Improve Clarity416 Discussion of the Circular Array Implementation of a Queue418 Linked-List Implementation of a Queue420
Implementation Details421
Programming Tip: Make Note of “Don’t Care” Situations423 Pitfall: Which End Is Which423 Self-Test Exercises for Section 8.3426
8.4Implementing the STL Deque Class426 Calling the Destructor and Constructor for the Deque’s value_type Items429
OtherVariations on Stacks and Queues430 Self-Test Exercises for Section 8.4430
8.5Reference Return Values for the Stack, Queue, and Other Classes430
Chapter Summary430 Solutions to Self-Test Exercises432
Programming Projects433
CHAPTER 9 RECURSIVE THINKING
9.1Recursive Functions437
A First Example of Recursive Thinking437 Tracing Recursive Calls439
Programming Example: An Extension of write_vertical441 A Closer Look at Recursion442
General Form of a Successful Recursive Function445 Self-Test Exercises for Section 9.1446
9.2Studies of Recursion: Fractals and Mazes447
Programming Example: Generating Random Fractals447 A Function for Generating Random Fractals—Specification448 Design and Implementation of the Fractal Function450 How the Random Fractals Are Displayed451
Programming Example: Traversing a Maze453
Traversing a Maze—Specification453 Traversing a Maze—Design455
Traversing a Maze—Implementation456
The Recursive Pattern of Exhaustive Search with Backtracking458
Programming Example: TheTeddy Bear Game459
Pitfall: Forgetting to Use the Return Value from a Recursive Call459 Self-Test Exercises for Section 9.2460
Contents
9.3Reasoning About Recursion461
How to Ensure That There Is No Infinite Recursion463
Inductive Reasoning About the Correctness of a Recursive Function466
Self-Test Exercises for Section 9.3467
Chapter Summary468
Solutions to Self-Test Exercises468
Programming Projects470
CHAPTER 10 TREES
10.1Introduction to Trees475
Binary Trees475
Binary Taxonomy Trees478
General Trees479
Self-Test Exercises for Section 10.1480
10.2Tree Representations480
Array Representation of Complete Binary Trees480 Representing a Binary Tree with a Class for Nodes483
Self-Test Exercises for Section 10.2485
10.3Binary Tree Nodes485
Pitfall: Not Connecting All the Links488
Programming Example: Animal Guessing489
Animal Guessing Program—Design and Implementation491
Animal Guessing Program—Improvements496
Self-Test Exercises for Section 10.3500
10.4Tree Traversals500
Traversals of Binary Trees500
Printing the Data from a Tree’s Node505
The Problem with Our Traversals506
A Parameter Can Be a Function507
A Template Version of the Apply Function509
More Generality for the Apply Template Function510
Template Functions for Tree Traversals511 Self-Test Exercises for Section 10.4512
10.5Binary Search Trees518
The Binary Search Tree Storage Rules518
Our Sixth Bag—Class Definition522
Our Sixth Bag—Implementation of Some Simple Functions522 Counting the Occurrences of an Item in a Binary Search Tree523
Inserting a New Item into a Binary Search Tree524
Removing an Item from a Binary Search Tree525
The Union Operators for Binary Search Trees529
Time Analysis and an Iterator531
Self-Test Exercises for Section 10.5531
Chapter Summary531
Solutions to Self-Test Exercises532
Programming Projects534
CHAPTER 11 BALANCED TREES
11.1Heaps540
The Heap Storage Rules540
The Priority Queue ADT with Heaps541 Adding an Entry to a Heap542
Removing an Entry from a Heap543
11.2 The STL Priority Queue and Heap Algorithms546
11.3 B-Trees547
Self-Test Exercises for Sections 11.1 and 11.2547
The Problem of Unbalanced Trees547
The B-Tree Rules548
An Example B-Tree549
The Set ADT with B-Trees550
Searching for an Item in a B-Tree555
Inserting an Item into a B-Tree557
The Loose Insertion into a B-Tree557
A Private Member Function to Fix an Excess in a Child560
Back to the Insert Member Function561 Employing Top-Down Design563
Removing an Item from a B-Tree563
The Loose Erase from a B-Tree564
A Private Member Function to Fix a Shortage in a Child566
Removing the Biggest Item from a B-Tree569
Programming Tip: Write and Test Small Pieces569
Programming Tip: Consider Using the STL Vector570
External B-Trees570
Self-Test Exercises for Section 11.2571
11.4 Trees, Logs, and Time Analysis572
Time Analysis for Binary Search Trees573
Time Analysis for Heaps573
Logarithms575
Logarithmic Algorithms576
Self-Test Exercises for Section 11.3577
11.5 The STL Map and Multimap Classes577
Chapter Summary579
Map and Multimap Implementations578
Solutions to Self-Test Exercises579
Programming Projects582
CHAPTER 12 SEARCHING
12.1Serial Search and Binary Search584
Serial Search584
Serial Search—Analysis584
Binary Search586
Binary Search—Design587
Pitfall: Common Indexing Errors in Binary Search Implementations589
Binary Search—Analysis590
Standard Library Search Functions594 Functions for Sorted Ranges594 Functions for Unsorted Ranges596
The STL search Function596 Self-Test Exercises for Section 12.1598
12.2Open-Address Hashing598
Introduction to Hashing598
TheTable Class—Specification601
TheTable Class—Design603 Programming Tip: Using size_t Can Indicate a Value’s Purpose606 TheTable ADT—Implementation606
C++ Feature: Inline Functions in the Implementation File612 Choosing a Hash Function to Reduce Collisions612 Double Hashing to Reduce Clustering613 Self-Test Exercises for Section 12.2614
12.3Chained Hashing615 Self-Test Exercises for Section 12.3617
12.4Time Analysis of Hashing617
The Load Factor of a Hash Table617 Self-Test Exercises for Section 12.4620
12.5Programming Project: A Table Class with STL Vectors620 A New Table Class620 Using Vectors in the New Table621 Template Parameters That Are Constants621 Template Parameters That Are Functions621 Implementing the New Table Class622 Self-Test Exercises for Section 12.5623
12.6HashTables in the TR1 Library Extensions624 Chapter Summary624 Solutions to Self-Test Exercises625 Programming Projects628
CHAPTER 13 SORTING
13.1Quadratic Sorting Algorithms630
Selectionsort—Specification630
Selectionsort—Design630
Selectionsort—Implementation632
Selectionsort—Analysis634
Programming Tip: Rough Estimates Suffice for Big-O 636 Insertionsort636
Insertionsort—Analysis640
Self-Test Exercises for Section 13.1642
13.2Recursive Sorting Algorithms642
Divide-and-Conquer Using Recursion642 C++ Feature: Specifying a Subarray with Pointer Arithmetic643 Mergesort645
The merge Function646 Dynamic Memory Usage in Mergesort651 Mergesort—Analysis651 Mergesort for Files653 Quicksort653
The partition Function655 Quicksort—Analysis659 Quicksort—Choosing a Good Pivot Element661 Self-Test Exercises for Section 13.2661
13.3 An O(n log n) Algorithm Using a Heap662 Heapsort662 Making the Heap667 Reheapification Downward670 Heapsort—Analysis671
Self-Test Exercises for Section 13.3672
13.4Sorting and Binary Search in the STL672
The Original C qsort Function672
The STL sort Function673 Heapsort in the STL674
Binary Search Functions in the STL674
The Comparison Parameter for STL Sorting Functions675 WritingYour Own sort Function That Uses Iterators676 Chapter Summary677 Solutions to Self-Test Exercises678 Programming Projects679
CHAPTER 14 DERIVED CLASSES AND INHERITANCE
14.1Derived Classes684
How to Declare a Derived Class686
The Automatic Constructors of a Derived Class687 Using a Derived Class688
The Automatic Assignment Operator for a Derived Class690
The Automatic Destructor of a Derived Class690 Overriding Inherited Member Functions691
Programming Tip: Make the Overriding Function Call the Original692
Self-Test Exercises for Section 14.1692