Data Structures and Algorithms in C++

738

description

Textbook in Data Struct and Algorithms using C++

Transcript of Data Structures and Algorithms in C++

This page intentionally left blank iimain 2011/1/13 9:10 page i #1iiiiiiData Structures andAlgorithms in C++Second EditionThis page intentionally left blank iimain 2011/1/13 9:10 page iii #3iiiiiiData Structures andAlgorithms in C++Second EditionMichael T. GoodrichDepartment of Computer ScienceUniversity of California, IrvineRoberto TamassiaDepartment of Computer ScienceBrown UniversityDavid M. MountDepartment of Computer ScienceUniversity of MarylandJohn Wiley & Sons, Inc.iimain 2011/1/13 9:10 page iv #4iiiiiiACQUISITIONS EDITOR Beth Lang GolubMARKETING MANAGER Chris RuelEDITORIAL ASSISTANT Elizabeth MillsMEDIA EDITOR Thomas KulesaSENIOR DESIGNER Jim OSheaCONTENT MANAGER Micheline FrederickPRODUCTION EDITOR Amy WeintraubPHOTO EDITOR Sheena GoldsteinThis book was set in LATEX by the authors and printed and bound by Malloy Lithographers.The cover was printed by Malloy Lithographers. The cover image is fromWuta Wuta Tjan-gala, Emu dreaming c estate of the artist 2009 licensed by Aboriginal Artists Agency.Jennifer Steele/Art Resource, NY.This book is printed on acid free paper. Trademark Acknowledgments: Java is a trademark of Sun Microsystems, Inc. UNIX R isa registered trademark in the United States and other countries, licensed through X/OpenCompany, Ltd. PowerPoint R is a trademark of Microsoft Corporation. All other productnames mentioned herein are the trademarks of their respective owners.Copyright c 2011, John Wiley & Sons, Inc. All rights reserved.No part of this publication may be reproduced, stored in a retrieval system or transmittedin any form or by any means, electronic, mechanical, photocopying, recording, scanningor otherwise, except as permitted under Sections 107 or 108 of the 1976 United StatesCopyright Act, without either the prior written permission of the Publisher, or authorizationthrough payment of the appropriate per-copy fee to the Copyright Clearance Center, Inc.222 Rosewood Drive, Danvers, MA 01923, (978)750-8400, fax (978)646-8600.Requests to the Publisher for permission should be addressed to the Permissions Depart-ment, John Wiley & Sons, Inc., 111 River Street, Hoboken, NJ 07030, (201)748-6011, fax(201)748-6008, E-Mail: [email protected] order books or for customer service please call 1-800-CALL WILEY (225-5945).Founded in 1807, John Wiley & Sons, Inc. has been a valued source of knowledge andunderstanding for more than 200 years, helping people around the world meet their needsand fulll their aspirations. Our company is built on a foundation of principles that includeresponsibility to the communities we serve and where we live and work. In 2008, welaunched a Corporate Citizenship Initiative, a global effort to address the environmental,social, economic, and ethical challenges we face in our business. Among the issues weare addressing are carbon impact, paper specications and procurement, ethical conductwithin our business and among our vendors, and community and charitable support. Formore information, please visit our website: www.wiley.com/go/citizenship.Library of Congress Cataloging in Publication DataISBN-13 978-0-470-38327-8Printed in the United States of America10 9 8 7 6 5 4 3 2 1iimain 2011/1/13 9:10 page v #5iiiiiiTo Karen, Paul, Anna, and Jack Michael T. GoodrichTo Isabel Roberto TamassiaTo Jeanine David M. MountThis page intentionally left blank iimain 2011/1/13 9:10 page vii #7iiiiiiPrefaceThis second edition of Data Structures and Algorithms in C++ is designed to pro-vide an introduction to data structures and algorithms, including their design, analy-sis, and implementation. In terms of curricula based on the IEEE/ACM 2001 Com-puting Curriculum, this book is appropriate for use in the courses CS102 (I/O/Bversions), CS103 (I/O/B versions), CS111 (A version), and CS112 (A/I/O/F/H ver-sions). We discuss its use for such courses in more detail later in this preface.The major changes in the second edition are the following: We added more examples of data structure and algorithm analysis. We enhanced consistency with the C++ Standard Template Library (STL). We incorporated STL data structures into many of our data structures. We added a chapter on arrays, linked lists, and iterators (Chapter 3). We added a chapter on memory management and B-trees (Chapter 14). We enhanced the discussion of algorithmic design techniques, like dynamicprogramming and the greedy method. We simplied and reorganized the presentation of code fragments. We have introduced STL-style iterators into our container classes, and havepresented C++ implementations for these iterators, even for complex struc-tures such as hash tables and binary search trees. We have modied our priority-queue interface to use STL-style comparatorobjects. We expanded and revised exercises, continuing our approach of dividingthem into reinforcement, creativity, and project exercises.This book is related to the following books: M.T. Goodrich and R. Tamassia, Data Structures and Algorithms in Java,John Wiley & Sons, Inc. This book has a similar overall structure to thepresent book, but uses Java as the underlying language (with some modest,but necessary pedagogical differences required by this approach). M.T. Goodrich and R. Tamassia, Algorithm Design: Foundations, Analysis,and Internet Examples, John Wiley & Sons, Inc. This is a textbook for a moreadvanced algorithms and data structures course, such as CS210 (T/W/C/Sversions) in the IEEE/ACM 2001 curriculum.While this book retains the same pedagogical approach and general structureas Data Structures and Algorithms in Java, the code fragments have been com-pletely redesigned. We have been careful to make full use of C++s capabilities anddesign code in a manner that is consistent with modern C++ usage. In particular,whenever appropriate, we make extensive use of C++ elements that are not part ofJava, including the C++ Standard Template Library (STL), C++ memory allocationviiiimain 2011/1/13 9:10 page viii #8iiiiiiviii Prefaceand deallocation (and the associated issues of destructors), virtual functions, streaminput and output, operator overloading, and C++s safe run-time casting.Use as a TextbookThe design and analysis of efcient data structures has long been recognized as avital subject in computing, because the study of data structures is part of the coreof every collegiate computer science and computer engineering major program weare familiar with. Typically, the introductory courses are presented as a two- orthree-course sequence. Elementary data structures are often briey introduced inthe rst programming course or in an introduction to computer science course andthis is followed by a more in-depth introduction to data structures in the courses thatfollow after this. Furthermore, this course sequence is typically followed at a laterpoint in the curriculum by a more in-depth study of data structures and algorithms.We feel that the central role of data structure design and analysis in the curriculumis fully justied, given the importance of efcient data structures in most softwaresystems, including the Web, operating systems, databases, compilers, and scienticsimulation systems.With the emergence of the object-oriented paradigm as the framework of choicefor building robust and reusable software, we have tried to take a consistent object-oriented viewpoint throughout this text. One of the main ideas behind the object-oriented approach is that data should be presented as being encapsulated with themethods that access and modify them. That is, rather than simply viewing dataas a collection of bytes and addresses, we think of data objects as instances of anabstract data type (ADT), which includes a repertoire of methods for performingoperations on data objects of this type. Likewise, object-oriented solutions are oftenorganized utilizing common design patterns, which facilitate software reuse androbustness. Thus, we present each data structure using ADTs and their respectiveimplementations and we introduce important design patterns as a way to organizethose implementations into classes, methods, and objects.For most of the ADTs presented in this book, we provide a description of thepublic interface in C++. Also, concrete data structures realizing the ADTs arediscussed and we often give concrete C++ classes implementing these interfaces.We also give C++ implementations of fundamental algorithms, such as sorting andgraph searching. Moreover, in addition to providing techniques for using data struc-tures to implement ADTs, we also give sample applications of data structures, suchas HTML tag matching and a simple system to maintain a play list for a digitalaudio system. Due to space limitations, however, we only show code fragments ofsome of the implementations in this book and make additional source code avail-able on the companion web site.iimain 2011/1/13 9:10 page ix #9iiiiiiPreface ixOnline ResourcesThis book is accompanied by an extensive set of online resources, which can befound at the following web site:www.wiley.com/college/goodrichIncluded on this Web site is a collection of educational aids that augment thetopics of this book, for both students and instructors. Students are encouraged touse this site along with the book, to help with exercises and increase understand-ing of the subject. Instructors are likewise welcome to use the site to help plan,organize, and present their course materials. Because of their added value, some ofthese online resources are password protected.For the StudentFor all readers, and especially for students, we include the following resources: All the C++ source code presented in this book. PDF handouts of Powerpoint slides (four-per-page) provided to instructors. A database of hints to all exercises, indexed by problem number. An online study guide, which includes solutions to selected exercises.The hints should be of considerable use to anyone needing a little help gettingstarted on certain exercises, and the solutions should help anyone wishing to seecompleted exercises. Students who have purchased a new copy of this book willget password access to the hints and other password-protected online resources atno extra charge. Other readers can purchase password access for a nominal fee.For the InstructorFor instructors using this book, we include the following additional teaching aids: Solutions to over 200 of the books exercises. A database of additional exercises, suitable for quizes and exams. Additional C++ source code. Slides in Powerpoint and PDF (one-per-page) format. Self-contained, special-topic supplements, including discussions on convexhulls, range trees, and orthogonal segment intersection.The slides are fully editable, so as to allow an instructor using this book full free-dom in customizing his or her presentations. All the online resources are providedat no extra charge to any instructor adopting this book for his or her course.iimain 2011/1/13 9:10 page x #10iiiiiix PrefaceA Resource for Teaching Data Structures and AlgorithmsThis book contains many C++-code and pseudo-code fragments, and hundreds ofexercises, which are divided into roughly 40% reinforcement exercises, 40% cre-ativity exercises, and 20% programming projects.This book can be used for the CS2 course, as described in the 1978 ACM Com-puter Science Curriculum, or in courses CS102 (I/O/B versions), CS103 (I/O/B ver-sions), CS111 (A version), and/or CS112 (A/I/O/F/H versions), as described in theIEEE/ACM 2001 Computing Curriculum, with instructional units as outlined inTable 0.1.Instructional Unit Relevant MaterialPL1. Overview of Programming Languages Chapters 1 and 2PL2. Virtual Machines Sections 14.1.1 and 14.1.2PL3. Introduction to Language Translation Section 1.7PL4. Declarations and Types Sections 1.1.2, 1.1.3, and 2.2.5PL5. Abstraction Mechanisms Sections 2.2.5, 5.15.3, 6.1.1, 6.2.1, 6.3,7.1, 7.3.1, 8.1, 9.1, 9.5, 11.4, and 13.1.1PL6. Object-Oriented Programming Chapters 1 and 2 and Sections 6.2.1,7.3.7, 8.1.2, and 13.3.1PF1. Fundamental Programming Constructs Chapters 1 and 2PF2. Algorithms and Problem-Solving Sections 1.7 and 4.2PF3. Fundamental Data Structures Sections 3.1, 3.2, 5.15.3, 6.16.3, 7.1,7.3, 8.1, 8.3, 9.19.4, 10.1, and 13.1.1PF4. Recursion Section 3.5SE1. Software Design Chapter 2 and Sections 6.2.1, 7.3.7,8.1.2, and 13.3.1SE2. Using APIs Sections 2.2.5, 5.15.3, 6.1.1, 6.2.1, 6.3,7.1, 7.3.1, 8.1, 9.1, 9.5, 11.4, and 13.1.1AL1. Basic Algorithmic Analysis Chapter 4AL2. Algorithmic Strategies Sections 11.1.1, 11.5.1, 12.2, 12.3.1, and12.4.2AL3. Fundamental Computing Algorithms Sections 8.1.5, 8.2.2, 8.3.5, 9.2, and9.3.1, and Chapters 11, 12, and 13DS1. Functions, Relations, and Sets Sections 4.1, 8.1, and 11.4DS3. Proof Techniques Sections 4.3, 6.1.3, 7.3.3, 8.3, 10.210.5,11.2.1, 11.3.1, 11.4.3, 13.1.1, 13.3.1,13.4, and 13.5DS4. Basics of Counting Sections 2.2.3 and 11.1.5DS5. Graphs and Trees Chapters 7, 8, 10, and 13DS6. Discrete Probability Appendix A and Sections 9.2, 9.4.2,11.2.1, and 11.5Table 0.1: Material for units in the IEEE/ACM 2001 Computing Curriculum.iimain 2011/1/13 9:10 page xi #11iiiiiiPreface xiContents and OrganizationThe chapters for this course are organized to provide a pedagogical path that startswith the basics of C++ programming and object-oriented design. We provide anearly discussion of concrete structures, like arrays and linked lists, in order to pro-vide a concrete footing to build upon when constructing other data structures. Wethen add foundational techniques like recursion and algorithm analysis, and, in themain portion of the book, we present fundamental data structures and algorithms,concluding with a discussion of memory management (that is, the architecturalunderpinnings of data structures). Specically, the chapters for this book are orga-nized as follows:1. A C++ Primer2. Object-Oriented Design3. Arrays, Linked Lists, and Recursion4. Analysis Tools5. Stacks, Queues, and Deques6. List and Iterator ADTs7. Trees8. Heaps and Priority Queues9. Hash Tables, Maps, and Skip Lists10. Search Trees11. Sorting, Sets, and Selection12. Strings and Dynamic Programming13. Graph Algorithms14. Memory Management and B-TreesA. Useful Mathematical FactsA more detailed listing of the contents of this book can be found in the table ofcontents.iimain 2011/1/13 9:10 page xii #12iiiiiixii PrefacePrerequisitesWe have written this book assuming that the reader comes to it with certain knowl-edge. We assume that the reader is at least vaguely familiar with a high-level pro-gramming language, such as C, C++, Python, or Java, and that he or she understandsthe main constructs from such a high-level language, including: Variables and expressions. Functions (also known as methods or procedures). Decision structures (such as if-statements and switch-statements). Iteration structures (for-loops and while-loops).For readers who are familiar with these concepts, but not with how they are ex-pressed in C++, we provide a primer on the C++ language in Chapter 1. Still, thisbook is primarily a data structures book, not a C++ book; hence, it does not providea comprehensive treatment of C++. Nevertheless, we do not assume that the readeris necessarily familiar with object-oriented design or with linked structures, suchas linked lists, since these topics are covered in the core chapters of this book.In terms of mathematical background, we assume the reader is somewhat famil-iar with topics from high-school mathematics. Even so, in Chapter 4, we discussthe seven most-important functions for algorithm analysis. In fact, sections that usesomething other than one of these seven functions are considered optional, and areindicated with a star (). We give a summary of other useful mathematical facts,including elementary probability, in Appendix A.About the AuthorsProfessors Goodrich, Tamassia, and Mount are well-recognized researchers in al-gorithms and data structures, having published many papers in this eld, with ap-plications to Internet computing, information visualization, computer security, andgeometric computing. They have served as principal investigators in several jointprojects sponsored by the National Science Foundation, the Army Research Of-ce, the Ofce of Naval Research, and the Defense Advanced Research ProjectsAgency. They are also active in educational technology research.Michael Goodrich received his Ph.D. in Computer Science from Purdue Uni-versity in 1987. He is currently a Chancellors Professor in the Department of Com-puter Science at University of California, Irvine. Previously, he was a professor atJohns Hopkins University. He is an editor for a number of journals in computerscience theory, computational geometry, and graph algorithms. He is an ACM Dis-tinguished Scientist, a Fellow of the American Association for the Advancement ofScience (AAAS), a Fulbright Scholar, and a Fellow of the IEEE. He is a recipient ofthe IEEE Computer Society Technical Achievement Award, the ACM Recognitionof Service Award, and the Pond Award for Excellence in Undergraduate Teaching.iimain 2011/1/13 9:10 page xiii #13iiiiiiPreface xiiiRoberto Tamassia received his Ph.D. in Electrical and Computer Engineeringfrom the University of Illinois at Urbana-Champaign in 1988. He is the PlastechProfessor of Computer Science and the Chair of the Department of Computer Sci-ence at Brown University. He is also the Director of Browns Center for GeometricComputing. His research interests include information security, cryptography, anal-ysis, design, and implementation of algorithms, graph drawing, and computationalgeometry. He is an IEEE Fellow and a recipient of the Technical AchievementAward from the IEEE Computer Society for pioneering the eld of graph drawing.He is an editor of several journals in geometric and graph algorithms. He previouslyserved on the editorial board of IEEE Transactions on Computers.David Mount received his Ph.D. in Computer Science from Purdue Universityin 1983. He is currently a professor in the Department of Computer Science atthe University of Maryland with a joint appointment in the University of Mary-lands Institute for Advanced Computer Studies. He is an associate editor for ACMTransactions on Mathematical Software and the International Journal of Compu-tational Geometry and Applications. He is the recipient of two ACM Recognitionof Service Awards.In addition to their research accomplishments, the authors also have extensiveexperience in the classroom. For example, Dr. Goodrich has taught data structuresand algorithms courses, including Data Structures as a freshman-sophomore levelcourse and Introduction to Algorithms as an upper-level course. He has earned sev-eral teaching awards in this capacity. His teaching style is to involve the students inlively interactive classroom sessions that bring out the intuition and insights behinddata structuring and algorithmic techniques. Dr. Tamassia has taught Data Struc-tures and Algorithms as an introductory freshman-level course since 1988. Onething that has set his teaching style apart is his effective use of interactive hyper-media presentations integrated with the Web. Dr. Mount has taught both the DataStructures and the Algorithms courses at the University of Maryland since 1985.He has won a number of teaching awards from Purdue University, the University ofMaryland, and the Hong Kong University of Science and Technology. His lecturenotes and homework exercises for the courses that he has taught are widely used assupplementary learning material by students and instructors at other universities.AcknowledgmentsThere are a number of individuals who have made contributions to this book.We are grateful to all our research collaborators and teaching assistants, whoprovided feedback on early drafts of chapters and have helped us in developingexercises, software, and algorithm animation systems. There have been a number offriends and colleagues whose comments have lead to improvements in the text. Weare particularly thankful to Michael Goldwasser for his many valuable suggestions.iimain 2011/1/13 9:10 page xiv #14iiiiiixiv PrefaceWe are also grateful to Karen Goodrich, Art Moorshead, Scott Smith, and IoannisTollis for their insightful comments.We are also truly indebted to the outside reviewers and readers for their co-pious comments, emails, and constructive criticism, which were extremely use-ful in writing this edition. We specically thank the following reviewers for theircomments and suggestions: Divy Agarwal, University of California, Santa Bar-bara; Terry Andres, University of Manitoba; Bobby Blumofe, University of Texas,Austin; Michael Clancy, University of California, Berkeley; Larry Davis, Univer-sity of Maryland; Scott Drysdale, Dartmouth College; Arup Guha, University ofCentral Florida; Chris Ingram, University of Waterloo; Stan Kwasny, WashingtonUniversity; Calvin Lin, University of Texas at Austin; John Mark Mercer, McGillUniversity; Laurent Michel, University of Connecticut; Leonard Myers, CaliforniaPolytechnic State University, San Luis Obispo; David Naumann, Stevens Instituteof Technology; Robert Pastel, Michigan Technological University; Bina Rama-murthy, SUNY Buffalo; Ken Slonneger, University of Iowa; C.V. Ravishankar,University of Michigan; Val Tannen, University of Pennsylvania; Paul Van Ar-ragon, Messiah College; and Christopher Wilson, University of Oregon.We are grateful to our editor, Beth Golub, for her enthusiastic support of thisproject. The team at Wiley has been great. Many thanks go to Mike Berlin, Lil-ian Brady, Regina Brooks, Paul Crockett, Richard DeLorenzo, Jen Devine, SimonDurkin, Micheline Frederick, Lisa Gee, Katherine Hepburn, Rachael Leblond, An-dre Legaspi, Madelyn Lesure, Frank Lyman, Hope Miller, Bridget Morrisey, ChrisRuel, Ken Santor, Lauren Sapira, Dan Sayre, Diana Smith, Bruce Spatz, DawnStanley, Jeri Warner, and Bill Zobrist.The computing systems and excellent technical support staff in the departmentsof computer science at Brown University, University of California, Irvine, and Uni-versity of Maryland gave us reliable working environments. This manuscript wasprepared primarily with the LATEX typesetting package.Finally, we would like to warmly thank Isabel Cruz, Karen Goodrich, JeanineMount, Giuseppe Di Battista, Franco Preparata, Ioannis Tollis, and our parents forproviding advice, encouragement, and support at various stages of the preparationof this book. We also thank them for reminding us that there are things in lifebeyond writing books.Michael T. GoodrichRoberto TamassiaDavid M. Mountiimain 2011/1/13 9:10 page xv #15iiiiiiContents1 A C++ Primer 11.1 Basic C++ Programming Elements . . . . . . . . . . . . . . . 21.1.1 A Simple C++ Program . . . . . . . . . . . . . . . . . . 21.1.2 Fundamental Types . . . . . . . . . . . . . . . . . . . . 41.1.3 Pointers, Arrays, and Structures . . . . . . . . . . . . . 71.1.4 Named Constants, Scope, and Namespaces . . . . . . . 131.2 Expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161.2.1 Changing Types through Casting . . . . . . . . . . . . . 201.3 Control Flow . . . . . . . . . . . . . . . . . . . . . . . . . . . 231.4 Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 261.4.1 Argument Passing . . . . . . . . . . . . . . . . . . . . . 281.4.2 Overloading and Inlining . . . . . . . . . . . . . . . . . 301.5 Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 321.5.1 Class Structure . . . . . . . . . . . . . . . . . . . . . . 331.5.2 Constructors and Destructors . . . . . . . . . . . . . . . 371.5.3 Classes and Memory Allocation . . . . . . . . . . . . . . 401.5.4 Class Friends and Class Members . . . . . . . . . . . . . 431.5.5 The Standard Template Library . . . . . . . . . . . . . . 451.6 C++ Program and File Organization . . . . . . . . . . . . . . 471.6.1 An Example Program . . . . . . . . . . . . . . . . . . . 481.7 Writing a C++ Program . . . . . . . . . . . . . . . . . . . . . 531.7.1 Design . . . . . . . . . . . . . . . . . . . . . . . . . . . 541.7.2 Pseudo-Code . . . . . . . . . . . . . . . . . . . . . . . 541.7.3 Coding . . . . . . . . . . . . . . . . . . . . . . . . . . . 551.7.4 Testing and Debugging . . . . . . . . . . . . . . . . . . 571.8 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 602 Object-Oriented Design 652.1 Goals, Principles, and Patterns . . . . . . . . . . . . . . . . 662.1.1 Object-Oriented Design Goals . . . . . . . . . . . . . . 662.1.2 Object-Oriented Design Principles . . . . . . . . . . . . 672.1.3 Design Patterns . . . . . . . . . . . . . . . . . . . . . . 70xviimain 2011/1/13 9:10 page xvi #16iiiiiixvi Contents2.2 Inheritance and Polymorphism . . . . . . . . . . . . . . . . . 712.2.1 Inheritance in C++ . . . . . . . . . . . . . . . . . . . . . 712.2.2 Polymorphism . . . . . . . . . . . . . . . . . . . . . . . 782.2.3 Examples of Inheritance in C++ . . . . . . . . . . . . . . 792.2.4 Multiple Inheritance and Class Casting . . . . . . . . . . 842.2.5 Interfaces and Abstract Classes . . . . . . . . . . . . . . 872.3 Templates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 902.3.1 Function Templates . . . . . . . . . . . . . . . . . . . . 902.3.2 Class Templates . . . . . . . . . . . . . . . . . . . . . . 912.4 Exceptions . . . . . . . . . . . . . . . . . . . . . . . . . . . . 932.4.1 Exception Objects . . . . . . . . . . . . . . . . . . . . . 932.4.2 Throwing and Catching Exceptions . . . . . . . . . . . . 942.4.3 Exception Specication . . . . . . . . . . . . . . . . . . 962.5 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 983 Arrays, Linked Lists, and Recursion 1033.1 Using Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . 1043.1.1 Storing Game Entries in an Array . . . . . . . . . . . . . 1043.1.2 Sorting an Array . . . . . . . . . . . . . . . . . . . . . . 1093.1.3 Two-Dimensional Arrays and Positional Games . . . . . 1113.2 Singly Linked Lists . . . . . . . . . . . . . . . . . . . . . . . . 1173.2.1 Implementing a Singly Linked List . . . . . . . . . . . . 1173.2.2 Insertion to the Front of a Singly Linked List . . . . . . 1193.2.3 Removal from the Front of a Singly Linked List . . . . . 1193.2.4 Implementing a Generic Singly Linked List . . . . . . . . 1213.3 Doubly Linked Lists . . . . . . . . . . . . . . . . . . . . . . . 1233.3.1 Insertion into a Doubly Linked List . . . . . . . . . . . . 1233.3.2 Removal from a Doubly Linked List . . . . . . . . . . . 1243.3.3 A C++ Implementation . . . . . . . . . . . . . . . . . . 1253.4 Circularly Linked Lists and List Reversal . . . . . . . . . . . 1293.4.1 Circularly Linked Lists . . . . . . . . . . . . . . . . . . . 1293.4.2 Reversing a Linked List . . . . . . . . . . . . . . . . . . 1333.5 Recursion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1343.5.1 Linear Recursion . . . . . . . . . . . . . . . . . . . . . . 1403.5.2 Binary Recursion . . . . . . . . . . . . . . . . . . . . . 1443.5.3 Multiple Recursion . . . . . . . . . . . . . . . . . . . . 1473.6 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1494 Analysis Tools 1534.1 The Seven Functions Used in This Book . . . . . . . . . . . 1544.1.1 The Constant Function . . . . . . . . . . . . . . . . . . 1544.1.2 The Logarithm Function . . . . . . . . . . . . . . . . . 154iimain 2011/1/13 9:10 page xvii #17iiiiiiContents xvii4.1.3 The Linear Function . . . . . . . . . . . . . . . . . . . . 1564.1.4 The N-Log-N Function . . . . . . . . . . . . . . . . . . 1564.1.5 The Quadratic Function . . . . . . . . . . . . . . . . . . 1564.1.6 The Cubic Function and Other Polynomials . . . . . . . 1584.1.7 The Exponential Function . . . . . . . . . . . . . . . . . 1594.1.8 Comparing Growth Rates . . . . . . . . . . . . . . . . . 1614.2 Analysis of Algorithms . . . . . . . . . . . . . . . . . . . . . 1624.2.1 Experimental Studies . . . . . . . . . . . . . . . . . . . 1634.2.2 Primitive Operations . . . . . . . . . . . . . . . . . . . 1644.2.3 Asymptotic Notation . . . . . . . . . . . . . . . . . . . 1664.2.4 Asymptotic Analysis . . . . . . . . . . . . . . . . . . . . 1704.2.5 Using the Big-Oh Notation . . . . . . . . . . . . . . . . 1724.2.6 A Recursive Algorithm for Computing Powers . . . . . . 1764.2.7 Some More Examples of Algorithm Analysis . . . . . . . 1774.3 Simple Justication Techniques . . . . . . . . . . . . . . . . 1814.3.1 By Example . . . . . . . . . . . . . . . . . . . . . . . . 1814.3.2 The Contra Attack . . . . . . . . . . . . . . . . . . . 1814.3.3 Induction and Loop Invariants . . . . . . . . . . . . . . 1824.4 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1855 Stacks, Queues, and Deques 1935.1 Stacks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1945.1.1 The Stack Abstract Data Type . . . . . . . . . . . . . . 1955.1.2 The STL Stack . . . . . . . . . . . . . . . . . . . . . . 1965.1.3 A C++ Stack Interface . . . . . . . . . . . . . . . . . . 1965.1.4 A Simple Array-Based Stack Implementation . . . . . . 1985.1.5 Implementing a Stack with a Generic Linked List . . . . 2025.1.6 Reversing a Vector Using a Stack . . . . . . . . . . . . . 2035.1.7 Matching Parentheses and HTML Tags . . . . . . . . . 2045.2 Queues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2085.2.1 The Queue Abstract Data Type . . . . . . . . . . . . . 2085.2.2 The STL Queue . . . . . . . . . . . . . . . . . . . . . . 2095.2.3 A C++ Queue Interface . . . . . . . . . . . . . . . . . . 2105.2.4 A Simple Array-Based Implementation . . . . . . . . . . 2115.2.5 Implementing a Queue with a Circularly Linked List . . . 2135.3 Double-Ended Queues . . . . . . . . . . . . . . . . . . . . . . 2175.3.1 The Deque Abstract Data Type . . . . . . . . . . . . . 2175.3.2 The STL Deque . . . . . . . . . . . . . . . . . . . . . . 2185.3.3 Implementing a Deque with a Doubly Linked List . . . . 2185.3.4 Adapters and the Adapter Design Pattern . . . . . . . . 2205.4 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223iimain 2011/1/13 9:10 page xviii #18iiiiiixviii Contents6 List and Iterator ADTs 2276.1 Vectors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2286.1.1 The Vector Abstract Data Type . . . . . . . . . . . . . 2286.1.2 A Simple Array-Based Implementation . . . . . . . . . . 2296.1.3 An Extendable Array Implementation . . . . . . . . . . . 2316.1.4 STL Vectors . . . . . . . . . . . . . . . . . . . . . . . . 2366.2 Lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2386.2.1 Node-Based Operations and Iterators . . . . . . . . . . . 2386.2.2 The List Abstract Data Type . . . . . . . . . . . . . . . 2406.2.3 Doubly Linked List Implementation . . . . . . . . . . . . 2426.2.4 STL Lists . . . . . . . . . . . . . . . . . . . . . . . . . 2476.2.5 STL Containers and Iterators . . . . . . . . . . . . . . . 2486.3 Sequences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2556.3.1 The Sequence Abstract Data Type . . . . . . . . . . . . 2556.3.2 Implementing a Sequence with a Doubly Linked List . . 2556.3.3 Implementing a Sequence with an Array . . . . . . . . . 2576.4 Case Study: Bubble-Sort on a Sequence . . . . . . . . . . . 2596.4.1 The Bubble-Sort Algorithm . . . . . . . . . . . . . . . . 2596.4.2 A Sequence-Based Analysis of Bubble-Sort . . . . . . . . 2606.5 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2627 Trees 2677.1 General Trees . . . . . . . . . . . . . . . . . . . . . . . . . . . 2687.1.1 Tree Denitions and Properties . . . . . . . . . . . . . . 2697.1.2 Tree Functions . . . . . . . . . . . . . . . . . . . . . . . 2727.1.3 A C++ Tree Interface . . . . . . . . . . . . . . . . . . . 2737.1.4 A Linked Structure for General Trees . . . . . . . . . . . 2747.2 Tree Traversal Algorithms . . . . . . . . . . . . . . . . . . . 2757.2.1 Depth and Height . . . . . . . . . . . . . . . . . . . . . 2757.2.2 Preorder Traversal . . . . . . . . . . . . . . . . . . . . . 2787.2.3 Postorder Traversal . . . . . . . . . . . . . . . . . . . . 2817.3 Binary Trees . . . . . . . . . . . . . . . . . . . . . . . . . . . 2847.3.1 The Binary Tree ADT . . . . . . . . . . . . . . . . . . . 2857.3.2 A C++ Binary Tree Interface . . . . . . . . . . . . . . . 2867.3.3 Properties of Binary Trees . . . . . . . . . . . . . . . . 2877.3.4 A Linked Structure for Binary Trees . . . . . . . . . . . 2897.3.5 A Vector-Based Structure for Binary Trees . . . . . . . . 2957.3.6 Traversals of a Binary Tree . . . . . . . . . . . . . . . . 2977.3.7 The Template Function Pattern . . . . . . . . . . . . . 3037.3.8 Representing General Trees with Binary Trees . . . . . . 3097.4 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 310iimain 2011/1/13 9:10 page xix #19iiiiiiContents xix8 Heaps and Priority Queues 3218.1 The Priority Queue Abstract Data Type . . . . . . . . . . . 3228.1.1 Keys, Priorities, and Total Order Relations . . . . . . . . 3228.1.2 Comparators . . . . . . . . . . . . . . . . . . . . . . . . 3248.1.3 The Priority Queue ADT . . . . . . . . . . . . . . . . . 3278.1.4 A C++ Priority Queue Interface . . . . . . . . . . . . . . 3288.1.5 Sorting with a Priority Queue . . . . . . . . . . . . . . . 3298.1.6 The STL priority queue Class . . . . . . . . . . . . . . . 3308.2 Implementing a Priority Queue with a List . . . . . . . . . . 3318.2.1 A C++ Priority Queue Implementation using a List . . . 3338.2.2 Selection-Sort and Insertion-Sort . . . . . . . . . . . . . 3358.3 Heaps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3378.3.1 The Heap Data Structure . . . . . . . . . . . . . . . . . 3378.3.2 Complete Binary Trees and Their Representation . . . . 3408.3.3 Implementing a Priority Queue with a Heap . . . . . . . 3448.3.4 C++ Implementation . . . . . . . . . . . . . . . . . . . 3498.3.5 Heap-Sort . . . . . . . . . . . . . . . . . . . . . . . . . 3518.3.6 Bottom-Up Heap Construction . . . . . . . . . . . . . 3538.4 Adaptable Priority Queues . . . . . . . . . . . . . . . . . . . 3578.4.1 A List-Based Implementation . . . . . . . . . . . . . . . 3588.4.2 Location-Aware Entries . . . . . . . . . . . . . . . . . . 3608.5 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3619 Hash Tables, Maps, and Skip Lists 3679.1 Maps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3689.1.1 The Map ADT . . . . . . . . . . . . . . . . . . . . . . 3699.1.2 A C++ Map Interface . . . . . . . . . . . . . . . . . . . 3719.1.3 The STL map Class . . . . . . . . . . . . . . . . . . . . 3729.1.4 A Simple List-Based Map Implementation . . . . . . . . 3749.2 Hash Tables . . . . . . . . . . . . . . . . . . . . . . . . . . . 3759.2.1 Bucket Arrays . . . . . . . . . . . . . . . . . . . . . . . 3759.2.2 Hash Functions . . . . . . . . . . . . . . . . . . . . . . 3769.2.3 Hash Codes . . . . . . . . . . . . . . . . . . . . . . . . 3769.2.4 Compression Functions . . . . . . . . . . . . . . . . . . 3809.2.5 Collision-Handling Schemes . . . . . . . . . . . . . . . . 3829.2.6 Load Factors and Rehashing . . . . . . . . . . . . . . . 3869.2.7 A C++ Hash Table Implementation . . . . . . . . . . . . 3879.3 Ordered Maps . . . . . . . . . . . . . . . . . . . . . . . . . . 3949.3.1 Ordered Search Tables and Binary Search . . . . . . . . 3959.3.2 Two Applications of Ordered Maps . . . . . . . . . . . . 3999.4 Skip Lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 402iimain 2011/1/13 9:10 page xx #20iiiiiixx Contents9.4.1 Search and Update Operations in a Skip List . . . . . . 4049.4.2 A Probabilistic Analysis of Skip Lists . . . . . . . . . 4089.5 Dictionaries . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4119.5.1 The Dictionary ADT . . . . . . . . . . . . . . . . . . . 4119.5.2 A C++ Dictionary Implementation . . . . . . . . . . . . 4139.5.3 Implementations with Location-Aware Entries . . . . . . 4159.6 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41710 Search Trees 42310.1 Binary Search Trees . . . . . . . . . . . . . . . . . . . . . . . 42410.1.1 Searching . . . . . . . . . . . . . . . . . . . . . . . . . 42610.1.2 Update Operations . . . . . . . . . . . . . . . . . . . . 42810.1.3 C++ Implementation of a Binary Search Tree . . . . . . 43210.2 AVL Trees . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43810.2.1 Update Operations . . . . . . . . . . . . . . . . . . . . 44010.2.2 C++ Implementation of an AVL Tree . . . . . . . . . . . 44610.3 Splay Trees . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45010.3.1 Splaying . . . . . . . . . . . . . . . . . . . . . . . . . . 45010.3.2 When to Splay . . . . . . . . . . . . . . . . . . . . . . . 45410.3.3 Amortized Analysis of Splaying . . . . . . . . . . . . 45610.4 (2,4) Trees . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46110.4.1 Multi-Way Search Trees . . . . . . . . . . . . . . . . . . 46110.4.2 Update Operations for (2, 4) Trees . . . . . . . . . . . . 46710.5 Red-Black Trees . . . . . . . . . . . . . . . . . . . . . . . . . 47310.5.1 Update Operations . . . . . . . . . . . . . . . . . . . . 47510.5.2 C++ Implementation of a Red-Black Tree . . . . . . . . 48810.6 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49211 Sorting, Sets, and Selection 49911.1 Merge-Sort . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50011.1.1 Divide-and-Conquer . . . . . . . . . . . . . . . . . . . . 50011.1.2 Merging Arrays and Lists . . . . . . . . . . . . . . . . . 50511.1.3 The Running Time of Merge-Sort . . . . . . . . . . . . 50811.1.4 C++ Implementations of Merge-Sort . . . . . . . . . . . 50911.1.5 Merge-Sort and Recurrence Equations . . . . . . . . . 51111.2 Quick-Sort . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51311.2.1 Randomized Quick-Sort . . . . . . . . . . . . . . . . . . 52111.2.2 C++ Implementations and Optimizations . . . . . . . . . 52311.3 Studying Sorting through an Algorithmic Lens . . . . . . . 52611.3.1 A Lower Bound for Sorting . . . . . . . . . . . . . . . . 52611.3.2 Linear-Time Sorting: Bucket-Sort and Radix-Sort . . . . 52811.3.3 Comparing Sorting Algorithms . . . . . . . . . . . . . . 531iimain 2011/1/13 9:10 page xxi #21iiiiiiContents xxi11.4 Sets and Union/Find Structures . . . . . . . . . . . . . . . . 53311.4.1 The Set ADT . . . . . . . . . . . . . . . . . . . . . . . 53311.4.2 Mergable Sets and the Template Method Pattern . . . . 53411.4.3 Partitions with Union-Find Operations . . . . . . . . . . 53811.5 Selection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54211.5.1 Prune-and-Search . . . . . . . . . . . . . . . . . . . . . 54211.5.2 Randomized Quick-Select . . . . . . . . . . . . . . . . . 54311.5.3 Analyzing Randomized Quick-Select . . . . . . . . . . . 54411.6 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54512 Strings and Dynamic Programming 55312.1 String Operations . . . . . . . . . . . . . . . . . . . . . . . . 55412.1.1 The STL String Class . . . . . . . . . . . . . . . . . . . 55512.2 Dynamic Programming . . . . . . . . . . . . . . . . . . . . . 55712.2.1 Matrix Chain-Product . . . . . . . . . . . . . . . . . . . 55712.2.2 DNA and Text Sequence Alignment . . . . . . . . . . . 56012.3 Pattern Matching Algorithms . . . . . . . . . . . . . . . . . 56412.3.1 Brute Force . . . . . . . . . . . . . . . . . . . . . . . . 56412.3.2 The Boyer-Moore Algorithm . . . . . . . . . . . . . . . 56612.3.3 The Knuth-Morris-Pratt Algorithm . . . . . . . . . . . . 57012.4 Text Compression and the Greedy Method . . . . . . . . . 57512.4.1 The Human-Coding Algorithm . . . . . . . . . . . . . 57612.4.2 The Greedy Method . . . . . . . . . . . . . . . . . . . . 57712.5 Tries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57812.5.1 Standard Tries . . . . . . . . . . . . . . . . . . . . . . . 57812.5.2 Compressed Tries . . . . . . . . . . . . . . . . . . . . . 58212.5.3 Sux Tries . . . . . . . . . . . . . . . . . . . . . . . . 58412.5.4 Search Engines . . . . . . . . . . . . . . . . . . . . . . 58612.6 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58713 Graph Algorithms 59313.1 Graphs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59413.1.1 The Graph ADT . . . . . . . . . . . . . . . . . . . . . . 59913.2 Data Structures for Graphs . . . . . . . . . . . . . . . . . . . 60013.2.1 The Edge List Structure . . . . . . . . . . . . . . . . . . 60013.2.2 The Adjacency List Structure . . . . . . . . . . . . . . . 60313.2.3 The Adjacency Matrix Structure . . . . . . . . . . . . . 60513.3 Graph Traversals . . . . . . . . . . . . . . . . . . . . . . . . . 60713.3.1 Depth-First Search . . . . . . . . . . . . . . . . . . . . 60713.3.2 Implementing Depth-First Search . . . . . . . . . . . . . 61113.3.3 A Generic DFS Implementation in C++ . . . . . . . . . . 61313.3.4 Polymorphic Objects and Decorator Values . . . . . . 621iimain 2011/1/13 9:10 page xxii #22iiiiiixxii Contents13.3.5 Breadth-First Search . . . . . . . . . . . . . . . . . . . 62313.4 Directed Graphs . . . . . . . . . . . . . . . . . . . . . . . . . 62613.4.1 Traversing a Digraph . . . . . . . . . . . . . . . . . . . 62813.4.2 Transitive Closure . . . . . . . . . . . . . . . . . . . . . 63013.4.3 Directed Acyclic Graphs . . . . . . . . . . . . . . . . . . 63313.5 Shortest Paths . . . . . . . . . . . . . . . . . . . . . . . . . . 63713.5.1 Weighted Graphs . . . . . . . . . . . . . . . . . . . . . 63713.5.2 Dijkstras Algorithm . . . . . . . . . . . . . . . . . . . . 63913.6 Minimum Spanning Trees . . . . . . . . . . . . . . . . . . . . 64513.6.1 Kruskals Algorithm . . . . . . . . . . . . . . . . . . . . 64713.6.2 The Prim-Jarnk Algorithm . . . . . . . . . . . . . . . . 65113.7 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65414 Memory Management and B-Trees 66514.1 Memory Management . . . . . . . . . . . . . . . . . . . . . . 66614.1.1 Memory Allocation in C++ . . . . . . . . . . . . . . . . 66914.1.2 Garbage Collection . . . . . . . . . . . . . . . . . . . . 67114.2 External Memory and Caching . . . . . . . . . . . . . . . . . 67314.2.1 The Memory Hierarchy . . . . . . . . . . . . . . . . . . 67314.2.2 Caching Strategies . . . . . . . . . . . . . . . . . . . . 67414.3 External Searching and B-Trees . . . . . . . . . . . . . . . . 67914.3.1 (a, b) Trees . . . . . . . . . . . . . . . . . . . . . . . . 68014.3.2 B-Trees . . . . . . . . . . . . . . . . . . . . . . . . . . 68214.4 External-Memory Sorting . . . . . . . . . . . . . . . . . . . . 68314.4.1 Multi-Way Merging . . . . . . . . . . . . . . . . . . . . 68414.5 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 685A Useful Mathematical Facts 689Bibliography 697Index 702iimain 2011/1/13 9:10 page 1 #23iiiiiiChapter1 A C++ PrimerContents1.1 Basic C++ Programming Elements . . . . . . . . . . . 21.1.1 A Simple C++ Program . . . . . . . . . . . . . . . . 21.1.2 Fundamental Types . . . . . . . . . . . . . . . . . . 41.1.3 Pointers, Arrays, and Structures . . . . . . . . . . . 71.1.4 Named Constants, Scope, and Namespaces . . . . . 131.2 Expressions . . . . . . . . . . . . . . . . . . . . . . . . 161.2.1 Changing Types through Casting . . . . . . . . . . . 201.3 Control Flow . . . . . . . . . . . . . . . . . . . . . . . 231.4 Functions . . . . . . . . . . . . . . . . . . . . . . . . . 261.4.1 Argument Passing . . . . . . . . . . . . . . . . . . . 281.4.2 Overloading and Inlining . . . . . . . . . . . . . . . 301.5 Classes . . . . . . . . . . . . . . . . . . . . . . . . . . 321.5.1 Class Structure . . . . . . . . . . . . . . . . . . . . 331.5.2 Constructors and Destructors . . . . . . . . . . . . . 371.5.3 Classes and Memory Allocation . . . . . . . . . . . . 401.5.4 Class Friends and Class Members . . . . . . . . . . . 431.5.5 The Standard Template Library . . . . . . . . . . . . 451.6 C++ Program and File Organization . . . . . . . . . . 471.6.1 An Example Program . . . . . . . . . . . . . . . . . 481.7 Writing a C++ Program . . . . . . . . . . . . . . . . . 531.7.1 Design . . . . . . . . . . . . . . . . . . . . . . . . . 541.7.2 Pseudo-Code . . . . . . . . . . . . . . . . . . . . . 541.7.3 Coding . . . . . . . . . . . . . . . . . . . . . . . . . 551.7.4 Testing and Debugging . . . . . . . . . . . . . . . . 571.8 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . 60iimain 2011/1/13 9:10 page 2 #24iiiiii2 Chapter 1. A C++ Primer1.1 Basic C++ Programming ElementsBuilding data structures and algorithms requires communicating instructions to acomputer, and an excellent way to perform such communication is using a high-level computer language, such as C++. C++ evolved from the programming lan-guage C, and has, over time, undergone further evolution and development fromits original denition. It has incorporated many features that were not part of C,such as symbolic constants, in-line function substitution, reference types, paramet-ric polymorphism through templates, and exceptions (which are discussed later).As a result, C++ has grown to be a complex programming language. Fortunately,we do not need to know every detail of this sophisticated language in order to useit effectively.In this chapter and the next, we present a quick tour of the C++ programminglanguage and its features. It would be impossible to present a complete presentationof the language in this short space, however. Since we assume that the reader isalready familiar with programming with some other language, such as C or Java,our descriptions are short. This chapter presents the languages basic features, andin the following chapter, we concentrate on those features that are important forobject-oriented programming.C++ is a powerful and exible programming language, which was designed tobuild upon the constructs of the C programming language. Thus, with minor ex-ceptions, C++ is a superset of the C programming language. C++ shares Cs abilityto deal efciently with hardware at the level of bits, bytes, words, addresses, etc.In addition, C++ adds several enhancements over C (which motivates the nameC++), with the principal enhancement being the object-oriented concept of aclass.A class is a user-dened type that encapsulates many important mechanismssuch as guaranteed initialization, implicit type conversion, control of memory man-agement, operator overloading, and polymorphism (which are all important topicsthat are discussed later in this book). A class also has the ability to hide its un-derlying data. This allows a class to conceal its implementation details and allowsusers to conceptualize the class in terms of a well-dened interface. Classes enableprogrammers to break an application up into small, manageable pieces, or objects.The resulting programs are easier to understand and easier to maintain.1.1.1 A Simple C++ ProgramLike many programming languages, creating and running a C++ program requiresseveral steps. First, we create a C++ source le into which we enter the lines of ourprogram. After we save this le, we then run a program, called a compiler, whichiimain 2011/1/13 9:10 page 3 #25iiiiii1.1. Basic C++ Programming Elements 3creates a machine-code interpretation of this program. Another program, calleda linker (which is typically invoked automatically by the compiler), includes anyrequired library code functions needed and produces the nal machine-executablele. In order to run our program, the user requests that the system execute this le.Let us consider a very simple program to illustrate some of the languages basicelements. Dont worry if some elements in this example are not fully explained. Wediscuss them in greater depth later in this chapter. This program inputs two integers,which are stored in the variables x and y. It then computes their sum and stores theresult in a variable sum, and nally it outputs this sum. (The line numbers are notpart of the program; they are just for our reference.)1 #include 2 #include 3 /* This program inputs two numbers x and y and outputs their sum */4 int main( ) {5 int x, y;6 std::cout > x >> y; // input x and y8 int sum = x + y; // compute their sum9 std::cout y;We discuss the using statement later in Section 1.1.4. In order to keep ourexamples short, we often omit the include and using statements when displayingC++ code. We also use //. . . to indicate that some code has been omitted.Returning to our simple example C++ program, we note that the statement online 9 outputs the value of the variable sum, which in this case stores the computedsum of x and y. By default, the output statement does not produce an end of line.The special object std::endl generates a special end-of-line character. Another wayto generate an end of line is to output the newline character, \n.If run interactively, that is, with the user inputing values when requested todo so, this programs output would appear as shown below. The users input isindicated below in blue.Please enter two numbers: 7 35Their sum is 421.1.2 Fundamental TypesWe continue our exploration of C++ by discussing the languages basic data typesand how these types are represented as constants and variables. The fundamentaliimain 2011/1/13 9:10 page 5 #27iiiiii1.1. Basic C++ Programming Elements 5types are the basic building blocks from which more complex types are constructed.They include the following.bool Boolean value, either true or falsechar charactershort short integerint integerlong long integeroat single-precision oating-point numberdouble double-precision oating-point numberThere is also an enumeration, or enum, type to represent a set of discrete val-ues. Together, enumerations and the types bool, char, and int are called integraltypes. Finally, there is a special type void, which explicitly indicates the absenceof any type information. We now discuss each of these types in greater detail.CharactersA char variable holds a single character. A char in C++ is typically 8-bits, but theexact number of bits used for a char variable is dependent on the particular imple-mentation. By allowing different implementations to dene the meaning of basictypes, such as char, C++ can tailor its generated code to each machine architectureand so achieve maximum efciency. This exibility can be a source of frustrationfor programmers who want to write machine-independent programs, however.A literal is a constant value appearing in a program. Character literals areenclosed in single quotes, as in a, Q, and +. A backslash ( \) is used tospecify a number of special character literals as shown below.\n newline \t tab\b backspace \0 null\ single quote \" double quote\\ backslashThe null character, \0, is sometimes used to indicate the end of a string ofcharacters. Every character is associated with an integer code. The function int(ch)returns the integer value associated with a character variable ch.IntegersAn int variable holds an integer. Integers come in three sizes: short int, (plain)int, and long int. The terms short and long are synonyms for short int andlong int, respectively. Decimal numbers such as 0, 25, 98765, and -3 are of typeint. The sufx l or L can be added to indicate a long integer, as in 123456789L.Octal (base 8) constants are specied by prexing the number with the zero digit,and hexadecimal (base 16) constants can be specied by prexing the number withiimain 2011/1/13 9:10 page 6 #28iiiiii6 Chapter 1. A C++ Primer0x. For example, the literals 256, 0400, and 0x100 all represent the integer value256 (in decimal).When declaring a variable, we have the option of providing a denition, orinitial value. If no denition is given, the initial value is unpredictable, so it isimportant that each variable be assigned a value before being used. Variable namesmay consist of any combination of letters, digits, or the underscore ( ) character,but the rst character cannot be a digit. Here are some examples of declarations ofintegral variables.short n; // ns value is undenedint octalNumber = 0400; // 400 (base 8) = 256 (base 10)char newline character = \n;long BIGnumber = 314159265L;short aSTRANGE 1234 variABlE NaMe;Although it is legal to start a variable name with an underscore, it is best to avoidthis practice, since some C++ compilers use this convention for dening their owninternal identiers.C++ does not specify the exact number of bits in each type, but a short is at least16 bits, and a long is at least 32 bits. In fact, there is no requirement that long bestrictly longer than short (but it cannot be shorter!). Given a type T, the expressionsizeof(T) returns the size of type T, expressed as some number of multiples of thesize of char. For example, on typical systems, a char is 8 bits long, and an int is32 bits long, and hence sizeof(int) is 4.EnumerationsAn enumeration is a user-dened type that can hold any of a set of discrete values.Once dened, enumerations behave much like an integer type. A common useof enumerations is to provide meaningful names to a set of related values. Eachelement of an enumeration is associated with an integer value. By default, thesevalues count up from 0, but it is also possible to dene explicit constant values asshown below.enum Day { SUN, MON, TUE, WED, THU, FRI, SAT };enum Mood { HAPPY = 3, SAD = 1, ANXIOUS = 4, SLEEPY = 2 };Day today = THU; // today may be any of MON . . . SATMood myMood = SLEEPY; // myMood may be HAPPY, . . ., SLEEPYSince we did not specify values, SUN would be associated with 0, MON with 1,and so on. As a hint to the reader, we write enumeration names and other constantswith all capital letters.iimain 2011/1/13 9:10 page 7 #29iiiiii1.1. Basic C++ Programming Elements 7Floating PointA variable of type oat holds a single-precision oating-point number, and a vari-able of type double holds a double-precision oating-point number. As it doeswith integers, C++ leaves undened the exact number of bits in each of the oatingpoint types. By default, oating point literals, such as 3.14159 and -1234.567 areof type double. Scientic or exponential notation may by specied using eithere or E to separate the mantissa from the exponent, as in 3.14E5, which means3.14105. To force a literal to be a oat, add the sufx f or F, as in 2.0f or1.234e-3F.1.1.3 Pointers, Arrays, and StructuresWe next discuss how to combine fundamental types to form more complex ones.PointersEach program variable is stored in the computers memory at some location, oraddress. A pointer is a variable that holds the value of such an address. Given atype T, the type T* denotes a pointer to a variable of type T. For example, int*denotes a pointer to an integer.Two essential operators are used to manipulate pointers. The rst returns theaddress of an object in memory, and the second returns the contents of a givenaddress. In C++ the rst task is performed by the address-of operator, &. Forexample if x is an integer variable in your program &x is the address of x in memory.Accessing an objects value from its address is called dereferencing. This is doneusing the * operator. For example, if we were to declare q to be a pointer to aninteger (that is, int*) and then set q = &x, we could access xs value with *q.Assigning an integer value to *q effectively changes the value of x.Consider, for example, the code fragment below. The variable p is declared tobe a pointer to a char, and is initialized to point to the variable ch. Thus, *p isanother way of referring to ch. Observe that when the value of ch is changed, thevalue of *p changes as well.char ch = Q;char* p = &ch; // p holds the address of chcout isFreqFlyer = false;p>freqFlyerNo = "NONE";It would be natural to wonder whether we can initialize the members using the curlybrace ({...}) notation used above. The answer is no, but we will see another moreconvenient way of initializing members when we discuss classes and constructorsin Section 1.5.2.This new passenger object continues to exist in the free store until it is explicitlydeleteda process that is done using the delete operator, which destroys the objectand returns its space to the free store.delete p; // destroy the object p points toThe delete operator should only be applied to objects that have been allocatedthrough new. Since the object at ps address was allocated using the new operator,the C++ run-time system knows how much memory to deallocate for this deletestatement. Unlike some programming languages such as Java, C++ does not pro-vide automatic garbage collection. This means that C++ programmers have theresponsibility of explicitly deleting all dynamically allocated objects.Arrays can also be allocated with new. When this is done, the system allocatorreturns a pointer to the rst element of the array. Thus, a dynamically allocatedarray with elements of type T would be declared being of type *T. Arrays allocatedin this manner cannot be deallocated using the standard delete operator. Instead,the operator delete[ ] is used. Here is an example that allocates a character bufferof 500 elements, and then later deallocates it.char* buer = new char[500]; // allocate a buer of 500 charsbuer[3] = a; // elements are still accessed using [ ]delete [ ] buer; // delete the bueriimain 2011/1/13 9:10 page 13 #35iiiiii1.1. Basic C++ Programming Elements 13Memory LeaksFailure to delete dynamically allocated objects can cause problems. If we wereto change the (address) value of p without rst deleting the structure to which itpoints, there would be no way for us to access this object. It would continue toexist for the lifetime of the program, using up space that could otherwise be usedfor other allocated objects. Having such inaccessible objects in dynamic memoryis called a memory leak. We should strongly avoid memory leaks, especially inprograms that do a great deal of memory allocation and deallocation. A programwith memory leaks can run out of usable memory even when there is a sufcientamount of memory present. An important rule for a disciplined C++ programmeris the following:RememberIf an object is allocated with new, it should eventually be deallocated withdelete.ReferencesPointers provide one way to refer indirectly to an object. Another way is throughreferences. A reference is simply an alternative name for an object. Given a typeT, the notation T& indicates a reference to an object of type T. Unlike pointers,which can be NULL, a reference in C++ must refer to an actual variable. When areference is declared, its value must be initialized. Afterwards, any access to thereference is treated exactly as if it is an access to the underlying object.string author = "Samuel Clemens";string& penName = author; // penName is an alias for authorpenName = "Mark Twain"; // now author = Mark Twaincout isFreqFlyer) . . .Bitwise OperatorsThe following operators act on the representations of numbers as binary bit strings.They can be applied to any integer type, and the result is an integer type. exp bitwise complementexp & exp bitwise andexp ^ exp bitwise exclusive-orexp | exp bitwise orexp1 > exp2 shift exp1 right by exp2 bitsThe left shift operator always lls with zeros. How the right shift lls dependson a variables type. In C++ integer variables are signed quantities by default,but they may be declared as being unsigned, as in unsigned int x. If the leftoperand of a right shift is unsigned, the shift lls with zeros and otherwise the rightshift lls with the numbers sign bit (0 for positive numbers and 1 for negativenumbers). Note that the input (>>) and output ( var stream inputstream >) and output(comparison < >=equality == !=bitwise and &bitwise exclusive-or ^bitwise or |logical and &&logical or | |conditional bool exp ? true exp : false expassignment = += = *= /= %= >>= > command; // input command characterswitch (command) { // switch based on command valuecase I : // if (command == I)editInsert();break;case D : // else if (command == D)editDelete();break;case R : // else if (command == R)editReplace();break;default : // elsecout = 0) {sum += a[i++];}The do-while loop is similar to the while loop in that the condition is tested atthe end of the loop execution rather than before. It has the following syntax.doloop body statementwhile ( condition )For LoopMany loops involve three common elements: an initialization, a condition underwhich to continue execution, and an increment to be performed after each executionof the loops body. A for loop conveniently encapsulates these three elements.for ( initialization ; condition ; increment )loop body statementThe initialization indicates what is to be done before starting the loop. Typ-ically, this involves declaring and initializing a loop-control variable or counter.Next, the condition gives a Boolean expression to be tested in order for the loop tocontinue execution. It is evaluated before executing the loop body. When the con-dition evaluates to false, execution jumps to the next statement after the for loop.Finally, the increment species what changes are to be made at the end of eachexecution of the loop body. Typically, this involves incrementing or decrementingthe value of the loop-control variable.Here is a simple example, which prints the positive elements of an array, oneper line. Recall that \n generates a newline character.const int NUM ELEMENTS = 100;double b[NUM ELEMENTS];// . . .for (int i = 0; i < NUM ELEMENTS; i++) {if (b[i] > 0)cout value(), respectively.We assume that the key elements are drawn from a total order, which is denedby overloading the C++ relational less-than operator ( key(v) thenreturn TreeSearch(k, T.right(v))return v {we know k = key(v)}Code Fragment 10.1: Recursive search in a binary search tree.iimain 2011/1/13 12:30 page 427 #449iiiiii10.1. Binary Search Trees 427Analysis of Binary Tree SearchingThe analysis of the worst-case running time of searching in a binary search tree Tis simple. Algorithm TreeSearch is recursive and executes a constant number ofprimitive operations for each recursive call. Each recursive call of TreeSearch ismade on a child of the previous node. That is, TreeSearch is called on the nodesof a path of T that starts at the root and goes down one level at a time. Thus, thenumber of such nodes is bounded by h +1, where h is the height of T. In otherwords, since we spend O(1) time per node encountered in the search, function ndon map M runs in O(h) time, where h is the height of the binary search tree T usedto implement M. (See Figure 10.3.)Figure 10.3: The running time of searching in a binary search tree. We use a stan-dard visualization shortcut of viewing a binary search tree as a big triangle and apath from the root as a zig-zag line.We can also show that a variation of the above algorithm performs operationndAll(k) of the dictionary ADT in time O(h+s), where s is the number of entriesreturned. However, this function is slightly more complicated, and the details areleft as an exercise (Exercise C-10.2).Admittedly, the height h of T can be as large as the number of entries, n, butwe expect that it is usually much smaller. Indeed, we show how to maintain anupper bound of O(logn) on the height of a search tree T in Section 10.2. Before wedescribe such a scheme, however, let us describe implementations for map updatefunctions.iimain 2011/1/13 12:30 page 428 #450iiiiii428 Chapter 10. Search Trees10.1.2 Update OperationsBinary search trees allow implementations of the insert and erase operations usingalgorithms that are fairly straightforward, but not trivial.InsertionLet us assume a proper binary tree T supports the following update operation:insertAtExternal(v, e): Insert the element e at the external node v, and expandv to be internal, having new (empty) external node chil-dren; an error occurs if v is an internal node.Given this function, we perform insert(k, x) for a dictionary implemented with abinary search tree T by calling TreeInsert(k, x, T.root()), which is given in CodeFragment 10.2.Algorithm TreeInsert(k, x, v):Input: A search key k, an associated value, x, and a node v of TOutput: A new node w in the subtree T(v) that stores the entry (k, x)w TreeSearch(k, v)if T.isInternal(w) thenreturn TreeInsert(k, x, T.left(w)) {going to the right would be correct too}T.insertAtExternal(w, (k, x)) {this is an appropriate place to put (k, x)}return wCode Fragment 10.2: Recursive algorithm for insertion in a binary search tree.This algorithm traces a path from Ts root to an external node, which is ex-panded into a new internal node accommodating the new entry. An example ofinsertion into a binary search tree is shown in Figure 10.4.Figure 10.4: Insertion of an entry with key 78 into the search tree of Figure 10.1:(a) nding the position to insert; (b) the resulting tree.iimain 2011/1/13 12:30 page 429 #451iiiiii10.1. Binary Search Trees 429RemovalThe implementation of the erase(k) operation on a map M implemented with abinary search tree T is a bit more complex, since we do not wish to create anyholes in the tree T. We assume, in this case, that a proper binary tree supportsthe following additional update operation:removeAboveExternal(v): Remove an external node v and its parent, replacing vsparent with vs sibling; an error occurs if v is not external.Given this operation, we begin our implementation of operation erase(k) ofthe map ADT by calling TreeSearch(k, T.root()) on T to nd a node of T storingan entry with key equal to k. If TreeSearch returns an external node, then thereis no entry with key k in map M, and an error condition is signaled. If, instead,TreeSearch returns an internal node w, then w stores an entry we wish to remove,and we distinguish two cases: If one of the children of node w is an external node, say node z, we simply re-move w and z from T by means of operation removeAboveExternal(z) on T.This operation restructures T by replacing w with the sibling of z, removingboth w and z from T. (See Figure 10.5.) If both children of node w are internal nodes, we cannot simply remove thenode w from T, since this would create a hole in T. Instead, we proceed asfollows (see Figure 10.6): We nd the rst internal node y that follows w in an inorder traversalof T. Node y is the left-most internal node in the right subtree of w,and is found by going rst to the right child of w and then down Tfrom there, following the left children. Also, the left child x of y is theexternal node that immediately follows node w in the inorder traversalof T. We move the entry of y into w. This action has the effect of removingthe former entry stored at w. We remove nodes x and y from T by calling removeAboveExternal(x)on T. This action replaces y with xs sibling, and removes both x and yfrom T.As with searching and insertion, this removal algorithm traverses a path fromthe root to an external node, possibly moving an entry between two nodes of thispath, and then performs a removeAboveExternal operation at that external node.The position-based variant of removal is the same, except that we can skip theinitial step of invoking TreeSearch(k, T.root()) to locate the node containing thekey.iimain 2011/1/13 12:30 page 430 #452iiiiii430 Chapter 10. Search TreesFigure 10.5: Removal from the binary search tree of Figure 10.4b, where the entryto remove (with key 32) is stored at a node (w) with an external child: (a) beforethe removal; (b) after the removal.Figure 10.6: Removal from the binary search tree of Figure 10.4b, where the entryto remove (with key 65) is stored at a node (w) whose children are both internal:(a) before the removal; (b) after the removal.iimain 2011/1/13 12:30 page 431 #453iiiiii10.1. Binary Search Trees 431Performance of a Binary Search TreeThe analysis of the search, insertion, and removal algorithms are similar. We spendO(1) time at each node visited, and, in the worst case, the number of nodes visitedis proportional to the height h of T. Thus, in a map M implemented with a binarysearch tree T, the nd, insert, and erase functions run in O(h) time, where h is theheight of T. Thus, a binary search tree T is an efcient implementation of a mapwith n entries only if the height of T is small. In the best case, T has height h =log(n+1), which yields logarithmic-time performance for all the map operations.In the worst case, however, T has height n, in which case it would look and feel likean ordered list implementation of a map. Such a worst-case conguration arises,for example, if we insert a series of entries with keys in increasing or decreasingorder. (See Figure 10.7.)10203040Figure 10.7: Example of a binary search tree with linear height, obtained by insert-ing entries with keys in increasing order.The performance of a map implemented with a binary search tree is summa-rized in the following proposition and in Table 10.1.Proposition 10.1: A binary search tree T with height h for n key-value entriesuses O(n) space and executes the map ADT operations with the following runningtimes. Operations size and empty each take O(1) time. Operations nd, insert, anderase each take O(h) time.Operation Timesize, empty O(1)nd, insert, erase O(h)Table 10.1: Running times of the main functions of a map realized by a binarysearch tree. We denote the current height of the tree with h. The space usageis O(n), where n is the number of entries stored in the map.Note that the running time of search and update operations in a binary searchtree varies dramatically depending on the trees height. We can nevertheless takeiimain 2011/1/13 12:30 page 432 #454iiiiii432 Chapter 10. Search Treescomfort that, on average, a binary search tree with n keys generated from a ran-dom series of insertions and removals of keys has expected height O(logn). Such astatement requires careful mathematical language to precisely dene what we meanby a random series of insertions and removals, and sophisticated probability theoryto prove; hence, its justication is beyond the scope of this book. Nevertheless,keep in mind the poor worst-case performance and take care in using standard bi-nary search trees in applications where updates are not random. There are, afterall, applications where it is essential to have a map with fast worst-case search andupdate times. The data structures presented in the next sections address this need.10.1.3 C++ Implementation of a Binary Search TreeIn this section, we present a C++ implementation of the dictionary ADT based ona binary search tree, which we call SearchTree. Recall that a dictionary differsfrom a map in that it allows multiple copies of the same key to be inserted. Forsimplicity, we have not implemented the ndAll function.To keep the number of template parameters small, rather than templating ourclass on the key and value types, we have chosen instead to template our binarysearch tree on just the entry type denoted E. To obtain access to the key and valuetypes, we assume that the entry class denes two public types dening them. Givenan entry object of type E, we may access these types E::Key and E::Value. Oth-erwise, our entry class is essentially the same as the entry class given in CodeFragment 9.1. It is presented in Code Fragment 10.3.template class Entry { // a (key, value) pairpublic: // public typestypedef K Key; // key typetypedef V Value; // value typepublic: // public functionsEntry(const K& k = K(), const V& v = V()) // constructor: key(k), value(v) { }const K& key() const { return key; } // get key (read only)const V& value() const { return value; } // get value (read only)void setKey(const K& k) { key = k; } // set keyvoid setValue(const V& v) { value = v; } // set valueprivate: // private dataK key; // keyV value; // value};Code Fragment 10.3: A C++ class for a key-value entry.iimain 2011/1/13 12:30 page 433 #455iiiiii10.1. Binary Search Trees 433In Code Fragment 10.4, we present the main parts of the class denition forour binary search tree. We begin by dening the publicly accessible types for theentry, key, value, and the class iterator. This is followed by a declaration of thepublic member functions. We dene two local types, BinaryTree and TPos, whichrepresent a binary search tree and position within this binary tree, respectively.We also declare a number of local utility functions to help in nding, inserting,and erasing entries. The member data consists of a binary tree and the number ofentries in the tree.template class SearchTree { // a binary search treepublic: // public typestypedef typename E::Key K; // a keytypedef typename E::Value V; // a valueclass Iterator; // an iterator/positionpublic: // public functionsSearchTree(); // constructorint size() const; // number of entriesbool empty() const; // is the tree empty?Iterator nd(const K& k); // nd entry with key kIterator insert(const K& k, const V& x); // insert (k,x)void erase(const K& k) throw(NonexistentElement); // remove key k entryvoid erase(const Iterator& p); // remove entry at pIterator begin(); // iterator to rst entryIterator end(); // iterator to end entryprotected: // local utilitiestypedef BinaryTree BinaryTree; // linked binary treetypedef typename BinaryTree::Position TPos; // position in the treeTPos root() const; // get virtual rootTPos nder(const K& k, const TPos& v); // nd utilityTPos inserter(const K& k, const V& x); // insert utilityTPos eraser(TPos& v); // erase utilityTPos restructure(const TPos& v) // restructurethrow(BoundaryViolation);private: // member dataBinaryTree T; // the binary treeint n; // number of entriespublic:// . . .insert Iterator class declaration here};Code Fragment 10.4: Class SearchTree, which implements a binary search tree.We have omitted the denition of the iterator class for our binary search tree.This is presented in Code Fragment 10.5. An iterator consists of a single positionin the tree. We overload the dere