Sunteți pe pagina 1din 273

Welcome to Problem Solving with Algorithms and Data Structures

By Brad Miller and David Ranum, Luther College

Introduction

Introduction o Objectives o Getting Started o hat Is Com!uter Science" o Revie# o$ Basic %ython o Summary o &ey 'erms o Discussion (uestions o %rogramming )*ercises

Analysis

+lgorithm +nalysis o Objectives o hat Is +lgorithm +nalysis" o %er$ormance o$ %ython Data Structures o Summary o &ey 'erms o Discussion (uestions o %rogramming )*ercises

Basic Data Structures

Basic Data Structures o Objectives o hat +re Linear Structures" Stac,s o hat is a Stac," o 'he Stac, +bstract Data 'y!e o Im!lementing a Stac, in %ython o Sim!le Balanced %arentheses o Balanced Symbols -+ General Case. o Converting Decimal /umbers to Binary /umbers o In$i*, %re$i* and %ost$i* )*!ressions (ueues o hat Is a (ueue" o 'he (ueue +bstract Data 'y!e o Im!lementing a (ueue in %ython o Simulation0 1ot %otato 2

Simulation0 %rinting 'as,s hat Is a De3ue" 'he De3ue +bstract Data 'y!e Im!lementing a De3ue in %ython %alindrome4Chec,er

De3ues
o o o o

Lists 'he 5nordered List +bstract Data 'y!e Im!lementing an 5nordered List0 Lin,ed Lists 'he Ordered List +bstract Data 'y!e Im!lementing an Ordered List Summary &ey 'erms Discussion (uestions %rogramming )*ercises
o o o o

Recursion

Recursion Objectives hat Is Recursion" o Calculating the Sum o$ a List o$ /umbers o 'he 'hree La#s o$ Recursion o Converting an Integer to a String in +ny Base Stac, 6rames0 Im!lementing Recursion 7isuali8ing Recursion o Sier!ins,i 'riangle Com!le* Recursive %roblems o 'o#er o$ 1anoi )*!loring a Ma8e Dynamic %rogramming Summary &ey 'erms Discussion (uestions %rogramming )*ercises

Sorting and Searching

Sorting and Searching o Objectives o Searching Sorting o 'he Bubble Sort o 'he Selection Sort o 'he Insertion Sort o 'he Shell Sort o 'he Merge Sort o 'he (uic, Sort 9

Searching and Sorting o Summary o &ey 'erms o Discussion (uestions o %rogramming )*ercises

Trees and Tree Agorithms

'rees Objectives )*am!les o$ 'rees 7ocabulary and De$initions Im!lementation o List o$ Lists Re!resentation o /odes and Re$erences Binary 'ree +!!lications o %arse 'ree o 'ree 'raversals %riority (ueues #ith Binary 1ea!s o Binary 1ea! O!erations o Binary 1ea! Im!lementation Binary Search 'rees o Search 'ree O!erations o Search 'ree Im!lementation o Search 'ree +nalysis Balanced Binary Search 'rees o +7L 'ree %er$ormance o +7L 'ree Im!lementation o Summary o$ Ma! +D' Im!lementations Summary &ey 'erms Discussion (uestions %rogramming )*ercises
o o o

Graphs and Graph Algorithms

Gra!hs Objectives 7ocabulary and De$initions 'he Gra!h +bstract Data 'y!e Breadth 6irst Search o 'he ord Ladder %roblem o Building the ord Ladder Gra!h o Im!lementing Breadth 6irst Search o Breadth 6irst Search +nalysis De!th 6irst Search o 'he &night:s 'our %roblem o Building the &night:s 'our Gra!h
o o o

Im!lementing &night:s 'our &night:s 'our +nalysis General De!th 6irst Search De!th 6irst Search +nalysis 'o!ological Sorting Strongly Connected Com!onents Shortest %ath %roblems o Dij,stra:s +lgorithm o +nalysis o$ Dij,stra:s +lgorithm o %rim:s S!anning 'ree +lgorithm Summary &ey 'erms Discussion (uestions %rogramming )*ercises
o o o o

Ac nowledgements Indices and tables


Index Module Index Search Page

<

Introduction
!b"ectives

'o revie# the ideas o$ com!uter science, !rogramming, and !roblem4solving= 'o understand abstraction and the role it !lays in the !roblem4solving !rocess= 'o understand and im!lement the notion o$ an abstract data ty!e= 'o revie# the %ython !rogramming language=

Getting Started
'he #ay #e thin, about !rogramming has undergone many changes in the years since the $irst electronic com!uters re3uired !atch cables and s#itches to convey instructions $rom human to machine= +s is the case #ith many as!ects o$ society, changes in com!uting technology !rovide com!uter scientists #ith a gro#ing number o$ tools and !lat$orms on #hich to !ractice their cra$t= +dvances such as $aster !rocessors, high4s!eed net#or,s, and large memory ca!acities have created a s!iral o$ com!le*ity through #hich com!uter scientists must navigate= 'hroughout all o$ this ra!id evolution, a number o$ basic !rinci!les have remained constant= 'he science o$ com!uting is concerned #ith using com!uters to solve !roblems= >ou have no doubt s!ent considerable time learning the basics o$ !roblem4solving and ho!e$ully $eel con$ident in your ability to ta,e a !roblem statement and develo! a solution= >ou have also learned that #riting com!uter !rograms is o$ten hard= 'he com!le*ity o$ large !roblems and the corres!onding com!le*ity o$ the solutions can tend to overshado# the $undamental ideas related to the !roblem4solving !rocess= 'his cha!ter em!hasi8es t#o im!ortant areas $or the rest o$ the te*t= 6irst, it revie#s the $rame#or, #ithin #hich com!uter science and the study o$ algorithms and data structures must $it, in !articular, the reasons #hy #e need to study these to!ics and ho# understanding these to!ics hel!s us to become better !roblem solvers= Second, #e revie# the %ython !rogramming language= +lthough #e cannot !rovide a detailed, e*haustive re$erence, #e #ill give e*am!les and e*!lanations $or the basic constructs and ideas that #ill occur throughout the remaining cha!ters=

What Is #omputer Science$


Com!uter science is o$ten di$$icult to de$ine= 'his is !robably due to the un$ortunate use o$ the #ord ?com!uter@ in the name= +s you are !erha!s a#are, com!uter science is not sim!ly the study o$ com!uters= +lthough com!uters !lay an im!ortant su!!orting role as a tool in the disci!line, they are just thatAtools= Com!uter science is the study o$ !roblems, !roblem4solving, and the solutions that come out o$ the !roblem4solving !rocess= Given a !roblem, a com!uter scientist:s goal is to develo! an algorithm, a ste!4by4ste! list o$ instructions $or solving any instance o$ the !roblem that

might arise= +lgorithms are $inite !rocesses that i$ $ollo#ed #ill solve the !roblem= +lgorithms are solutions= Com!uter science can be thought o$ as the study o$ algorithms= 1o#ever, #e must be care$ul to include the $act that some !roblems may not have a solution= +lthough !roving this statement is beyond the sco!e o$ this te*t, the $act that some !roblems cannot be solved is im!ortant $or those #ho study com!uter science= e can $ully de$ine com!uter science, then, by including both ty!es o$ !roblems and stating that com!uter science is the study o$ solutions to !roblems as #ell as the study o$ !roblems #ith no solutions= It is also very common to include the #ord computable #hen describing !roblems and solutions= e say that a !roblem is com!utable i$ an algorithm e*ists $or solving it= +n alternative de$inition $or com!uter science, then, is to say that com!uter science is the study o$ !roblems that are and that are not com!utable, the study o$ the e*istence and the none*istence o$ algorithms= In any case, you #ill note that the #ord ?com!uter@ did not come u! at all= Solutions are considered inde!endent $rom the machine= Com!uter science, as it !ertains to the !roblem4solving !rocess itsel$, is also the study o$ abstraction= +bstraction allo#s us to vie# the !roblem and solution in such a #ay as to se!arate the so4called logical and !hysical !ers!ectives= 'he basic idea is $amiliar to us in a common e*am!le= Consider the automobile that you may have driven to school or #or, today= +s a driver, a user o$ the car, you have certain interactions that ta,e !lace in order to utili8e the car $or its intended !ur!ose= >ou get in, insert the ,ey, start the car, shi$t, bra,e, accelerate, and steer in order to drive= 6rom an abstraction !oint o$ vie#, #e can say that you are seeing the logical !ers!ective o$ the automobile= >ou are using the $unctions !rovided by the car designers $or the !ur!ose o$ trans!orting you $rom one location to another= 'hese $unctions are sometimes also re$erred to as the inter%ace= On the other hand, the mechanic #ho must re!air your automobile ta,es a very di$$erent !oint o$ vie#= She not only ,no#s ho# to drive but must ,no# all o$ the details necessary to carry out all the $unctions that #e ta,e $or granted= She needs to understand ho# the engine #or,s, ho# the transmission shi$ts gears, ho# tem!erature is controlled, and so on= 'his is ,no#n as the !hysical !ers!ective, the details that ta,e !lace ?under the hood=@ 'he same thing ha!!ens #hen #e use com!uters= Most !eo!le use com!uters to #rite documents, send and receive email, sur$ the #eb, !lay music, store images, and !lay games #ithout any ,no#ledge o$ the details that ta,e !lace to allo# those ty!es o$ a!!lications to #or,= 'hey vie# com!uters $rom a logical or user !ers!ective= Com!uter scientists, !rogrammers, technology su!!ort sta$$, and system administrators ta,e a very di$$erent vie# o$ the com!uter= 'hey must ,no# the details o$ ho# o!erating systems #or,, ho# net#or, !rotocols are con$igured, and ho# to code various scri!ts that control $unction= 'hey must be able to control the lo#4level details that a user sim!ly assumes= 'he common !oint $or both o$ these e*am!les is that the user o$ the abstraction, sometimes also called the client, does not need to ,no# the details as long as the user is a#are o$ the #ay the inter$ace #or,s= 'his inter$ace is the #ay #e as users communicate #ith the underlying com!le*ities o$ the im!lementation= +s another e*am!le o$ abstraction, consider the %ython math module= Once #e im!ort the module, #e can !er$orm com!utations such as C

>>> import math >>> math.sqrt(16) 4.0 >>>

'his is an e*am!le o$ procedural abstraction= e do not necessarily ,no# ho# the s3uare root is being calculated, but #e ,no# #hat the $unction is called and ho# to use it= I$ #e !er$orm the im!ort correctly, #e can assume that the $unction #ill !rovide us #ith the correct results= e ,no# that someone im!lemented a solution to the s3uare root !roblem but #e only need to ,no# ho# to use it= 'his is sometimes re$erred to as a ?blac, bo*@ vie# o$ a !rocess= e sim!ly describe the inter$ace0 the name o$ the $unction, #hat is needed -the !arameters., and #hat #ill be returned= 'he details are hidden inside -Figure 1.=

%rocedural +bstraction A test

What Is Programming?
Programming is the !rocess o$ ta,ing an algorithm and encoding it into a notation, a !rogramming language, so that it can be e*ecuted by a com!uter= +lthough many !rogramming languages and many di$$erent ty!es o$ com!uters e*ist, the im!ortant $irst ste! is the need to have the solution= ithout an algorithm there can be no !rogram= Com!uter science is not the study o$ !rogramming= %rogramming, ho#ever, is an im!ortant !art o$ #hat a com!uter scientist does= %rogramming is o$ten the #ay that #e create a re!resentation $or our solutions= 'here$ore, this language re!resentation and the !rocess o$ creating it becomes a $undamental !art o$ the disci!line= +lgorithms describe the solution to a !roblem in terms o$ the data needed to re!resent the !roblem instance and the set o$ ste!s necessary to !roduce the intended result= %rogramming languages must !rovide a notational #ay to re!resent both the !rocess and the data= 'o this end, languages !rovide control constructs and data ty!es= Control constructs allo# algorithmic ste!s to be re!resented in a convenient yet unambiguous #ay= +t a minimum, algorithms re3uire constructs that !er$orm se3uential !rocessing, selection $or decision4ma,ing, and iteration $or re!etitive control= +s long as the language !rovides these basic statements, it can be used $or algorithm re!resentation= +ll data items in the com!uter are re!resented as strings o$ binary digits= In order to give these strings meaning, #e need to have data types= Data ty!es !rovide an inter!retation $or this binary data so that #e can thin, about the data in terms that ma,e sense #ith res!ect to the !roblem being solved= 'hese lo#4level, built4in data ty!es -sometimes called the !rimitive data ty!es. !rovide the building bloc,s $or algorithm develo!ment=

6or e*am!le, most !rogramming languages !rovide a data ty!e $or integers= Strings o$ binary digits in the com!uter:s memory can be inter!reted as integers and given the ty!ical meanings that #e commonly associate #ith integers -e=g= 9;, CB<, and 42E.= In addition, a data ty!e also !rovides a descri!tion o$ the o!erations that the data items can !artici!ate in= ith integers, o!erations such as addition, subtraction, and multi!lication are common= e have come to e*!ect that numeric ty!es o$ data can !artici!ate in these arithmetic o!erations= 'he di$$iculty that o$ten arises $or us is the $act that !roblems and their solutions are very com!le*= 'hese sim!le, language4!rovided constructs and data ty!es, although certainly su$$icient to re!resent com!le* solutions, are ty!ically at a disadvantage as #e #or, through the !roblem4solving !rocess= e need #ays to control this com!le*ity and assist #ith the creation o$ solutions=

Why Study Data Structures and Abstract Data Types?


'o manage the com!le*ity o$ !roblems and the !roblem4solving !rocess, com!uter scientists use abstractions to allo# them to $ocus on the ?big !icture@ #ithout getting lost in the details= By creating models o$ the !roblem domain, #e are able to utili8e a better and more e$$icient !roblem4solving !rocess= 'hese models allo# us to describe the data that our algorithms #ill mani!ulate in a much more consistent #ay #ith res!ect to the !roblem itsel$= )arlier, #e re$erred to !rocedural abstraction as a !rocess that hides the details o$ a !articular $unction to allo# the user or client to vie# it at a very high level= e no# turn our attention to a similar idea, that o$ data abstraction= +n abstract data type, sometimes abbreviated ADT, is a logical descri!tion o$ ho# #e vie# the data and the o!erations that are allo#ed #ithout regard to ho# they #ill be im!lemented= 'his means that #e are concerned only #ith #hat the data is re!resenting and not #ith ho# it #ill eventually be constructed= By !roviding this level o$ abstraction, #e are creating an encapsulation around the data= 'he idea is that by enca!sulating the details o$ the im!lementation, #e are hiding them $rom the user:s vie#= 'his is called in%ormation hiding= Figure 2 sho#s a !icture o$ #hat an abstract data ty!e is and ho# it o!erates= 'he user interacts #ith the inter$ace, using the o!erations that have been s!eci$ied by the abstract data ty!e= 'he abstract data ty!e is the shell that the user interacts #ith= 'he im!lementation is hidden one level dee!er= 'he user is not concerned #ith the details o$ the im!lementation=

+bstract Data 'y!e 'he im!lementation o$ an abstract data ty!e, o$ten re$erred to as a data structure, #ill re3uire that #e !rovide a !hysical vie# o$ the data using some collection o$ !rogramming constructs and !rimitive data ty!es= +s #e discussed earlier, the se!aration o$ these t#o !ers!ectives #ill allo# us to de$ine the com!le* data models $or our !roblems #ithout giving any indication as to the details o$ ho# the model #ill actually be built= 'his !rovides an implementation&independent vie# o$ the data= Since there #ill usually be many di$$erent #ays to im!lement an abstract data ty!e, this im!lementation inde!endence allo#s the !rogrammer to s#itch the details o$ the im!lementation #ithout changing the #ay the user o$ the data interacts #ith it= 'he user can remain $ocused on the !roblem4solving !rocess=

Why Study Algorithms?


Com!uter scientists learn by e*!erience= e learn by seeing others solve !roblems and by solving !roblems by ourselves= Being e*!osed to di$$erent !roblem4solving techni3ues and seeing ho# di$$erent algorithms are designed hel!s us to ta,e on the ne*t challenging !roblem that #e are given= By considering a number o$ di$$erent algorithms, #e can begin to develo! !attern recognition so that the ne*t time a similar !roblem arises, #e are better able to solve it= +lgorithms are o$ten 3uite di$$erent $rom one another= Consider the e*am!le o$ s3rt seen earlier= It is entirely !ossible that there are many di$$erent #ays to im!lement the details to com!ute the s3uare root $unction= One algorithm may use many $e#er resources than another= One algorithm might ta,e 2G times as long to return the result as the other= e #ould li,e to have some #ay to com!are these t#o solutions= )ven though they both #or,, one is !erha!s ?better@ than the other= e might suggest that one is more e$$icient or that one sim!ly #or,s $aster or uses less memory= +s #e study algorithms, #e can learn analysis techni3ues that allo# us to com!are and contrast solutions based solely on their o#n characteristics, not the characteristics o$ the !rogram or com!uter used to im!lement them= In the #orst case scenario, #e may have a !roblem that is intractable, meaning that there is no algorithm that can solve the !roblem in a realistic amount o$ time= It is im!ortant to be

able to distinguish bet#een those !roblems that have solutions, those that do not, and those #here solutions e*ist but re3uire too much time or other resources to #or, reasonably= 'here #ill o$ten be trade4o$$s that #e #ill need to identi$y and decide u!on= +s com!uter scientists, in addition to our ability to solve !roblems, #e #ill also need to ,no# and understand solution evaluation techni3ues= In the end, there are o$ten many #ays to solve a !roblem= 6inding a solution and then deciding #hether it is a good one are tas,s that #e #ill do over and over again=

Review o% Basic Python


In this section, #e #ill revie# the !rogramming language %ython and also !rovide some more detailed e*am!les o$ the ideas $rom the !revious section= I$ you are ne# to %ython or $ind that you need more in$ormation about any o$ the to!ics !resented, #e recommend that you consult the resources listed at the end o$ this boo,=HoreillyG<IH8elleG<I Our goal here is to reac3uaint you #ith the language and also rein$orce some o$ the conce!ts that #ill be central to later cha!ters= %ython is a modern, easy4to4learn, object4oriented !rogramming language= It has a !o#er$ul set o$ built4in data ty!es and easy4to4use control constructs= Since %ython is an inter!reted language, it is most easily revie#ed by sim!ly loo,ing at and describing interactive sessions= >ou should recall that the inter!reter dis!lays the $amiliar JJJ !rom!t and then evaluates the %ython construct that you !rovide= 6or e*am!le,
>>> print("Algorithms and Data Structures") Algorithms and Data Structures >>>

sho#s the !rom!t, the !rint $unction, the result, and the ne*t !rom!t=

Getting Started with Data


e stated above that %ython su!!orts the object4oriented !rogramming !aradigm= 'his means that %ython considers data to be the $ocal !oint o$ the !roblem4solving !rocess= In %ython, as #ell as in any other object4oriented !rogramming language, #e de$ine a class to be a descri!tion o$ #hat the data loo, li,e -the state. and #hat the data can do -the behavior.= Classes are analogous to abstract data ty!es because a user o$ a class only sees the state and behavior o$ a data item= Data items are called ob"ects in the object4oriented !aradigm= +n object is an instance o$ a class=

Built&in Atomic Data Types


e #ill begin our revie# by considering the atomic data ty!es= %ython has t#o main built4in numeric classes that im!lement the integer and $loating !oint data ty!es= 'hese %ython classes are called int and $loat= 'he standard arithmetic o!erations, K, 4, L, M, and LL -e*!onentiation., can be used #ith !arentheses $orcing the order o$ o!erations a#ay $rom normal o!erator !recedence= Other very use$ul o!erations are the remainder -modulo. o!erator, N, and integer division, MM= /ote that #hen t#o integers are divided, the result is a $loating !oint= 'he integer division o!erator returns the integer !ortion o$ the 3uotient by truncating any $ractional !art= 2G

1 2 4 ! 6 " # $ 10 11 12 1 print print print print print print print print print print print

2% &4 (2% )&4 2&&10 6' "' "'' "( '6 ''6 (6 2&&100

-introO2.

'he boolean data ty!e, im!lemented as the %ython bool class, #ill be 3uite use$ul $or re!resenting truth values= 'he !ossible state values $or a boolean object are 'rue and 6alse #ith the standard boolean o!erators, and, or, and not=
1 >>> )rue 2 )rue >>> *alse 4 *alse ! >>> *alse or )rue 6 )rue " >>> not (*alse or )rue) # *alse $ >>> )rue and )rue 10 )rue

Boolean data objects are also used as results $or com!arison o!erators such as e3uality -PP. and greater than -J.= In addition, relational o!erators and logical o!erators can be combined together to $orm com!le* logical 3uestions= Table 1 sho#s the relational and logical o!erators #ith e*am!les sho#n in the session that $ollo#s= 22

!peration 'ame !perator

()planation Less than o!erator Greater than o!erator Less than or e3ual to o!erator Greater than or e3ual to o!erator )3uality o!erator /ot e3ual o!erator Both o!erands 'rue $or result to be 'rue One or the other o!erand is 'rue $or the result to be 'rue

Q greater than J less than or e3ual QP greater than or e3ual JP e3ual PP not e3ual RP logical and and logical or or
less than logical not

/egates the truth value, 6alse becomes 'rue, 'rue becomes 6alse Relational and Logical O!erators

not

1 2 4 ! print(!++10) print(10 > !) print((! >+ 1) and (! ,+ 10))

-introO9.

Identi$iers are used in !rogramming languages as names= In %ython, identi$iers start #ith a letter or an underscore -O., are case sensitive, and can be o$ any length= Remember that it is al#ays a good idea to use names that convey meaning so that your !rogram code is easier to read and understand= + %ython variable is created #hen a name is used $or the $irst time on the le$t4hand side o$ an assignment statement= +ssignment statements !rovide a #ay to associate a name #ith a value= 'he variable #ill hold a re$erence to a !iece o$ data and not the data itsel$= Consider the $ollo#ing session0
1 >>> theSum + 0 2 >>> theSum 0

29

4 ! 6 " # $

>>> theSum + theSum % 1 >>> theSum 1 >>> theSum + )rue >>> theSum )rue

'he assignment statement theSum P G creates a variable called theSum and lets it hold the re$erence to the data object G -see Figure 3.= In general, the right4hand side o$ the assignment statement is evaluated and a re$erence to the resulting data object is ?assigned@ to the name on the le$t4hand side= +t this !oint in our e*am!le, the ty!e o$ the variable is integer as that is the ty!e o$ the data currently being re$erred to by thesum= I$ the ty!e o$ the data changes -see Figure 4., as sho#n above #ith the boolean value 'rue, so does the ty!e o$ the variable -thesum is no# o$ the ty!e boolean.= 'he assignment statement changes the re$erence being held by the variable= 'his is a dynamic characteristic o$ %ython= 'he same variable can re$er to many di$$erent ty!es o$ data=

7ariables 1old Re$erences to Data Objects

+ssignment Changes the Re$erence

Built&in #ollection Data Types


In addition to the numeric and boolean classes, %ython has a number o$ very !o#er$ul built4in collection classes= Lists, strings, and tu!les are ordered collections that are very similar in general structure but have s!eci$ic di$$erences that must be understood $or them to be used !ro!erly= Sets and dictionaries are unordered collections= + list is an ordered collection o$ 8ero or more re$erences to %ython data objects= Lists are #ritten as comma4delimited values enclosed in s3uare brac,ets= 'he em!ty list is sim!ly S T= Lists are heterogeneous, meaning that the data objects need not all be $rom the same class and

2;

the collection can be assigned to a variable as belo#= 'he $ollo#ing $ragment sho#s a variety o$ %ython data objects in a list=
1 >>> -1. .)rue.6.!/ 2 -1. . )rue. 6.!/ >>> m01ist + -1. .)rue.6.!/ 4 >>> m01ist ! -1. . )rue. 6.!/

/ote that #hen %ython evaluates a list, the list itsel$ is returned= 1o#ever, in order to remember the list $or later !rocessing, its re$erence needs to be assigned to a variable= Since lists are considered to be se3uentially ordered, they su!!ort a number o$ o!erations that can be a!!lied to any %ython se3uence= Table 2 revie#s these o!erations and the $ollo#ing session gives e*am!les o$ their use= !peration 'ame !perator inde*ing concatenation re!etition membershi! length ST K L in len ()planation +ccess an element o$ a se3uence Combine se3uences together Concatenate a re!eated number o$ times +s, #hether an item is in a se3uence +s, the number o$ items in the se3uence

slicing S0T )*tract a !art o$ a se3uence O!erations on +ny Se3uence in %ython /ote that the indices $or lists -se3uences. start counting #ith G= 'he slice o!eration, myListS20;T, returns a list o$ items starting #ith the item inde*ed by 2 u! to but not including the item inde*ed by ;= Sometimes, you #ill #ant to initiali8e a list= 'his can 3uic,ly be accom!lished by using re!etition= 6or e*am!le,
>>> m01ist + -0/ & 6 >>> m01ist -0. 0. 0. 0. 0. 0/

One very im!ortant aside relating to the re!etition o!erator is that the result is a re!etition o$ re$erences to the data objects in the se3uence= 'his can best be seen by considering the $ollo#ing session0

1 2 4 !

2<

6 " m01ist + -1.2. .4/ A + -m01ist/& print(A) m01ist-2/+4! print(A)

-introO;.

'he variable + holds a collection o$ three re$erences to the original list called myList= /ote that a change to one element o$ myList sho#s u! in all three occurrences in += Lists su!!ort a number o$ methods that #ill be used to build data structures= Table 3 !rovides a summary= )*am!les o$ their use $ollo#= *ethod 'ame a!!end insert !o! !o! sort reverse del inde* count +se ()planation

alist=a!!end-item. +dds a ne# item to the end o$ a list alist=insert-i,item. Inserts an item at the ith !osition in a list alist=!o!-. alist=!o!-i. alist=sort-. alist=reverse-. del alistSiT alist=inde*-item. alist=count-item. Removes and returns the last item in a list Removes and returns the ith item in a list Modi$ies a list to be sorted Modi$ies a list to be in reverse order Deletes the item in the ith !osition Returns the inde* o$ the $irst occurrence o$ item Returns the number o$ occurrences o$ item

remove alist=remove-item. Removes the $irst occurrence o$ item Methods %rovided by Lists in %ython

1 2 4 ! 6 " # $ 10 11

2B

12 1 14 1! 16 1" 1# 1$ 20 21 22 2 m01ist + -1024. . )rue. 6.!/ m01ist.append(*alse) print(m01ist) m01ist.insert(2.4.!) print(m01ist) print(m01ist.pop()) print(m01ist) print(m01ist.pop(1)) print(m01ist) m01ist.pop(2) print(m01ist) m01ist.sort() print(m01ist) m01ist.re2erse() print(m01ist) print(m01ist.count(6.!)) print(m01ist.inde3(4.!)) m01ist.remo2e(6.!) print(m01ist) del m01ist-0/ print(m01ist)

-introOB.

>ou can see that some o$ the methods, such as !o!, return a value and also modi$y the list= Others, such as reverse, sim!ly modi$y the list #ith no return value= !o! #ill de$ault to the end o$ the list but can also remove and return a s!eci$ic item= 'he inde* range starting $rom G is again used $or these methods= >ou should also notice the $amiliar ?dot@ notation $or as,ing an object to invo,e a method= myList=a!!end-6alse. can be read as ?as, the object myList to !er$orm its a!!end method and send it the value 6alse=@ )ven sim!le data objects such as integers can invo,e methods in this #ay=
>>> (!4).44add44(21) "! >>>

In this $ragment #e are as,ing the integer object B< to e*ecute its add method -called OOaddOO in %ython. and !assing it 92 as the value to add= 'he result is the sum, DB= O$ course,

2C

#e usually #rite this as B<K92= section=

e #ill say much more about these methods later in this

One common %ython $unction that is o$ten discussed in conjunction #ith lists is the range $unction= range !roduces a range object that re!resents a se3uence o$ values= By using the list $unction, it is !ossible to see the value o$ the range object as a list= 'his is illustrated belo#=
1 >>> range(10) 2 range(0. 10) >>> list(range(10)) 4 -0. 1. 2. . 4. !. 6. ". #. $/ ! >>> range(!.10) 6 range(!. 10) " >>> list(range(!.10)) # -!. 6. ". #. $/ $ >>> list(range(!.10.2)) 10 -!. ". $/ 11 >>> list(range(10.1.51)) 12 -10. $. #. ". 6. !. 4. . 2/ 1 >>>

'he range object re!resents a se3uence o$ integers= By de$ault, it #ill start #ith G= I$ you !rovide more !arameters, it #ill start and end at !articular !oints and can even s,i! items= In our $irst e*am!le, range-2G., the se3uence starts #ith G and goes u! to but does not include 2G= In our second e*am!le, range-B,2G. starts at B and goes u! to but not including 2G= range-B,2G,9. !er$orms similarly but s,i!s by t#os -again, 2G is not included.= Strings are se3uential collections o$ 8ero or more letters, numbers and other symbols= call these letters, numbers and other symbols characters= Literal string values are di$$erentiated $rom identi$iers by using 3uotation mar,s -either single or double.=
1 >>> "Da2id" 2 6Da2id6 >>> m07ame + "Da2id" 4 >>> m07ame- / ! 6i6 6 >>> m07ame&2 " 6Da2idDa2id6 # >>> len(m07ame) $! 10 >>>

Since strings are se3uences, all o$ the se3uence o!erations described above #or, as you #ould e*!ect= In addition, strings have a number o$ methods, some o$ #hich are sho#n in Table 4= 6or e*am!le,
1 >>> m07ame 2 6Da2id6 >>> m07ame.upper() 4 6DA89D6 ! >>> m07ame.center(10) 6 6 Da2id 6 " >>> m07ame.:ind(626) #2 $ >>> m07ame.split(626) 10 -6Da6. 6id6/

2D

O$ these, s!lit #ill be very use$ul $or !rocessing data= s!lit #ill ta,e a string and return a list o$ strings using the s!lit character as a division !oint= In the e*am!le, v is the division !oint= I$ no division is s!eci$ied, the s!lit method loo,s $or #hites!ace characters such as tab, ne#line and s!ace= *ethod 'ame center count ljust lo#er rjust $ind +se astring=center-#. astring=ljust-#. astring=lo#er-. astring=rjust-#. astring=$ind-item. ()planation Returns a string centered in a $ield o$ si8e # Returns a string le$t4justi$ied in a $ield o$ si8e # Returns a string in all lo#ercase Returns a string right4justi$ied in a $ield o$ si8e # Returns the inde* o$ the $irst occurrence o$ item

astring=count-item. Returns the number o$ occurrences o$ item in the string

s!lit astring=s!lit-schar. S!lits a string into substrings at schar Methods %rovided by Strings in %ython + major di$$erence bet#een lists and strings is that lists can be modi$ied #hile strings cannot= 'his is re$erred to as mutability= Lists are mutableU strings are immutable= 6or e*am!le, you can change an item in a list by using inde*ing and assignment= ith a string that change is not allo#ed=
1 >>> m01ist 2 -1. . )rue. 6.!/ >>> m01ist-0/+2&&10 4 >>> m01ist ! -1024. . )rue. 6.!/ 6 >>> " >>> m07ame # 6Da2id6 $ >>> m07ame-0/+6;6 10 11 )race<ac= (most recent call last)> 12 *ile ",p0shell?#4>". line 1. in 5tople2el5 1 m07ame-0/+6;6 14 )0pe@rror> o<Aect doesn6t support item assignment 1! >>>

'u!les are very similar to lists in that they are heterogeneous se3uences o$ data= 'he di$$erence is that a tu!le is immutable, li,e a string= + tu!le cannot be changed= 'u!les are #ritten as comma4delimited values enclosed in !arentheses= +s se3uences, they can use any o!eration described above= 6or e*am!le,
1 >>> m0)uple + (2.)rue.4.$6) 2 >>> m0)uple (2. )rue. 4.$6) 4 >>> len(m0)uple) ! 6 >>> m0)uple-0/ "2 # >>> m0)uple & $ (2. )rue. 4.$6. 2. )rue. 4.$6. 2. )rue. 4.$6) 10 >>> m0)uple-0>2/

2F

11 (2. )rue) 12 >>>

1o#ever, i$ you try to change an item in a tu!le, you #ill get an error= /ote that the error message !rovides location and reason $or the !roblem=
1 >>> m0)uple-1/+*alse 2 )race<ac= (most recent call last)> 4 *ile ",p0shell?1 ">". line 1. in 5tople2el5 ! m0)uple-1/+*alse 6 )0pe@rror> o<Aect doesn6t support item assignment " >>>

+ set is an unordered collection o$ 8ero or more immutable %ython data objects= Sets do not allo# du!licates and are #ritten as comma4delimited values enclosed in curly braces= 'he em!ty set is re!resented by set-.= Sets are heterogeneous, and the collection can be assigned to a variable as belo#=
1 >>> B .6."cat".4.!.*alseC 2 B*alse. 4.!. . 6. 6cat6C >>> m0Set + B .6."cat".4.!.*alseC 4 >>> m0Set ! B*alse. 4.!. . 6. 6cat6C 6 >>>

)ven though sets are not considered to be se3uential, they do su!!ort a $e# o$ the $amiliar o!erations !resented earlier= Table 5 revie#s these o!erations and the $ollo#ing session gives e*am!les o$ their use= !peration 'ame membershi! length V W 4 QP in len !perator Set membershi! Returns the cardinality o$ the set Returns a ne# set #ith only those elements common to both sets Returns a ne# set #ith all items $rom the $irst set not in second +s,s #hether all elements o$ the $irst set are in the second ()planation

aset V otherset Returns a ne# set #ith all elements $rom both sets aset W otherset aset 4 otherset

aset QP otherset O!erations on a Set in %ython

1 >>> m0Set 2 B*alse. 4.!. . 6. 6cat6C >>> len(m0Set) 4! ! >>> *alse in m0Set 6 )rue " >>> "dog" in m0Set # *alse $ >>>

2E

Sets su!!ort a number o$ methods that should be $amiliar to those #ho have #or,ed #ith them in a mathematics setting= Table 6 !rovides a summary= )*am!les o$ their use $ollo#= /ote that union, intersection, issubset, and di$$erence all have o!erators that can be used as #ell= *ethod 'ame union intersection di$$erence issubset add remove !o! +se aset=union-otherset. aset=intersection-otherset. aset=di$$erence-otherset. aset=issubset-otherset. aset=add-item. aset=remove-item. aset=!o!-. ()planation Returns a ne# set #ith all elements $rom both sets Returns a ne# set #ith only those elements common to both sets Returns a ne# set #ith all items $rom $irst set not in second +s,s #hether all elements o$ one set are in the other +dds item to the set Removes item $rom the set Removes an arbitrary element $rom the set Removes all elements $rom the set

clear aset=clear-. Methods %rovided by Sets in %ython

1 >>> m0Set 2 B*alse. 4.!. . 6. 6cat6C >>> 0ourSet + B$$. .100C 4 >>> m0Set.union(0ourSet) ! B*alse. 4.!. . 100. 6. 6cat6. $$C 6 >>> m0Set D 0ourSet " B*alse. 4.!. . 100. 6. 6cat6. $$C # >>> m0Set.intersection(0ourSet) $B C 10 >>> m0Set E 0ourSet 11 B C 12 >>> m0Set.di::erence(0ourSet) 1 B*alse. 4.!. 6. 6cat6C 14 >>> m0Set 5 0ourSet 1! B*alse. 4.!. 6. 6cat6C 16 >>> B .100C.issu<set(0ourSet) 1" )rue 1# >>> B .100C,+0ourSet 1$ )rue 20 >>> m0Set.add("house") 21 >>> m0Set 22 B*alse. 4.!. . 6. 6house6. 6cat6C 2 >>> m0Set.remo2e(4.!) 24 >>> m0Set 2! B*alse. . 6. 6house6. 6cat6C 26 >>> m0Set.pop() 2" *alse 2# >>> m0Set 2$ B . 6. 6house6. 6cat6C 0 >>> m0Set.clear() 1 >>> m0Set 2 set() >>>

9G

Our $inal %ython collection is an unordered structure called a dictionary= Dictionaries are collections o$ associated !airs o$ items #here each !air consists o$ a ,ey and a value= 'his ,ey4value !air is ty!ically #ritten as ,ey0value= Dictionaries are #ritten as comma4delimited ,ey0value !airs enclosed in curly braces= 6or e*am!le,
>>> capitals + B69oFa6>6DesGoines6.6Hisconsin6>6Gadison6C >>> capitals B6Hisconsin6> 6Gadison6. 69oFa6> 6DesGoines6C >>>

e can mani!ulate a dictionary by accessing a value via its ,ey or by adding another ,ey4 value !air= 'he synta* $or access loo,s much li,e a se3uence access e*ce!t that instead o$ using the inde* o$ the item #e use the ,ey value= 'o add a ne# value is similar=

1 2 4 ! 6 " # $ 10 capitals + B69oFa6>6DesGoines6.6Hisconsin6>6Gadison6C print(capitals-69oFa6/) capitals-6Itah6/+6Salt1a=eJit06 print(capitals) capitals-6Jali:ornia6/+6Sacramento6 print(len(capitals)) :or = in capitals> print(capitals-=/." is the capital o: ". =)

-introOD.

It is im!ortant to note that the dictionary is maintained in no !articular order #ith res!ect to the ,eys= 'he $irst !air added -X5tahX0 XSaltLa,eCityX. #as !laced $irst in the dictionary and the second !air added -XCali$orniaX0 XSacramentoX. #as !laced last= 'he !lacement o$ a ,ey is de!endent on the idea o$ ?hashing,@ #hich #ill be e*!lained in more detail in Cha!ter <= e also sho# the length $unction !er$orming the same role as #ith !revious collections= Dictionaries have both methods and o!erators= Table x and Table x describe them, and the sessions sho#s them in action= 'he ,eys, values, and items methods all return objects that contain the values o$ interest= >ou can use the list $unction to convert them to lists= >ou #ill 92

also see that there are t#o variations on the get method= I$ the ,ey is not !resent in the dictionary, get #ill return /one= 1o#ever, a second, o!tional !arameter can s!eci$y a return value instead= !perator ST in +se myDictS,T ()planation Returns the value associated #ith ,, other#ise its an error

,ey in adict Returns 'rue i$ ,ey is in the dictionary, 6alse other#ise

del del adictS,eyT Removes the entry $rom the dictionary O!erators %rovided by Dictionaries in %ython
1 2 4 ! 6 " # $ 10 11 12 1 14 1! 16 1" 1# 1$ >>> phonee3t+B6da2id6>1410.6<rad6>11 "C >>> phonee3t B6<rad6> 11 ". 6da2id6> 1410C >>> phonee3t.=e0s() dict4=e0s(-6<rad6. 6da2id6/) >>> list(phonee3t.=e0s()) -6<rad6. 6da2id6/ >>> phonee3t.2alues() dict42alues(-11 ". 1410/) >>> list(phonee3t.2alues()) -11 ". 1410/ >>> phonee3t.items() dict4items(-(6<rad6. 11 "). (6da2id6. 1410)/) >>> list(phonee3t.items()) -(6<rad6. 11 "). (6da2id6. 1410)/ >>> phonee3t.get("=ent") >>> phonee3t.get("=ent"."7K @7)LM") 67K @7)LM6 >>>

*ethod 'ame ,eys values items get get adict=,eys-. adict=values-. adict=items-. adict=get-,. adict=get-,,alt.

+se

()planation Returns the ,eys o$ the dictionary in a dictO,eys object Returns the values o$ the dictionary in a dictOvalues object Returns the ,ey4value !airs in a dictOitems object Returns the value associated #ith ,, /one other#ise

Returns the value associated #ith ,, alt other#ise HMethods %rovided by Dictionaries in %ythonI HdictmethodsI

Input and Output


e o$ten have a need to interact #ith users, either to get data or to !rovide some sort o$ result= Most !rograms today use a dialog bco* as a #ay o$ as,ing the user to !rovide some ty!e o$ in!ut= hile %ython does have a #ay to create dialog bo*es, there is a much sim!ler $unction that #e can use= %ython !rovides us #ith a $unction that allo#s us to as, a user to

99

enter some data and returns a re$erence to the data in the $orm o$ a string= 'he $unction is called in!ut= %ython:s in!ut $unction ta,es a single !arameter that is a string= 'his string is o$ten called the HpromptI because it contains some hel!$ul te*t !rom!ting the user to enter something= 6or e*am!le, you might call in!ut as $ollo#s0
a7ame + input(6Nlease enter 0our name> 6)

/o# #hatever the user ty!es a$ter the !rom!t #ill be stored in the a/ame variable= 5sing the in!ut $unction, #e can easily #rite instructions that #ill !rom!t the user to enter data and then incor!orate that data into $urther !rocessing= 6or e*am!le, in the $ollo#ing t#o statements, the $irst as,s the user $or their name and the second !rints the result o$ some sim!le !rocessing based on the string that is !rovided=

1 2 4 ! a7ame + input("Nlease enter 0our name ") print("Mour name in all capitals is ".a7ame.upper(). "and has length". len(a7ame))

-strstu$$.

It is im!ortant to note that the value returned $rom the in!ut $unction #ill be a string re!resenting the e*act characters that #ere entered a$ter the !rom!t= I$ you #ant this string inter!reted as another ty!e, you must !rovide the ty!e conversion e*!licitly= In the statements belo#, the string that is entered by the user is converted to a $loat so that it can be used in $urther arithmetic !rocessing=
sradius + input("Nlease enter the radius o: the circle ") radius + :loat(sradius) diameter + 2 & radius

String ,ormatting
e have already seen that the !rint $unction !rovides a very sim!le #ay to out!ut values $rom a %ython !rogram= !rint ta,es 8ero or more !arameters and dis!lays them using a single blan, as the de$ault se!arator= It is !ossible to change the se!arator character by setting the se! argument= In addition, each !rint ends #ith a ne#line character by de$ault= 'his behavior

9;

can be changed by setting the end argument= 'hese variations are sho#n in the $ollo#ing session0
1 >>> print("Oello") 2 Oello >>> print("Oello"."Horld") 4 Oello Horld ! >>> print("Oello"."Horld". sep+"&&&") 6 Oello&&&Horld " >>> print("Oello"."Horld". end+"&&&") # Oello Horld&&&>>>

It is o$ten use$ul to have more control over the loo, o$ your out!ut= 6ortunately, %ython !rovides us #ith an alternative called %ormatted strings= + $ormatted string is a tem!late in #hich #ords or s!aces that #ill remain constant are combined #ith !laceholders $or variables that #ill be inserted into the string= 6or e*am!le, the statement
print(a7ame. "is". age. "0ears old.")

contains the #ords is and years old, but the name and the age #ill change de!ending on the variable values at the time o$ e*ecution= 5sing a $ormatted string, #e #rite the !revious statement as
print("(s is (d 0ears old." ( (a7ame. age))

'his sim!le e*am!le illustrates a ne# string e*!ression= 'he N o!erator is a string o!erator called the %ormat operator= 'he le$t side o$ the e*!ression holds the tem!late or $ormat string, and the right side holds a collection o$ values that #ill be substituted into the $ormat string= /ote that the number o$ values in the collection on the right side corres!onds #ith the number o$ N characters in the $ormat string= 7alues are ta,enYin order, le$t to rightY$rom the collection and inserted into the $ormat string= Let:s loo, at both sides o$ this $ormatting e*!ression in more detail= 'he $ormat string may contain one or more conversion s!eci$ications= + conversion character tells the $ormat o!erator #hat ty!e o$ value is going to be inserted into that !osition in the string= In the e*am!le above, the Ns s!eci$ies a string, #hile the Nd s!eci$ies an integer= Other !ossible ty!e s!eci$ications include i, u, $, e, g, c, or N= Table 7 summari8es all o$ the various ty!e s!eci$ications= #haracter d,ZZiZZ u $ e ) g c s Integer 5nsigned integer 6loating !oint as m=ddddd 6loating !oint as m=dddddeKM4** 6loating !oint as m=ddddd)KM4** 5se Ne $or e*!onents less than [< or greater than KB, other#ise use N$ Single character String, or any %ython data object that can be converted to a string by using the str !utput ,ormat

9<

#haracter $unction= N Insert a literal N character String 6ormatting Conversion Characters

!utput ,ormat

In addition to the $ormat character, you can also include a $ormat modi$ier bet#een the N and the $ormat character= 6ormat modi$iers may be used to le$t4justi$y or right4justi$iy the value #ith a s!eci$ied $ield #idth= Modi$iers can also be used to s!eci$y the $ield #idth along #ith a number o$ digits a$ter the decimal !oint= Table 8 e*!lains these $ormat modi$iers *odi%ier ()ample number

Description %ut the value in a $ield #idth o$ 9G %ut the value in a $ield 9G characters #ide, le$t4justi$ied %ut the value in a $ield 9G characters #ide, right4justi$ied %ut the value in a $ield 9G characters #ide, $ill in #ith leading 8eros= %ut the value in a $ield 9G characters #ide #ith 9 characters to the right o$ the decimal !oint=

N9Gd N49Gd NK9Gd NG9Gd N9G=9$

G =

-name. N-name.d Get the value $rom the su!!lied dictionary using name as the ,ey= +dditional $ormatting o!tions 'he right side o$ the $ormat o!erator is a collection o$ values that #ill be inserted into the $ormat string= 'he collection #ill be either a tu!le or a dictionary= I$ the collection is a tu!le, the values are inserted in order o$ !osition= 'hat is, the $irst element in the tu!le corres!onds to the $irst $ormat character in the $ormat string= I$ the collection is a dictionary, the values are inserted according to their ,eys= In this case all $ormat characters must use the -name. modi$ier to s!eci$y the name o$ the ,ey=
1 >>> price + 24 2 >>> item + "<anana" >>> print(")he (s costs (d cents"((item.price)) 4 )he <anana costs 24 cents ! >>> print(")he (%10s costs (!.2: cents"((item.price)) 6 )he <anana costs 24.00 cents " >>> print(")he (%10s costs (10.2: cents"((item.price)) # )he <anana costs 24.00 cents $ >>> itemdict + B"item">"<anana"."cost">24C 10 >>> print(")he ((item)s costs ((cost)".1: cents"(itemdict) 11 )he <anana costs 24.0 cents 12 >>>

In addition to $ormat strings that use $ormat characters and $ormat modi$iers, %ython strings also include a $ormat method that can be used in conjunction #ith a ne# 6ormatter class to im!lement com!le* string $ormatting= More about these $eatures can be $ound in the %ython library re$erence manual=

9B

Control Structures
+s #e noted earlier, algorithms re3uire t#o im!ortant control structures0 iteration and selection= Both o$ these are su!!orted by %ython in various $orms= 'he !rogrammer can choose the statement that is most use$ul $or the given circumstance= 6or iteration, %ython !rovides a standard #hile statement and a very !o#er$ul $or statement= 'he #hile statement re!eats a body o$ code as long as a condition is true= 6or e*am!le,
1 >>> counter + 1 2 >>> Fhile counter ,+ !> ... print("Oello. Forld") 4 ... counter + counter % 1 ! 6 " Oello. Forld # Oello. Forld $ Oello. Forld 10 Oello. Forld 11 Oello. Forld

!rints out the !hrase ?1ello, #orld@ $ive times= 'he condition on the #hile statement is evaluated at the start o$ each re!etition= I$ the condition is 'rue, the body o$ the statement #ill e*ecute= It is easy to see the structure o$ a %ython #hile statement due to the mandatory indentation !attern that the language en$orces= 'he #hile statement is a very general !ur!ose iterative structure that #e #ill use in a number o$ di$$erent algorithms= In many cases, a com!ound condition #ill control the iteration= + $ragment such as
Fhile counter ,+ 10 and not done> ...

#ould cause the body o$ the statement to be e*ecuted only in the case #here both !arts o$ the condition are satis$ied= 'he value o$ the variable counter #ould need to be less than or e3ual to 2G and the value o$ the variable done #ould need to be 6alse -not 6alse is 'rue. so that 'rue and 'rue results in 'rue= )ven though this ty!e o$ construct is very use$ul in a #ide variety o$ situations, another iterative structure, the $or statement, can be used in conjunction #ith many o$ the %ython collections= 'he $or statement can be used to iterate over the members o$ a collection, so long as the collection is a se3uence= So, $or e*am!le,
1 >>> :or item in -1. .6.2.!/> 2 ... print(item) ... 41 ! 66 "2 #!

9C

assigns the variable item to be each successive value in the list S2,;,C,9,BT= 'he body o$ the iteration is then e*ecuted= 'his #or,s $or any collection that is a se3uence -lists, tu!les, and strings.= + common use o$ the $or statement is to im!lement de$inite iteration over a range o$ values= 'he statement
1 >>> :or item in range(!)> 2 ... print(item&&2) ... 40 !1 64 "$ # 16 $ >>>

#ill !er$orm the !rint $unction $ive times= 'he range $unction #ill return a range object re!resenting the se3uence G,2,9,;,< and each value #ill be assigned to the variable item= 'his value is then s3uared and !rinted= 'he other very use$ul version o$ this iteration structure is used to !rocess each character o$ a string= 'he $ollo#ing code $ragment iterates over a list o$ strings and $or each string !rocesses each character by a!!ending it to a list= 'he result is a list o$ all the letters in all o$ the #ords=

1 2 4 ! 6 " # Fordlist + -6cat6.6dog6.6ra<<it6/ letterlist + - / :or aFord in Fordlist> :or aletter in aFord> letterlist.append(aletter) print(letterlist)

-introOF.

Selection statements allo# !rogrammers to as, 3uestions and then, based on the result, !er$orm di$$erent actions= Most !rogramming languages !rovide t#o versions o$ this use$ul

9D

construct0 the i$else and the i$= + sim!le e*am!le o$ a binary selection uses the i$else statement=
i: n,0> print("Sorr0. 2alue is negati2e") else> print(math.sqrt(n))

In this e*am!le, the object re$erred to by n is chec,ed to see i$ it is less than 8ero= I$ it is, a message is !rinted stating that it is negative= I$ it is not, the statement !er$orms the else clause and com!utes the s3uare root= Selection constructs, as #ith any control construct, can be nested so that the result o$ one 3uestion hel!s decide #hether to as, the ne*t= 6or e*am!le, assume that score is a variable holding a re$erence to a score $or a com!uter science test=
i: score >+ $0> print(6A6) else> i: score >+#0> print(6P6) else i: score >+ "0> print(6J6) else> i: score >+ 60> print(6D6) else> print(6*6)

'his $ragment #ill classi$y a value called score by !rinting the letter grade earned= I$ the score is greater than or e3ual to EG, the statement #ill !rint += I$ it is not -else., the ne*t 3uestion is as,ed= I$ the score is greater than or e3ual to FG then it must be bet#een FG and FE since the ans#er to the $irst 3uestion #as $alse= In this case !rint B is !rinted= >ou can see that the %ython indentation !attern hel!s to ma,e sense o$ the association bet#een i$ and else #ithout re3uiring any additional syntactic elements= +n alternative synta* $or this ty!e o$ nested selection uses the eli$ ,ey#ord= 'he else and the ne*t i$ are combined so as to eliminate the need $or additional nesting levels= /ote that the $inal else is still necessary to !rovide the de$ault case i$ all other conditions $ail=
1 i: score >+ $0> 2 print(6A6) eli: score >+#0> 4 print(6P6) ! eli: score >+ "0> 6 print(6J6) " eli: score >+ 60> # print(6D6) $ else> 10 print(6*6)

%ython also has a single #ay selection construct, the i$ statement= ith this statement, i$ the condition is true, an action is !er$ormed= In the case #here the condition is $alse, !rocessing sim!ly continues on to the ne*t statement a$ter the i$= 6or e*am!le, the $ollo#ing $ragment 9F

#ill $irst chec, to see i$ the value o$ a variable n is negative= I$ it is, then it is modi$ied by the absolute value $unction= Regardless, the ne*t action is to com!ute the s3uare root=
i: n,0> n + a<s(n) print(math.sqrt(n))

Sel$ Chec, 'est your understanding o$ #hat #e have covered so $ar by trying the $ollo#ing e*ercise= Modi$y the code $rom activecodeOD so that the $inal list only contains a single co!y o$ each letter=

1 2 ? the ansFer is> -6c6. 6a6. 6t6. 6d6. 6o6. 6g6. 6r6. 6<6. 6i6/

-sel$Ochec,O2.

Returning to lists, there is an alternative method $or creating a list that uses iteration and selection constructs= 'he is ,no#n as a list comprehension= + list com!rehension allo#s you to easily create a list based on some !rocessing or selection criteria= 6or e*am!le, i$ #e #ould li,e to create a list o$ the $irst 2G !er$ect s3uares, #e could use a $or statement0
1 >>> sqlist+-/ 2 >>> :or 3 in range(1.11)> sqlist.append(3&3) 4 ! >>> sqlist 6 -1. 4. $. 16. 2!. 6. 4$. 64. #1. 100/ " >>>

5sing a list com!rehension, #e can do this in one ste! as

9E

>>> sqlist+-3&3 :or 3 in range(1.11)/ >>> sqlist -1. 4. $. 16. 2!. 6. 4$. 64. #1. 100/ >>>

'he variable * ta,es on the values 2 through 2G as s!eci$ied by the $or construct= 'he value o$ *L* is then com!uted and added to the list that is being constructed= 'he general synta* $or a list com!rehension also allo#s a selection criteria to be added so that only certain items get added= 6or e*am!le,
>>> sqlist+-3&3 :or 3 in range(1.11) i: 3(2 Q+ 0/ >>> sqlist -1. $. 2!. 4$. #1/ >>>

'his list com!rehension constructed a list that only contained the s3uares o$ the odd numbers in the range $rom 2 to 2G= +ny se3uence that su!!orts iteration can be used #ithin a list com!rehension to construct a ne# list=
>>>-ch.upper() :or ch in 6comprehension6 i: ch not in 6aeiou6/ -6J6. 6G6. 6N6. 6L6. 6O6. 676. 6S6. 676/ >>>

Sel$ Chec, 'est your understanding o$ list com!rehensions by redoing activecode D using list com!rehensions= 6or e*tra bonus !oints see i$ you can $igure out ho# to remove the du!licates using com!rehensions too=

1 2 ? the ansFer is> -6c6. 6a6. 6t6. 6d6. 6o6. 6g6. 6r6. 6a6. 6<6. 6<6. 6i6. 6t6/

-sel$Ochec,O9.

;G

!ception "andling
'here are t#o ty!es o$ errors that ty!ically occur #hen #riting !rograms= 'he $irst, ,no#n as a synta* error, sim!ly means that the !rogrammer has made a mista,e in the structure o$ a statement or e*!ression= 6or e*am!le, it is incorrect to #rite a $or statement and $orget the colon=
>>> :or i in range(10) S0nta3@rror> in2alid s0nta3 (,p0shell?61>. line 1)

In this case, the %ython inter!reter has $ound that it cannot com!lete the !rocessing o$ this instruction since it does not con$orm to the rules o$ the language= Synta* errors are usually more $re3uent #hen you are $irst learning a language= 'he other ty!e o$ error, ,no#n as a logic error, denotes a situation #here the !rogram e*ecutes but gives the #rong result= 'his can be due to an error in the underlying algorithm or an error in your translation o$ that algorithm= In some cases, logic errors lead to very bad situations such as trying to divide by 8ero or trying to access an item in a list #here the inde* o$ the item is outside the bounds o$ the list= In this case, the logic error leads to a runtime error that causes the !rogram to terminate= 'hese ty!es o$ runtime errors are ty!ically called e)ceptions= Most o$ the time, beginning !rogrammers sim!ly thin, o$ e*ce!tions as $atal runtime errors that cause the end o$ e*ecution= 1o#ever, most !rogramming languages !rovide a #ay to deal #ith these errors that #ill allo# the !rogrammer to have some ty!e o$ intervention i$ they so choose= In addition, !rogrammers can create their o#n e*ce!tions i$ they detect a situation in the !rogram e*ecution that #arrants it= hen an e*ce!tion occurs, #e say that it has been ?raised=@ >ou can ?handle@ the e*ce!tion that has been raised by using a try statement= 6or e*am!le, consider the $ollo#ing session that as,s the user $or an integer and then calls the s3uare root $unction $rom the math library= I$ the user enters a value that is greater than or e3ual to G, the !rint #ill sho# the s3uare root= 1o#ever, i$ the user enters a negative value, the s3uare root $unction #ill re!ort a 7alue)rror e*ce!tion=
1 >>> anum<er + int(input("Nlease enter an integer ")) 2 Nlease enter an integer 52 >>> print(math.sqrt(anum<er)) 4 )race<ac= (most recent call last)>

;2

! *ile ",p0shell?102>". line 1. in ,module> 6 print(math.sqrt(anum<er)) " 8alue@rror> math domain error # >>>

e can handle this e*ce!tion by calling the !rint $unction $rom #ithin a try bloc,= + corres!onding e*ce!t bloc, ?catches@ the e*ce!tion and !rints a message bac, to the user in the event that an e*ce!tion occurs= 6or e*am!le0
1 >>> tr0> 2 print(math.sqrt(anum<er)) e3cept> 4 print("Pad 8alue :or square root") ! print("Ising a<solute 2alue instead") 6 print(math.sqrt(a<s(anum<er))) " # Pad 8alue :or square root $ Ising a<solute 2alue instead 10 4."$!# 1!2 1 11 >>>

#ill catch the $act that an e*ce!tion is raised by s3rt and #ill instead !rint the messages bac, to the user and use the absolute value to be sure that #e are ta,ing the s3uare root o$ a non4 negative number= 'his means that the !rogram #ill not terminate but instead #ill continue on to the ne*t statements= It is also !ossible $or a !rogrammer to cause a runtime e*ce!tion by using the raise statement= 6or e*am!le, instead o$ calling the s3uare root $unction #ith a negative number, #e could have chec,ed the value $irst and then raised our o#n e*ce!tion= 'he code $ragment belo# sho#s the result o$ creating a ne# Runtime)rror e*ce!tion= /ote that the !rogram #ould still terminate but no# the e*ce!tion that caused the termination is something e*!licitly created by the !rogrammer=
1 >>> i: anum<er , 0> 2 ... raise Luntime@rror("Mou can6t use a negati2e num<er") ... else> 4 ... print(math.sqrt(anum<er)) ! ... 6 )race<ac= (most recent call last)> " *ile ",stdin>". line 2. in ,module> # Luntime@rror> Mou can6t use a negati2e num<er $ >>>

'here are many ,inds o$ e*ce!tions that can be raised in addition to the Runtime)rror sho#n above= See the %ython re$erence manual $or a list o$ all the available e*ce!tion ty!es, and $or ho# to create your o#n=

De#ining $unctions
'he earlier e*am!le o$ !rocedural abstraction called u!on a %ython $unction called s3rt $rom the math module to com!ute the s3uare root= In general, #e can hide the details o$ any com!utation by de$ining a $unction= + $unction de$inition re3uires a name, a grou! o$ !arameters, and a body= It may also e*!licitly return a value= 6or e*am!le, the sim!le $unction de$ined belo# returns the s3uare o$ the value you !ass into it= ;9

1 >>> de: square(n)> 2 ... return n&&2 ... 4 >>> square( ) !$ 6 >>> square(square( )) " #1 # >>>

'he synta* $or this $unction de$inition includes the name, s3uare, and a !arenthesi8ed list o$ $ormal !arameters= 6or this $unction, n is the only $ormal !arameter, #hich suggests that s3uare needs only one !iece o$ data to do its #or,= 'he details, hidden ?inside the bo*,@ sim!ly com!ute the result o$ nLL9 and return it= e can invo,e or call the s3uare $unction by as,ing the %ython environment to evaluate it, !assing an actual !arameter value, in this case, ;= /ote that the call to s3uare returns an integer that can in turn be !assed to another invocation= e could im!lement our o#n s3uare root $unction by using a #ell4,no#n techni3ue called ?/e#ton:s Method=@ /e#ton:s Method $or a!!ro*imating s3uare roots !er$orms an iterative com!utation that converges on the correct value= 'he e3uation ne guessP29-oldguessKnoldguess. ta,es a value n and re!eatedly guesses the s3uare root by ma,ing each ne

guess the oldguess in the subse3uent iteration= 'he initial guess used here is n9= !isting 1 sho#s a $unction de$inition that acce!ts a value n and returns the s3uare root o$ n a$ter ma,ing 9G guesses= +gain, the details o$ /e#ton:s Method
are hidden inside the $unction de$inition and the user does not have to ,no# anything about the im!lementation to use the $unction $or its intended !ur!ose= !isting 1 also sho#s the use o$ the \ character as a comment mar,er= +ny characters that $ollo# the \ on a line are ignored=
1 >>>squareroot($) 2 .0 >>>squareroot(4!6 ) 4 6".!4$$#14$!1#6216 ! >>> 1 de: squareroot(n)> 2 root + n'2 ?initial guess Fill <e 1'2 o: n :or = in range(20)> 4 root + (1'2)&(root % (n ' root)) ! 6 return root

Sel$ Chec, 1ere:s a sel$ chec, that really covers everything so $ar= >ou may have heard o$ the in$inite mon,ey theorem" 'he theorem states that a mon,ey hitting ,eys at random on a ty!e#riter ,eyboard $or an in$inite amount o$ time #ill almost surely ty!e a given te*t, such as the com!lete #or,s o$ illiam Sha,es!eare= ell, su!!ose #e re!lace a mon,ey #ith a %ython $unction= 1o# long do you thin, it #ould ta,e $or a %ython $unction to generate just one sentence o$ Sha,es!eare" 'he sentence #e:ll shoot $or is0 ?methin,s it is li,e a #easel@ >ou:re not going to #ant to run this one in the bro#ser, so $ire u! your $avorite %ython ID)= 'he #ay #e:ll simulate this is to #rite a $unction that generates a string that is 9D characters ;;

long by choosing random letters $rom the 9C letters in the al!habet !lus the s!ace= e:ll #rite another $unction that #ill score each generated string by com!aring the randomly generated string to the goal= + third $unction #ill re!eatedly call generate and score, then i$ 2GGN o$ the letters are correct #e are done= I$ the letters are not correct then #e #ill generate a #hole ne# string='o ma,e it easier to $ollo# your !rogram:s !rogress this third $unction should !rint out the best string generated so $ar and its score every 2GGG tries= Sel$ Chec, Challenge See i$ you can im!rove u!on the !rogram in the sel$ chec, by ,ee!ing letters that are correct and only modi$ying one character in the best string so $ar= 'his is a ty!e o$ algorithm in the class o$ ]hill climbing: algorithms, that is #e only ,ee! the result i$ it is better than the !revious one=

Ob%ect&Oriented Programming in Python' De#ining Classes


e stated earlier that %ython is an object4oriented !rogramming language= So $ar, #e have used a number o$ built4in classes to sho# e*am!les o$ data and control structures= One o$ the most !o#er$ul $eatures in an object4oriented !rogramming language is the ability to allo# a !rogrammer -!roblem solver. to create ne# classes that model data that is needed to solve the !roblem= Remember that #e use abstract data ty!es to !rovide the logical descri!tion o$ #hat a data object loo,s li,e -its state. and #hat it can do -its methods.= By building a class that im!lements an abstract data ty!e, a !rogrammer can ta,e advantage o$ the abstraction !rocess and at the same time !rovide the details necessary to actually use the abstraction in a !rogram= henever #e #ant to im!lement an abstract data ty!e, #e #ill do so #ith a ne# class=

A ,raction #lass
+ very common e*am!le to sho# the details o$ im!lementing a user4de$ined class is to construct a class to im!lement the abstract data ty!e 6raction= e have already seen that %ython !rovides a number o$ numeric classes $or our use= 'here are times, ho#ever, that it #ould be most a!!ro!riate to be able to create data objects that ?loo, li,e@ $ractions=

;<

+ $raction such as ;B consists o$ t#o !arts= 'he to! value, ,no#n as the numerator, can be any integer= 'he bottom value, called the denominator, can be any integer greater than G -negative $ractions have a negative numerator.= +lthough it is !ossible to create a $loating !oint a!!ro*imation $or any $raction, in this case #e #ould li,e to re!resent the $raction as an e*act value= 'he o!erations $or the 6raction ty!e #ill allo# a 6raction data object to behave li,e any other numeric value= e need to be able to add, subtract, multi!ly, and divide $ractions= e also #ant to be able to sho# $ractions using the standard ?slash@ $orm, $or e*am!le ;MB= In addition, all $raction methods should return results in their lo#est terms so that no matter #hat com!utation is !er$ormed, #e al#ays end u! #ith the most common $orm= In %ython, #e de$ine a ne# class by !roviding a name and a set o$ method de$initions that are syntactically similar to $unction de$initions= 6or this e*am!le,
class *raction> ?the methods go here

!rovides the $rame#or, $or us to de$ine the methods= 'he $irst method that all classes should !rovide is the constructor= 'he constructor de$ines the #ay in #hich data objects are created= 'o create a 6raction object, #e #ill need to !rovide t#o !ieces o$ data, the numerator and the denominator= In %ython, the constructor method is al#ays called OOinitOO -t#o underscores be$ore and a$ter init. and is sho#n in !isting 2=
1 class *raction> 2 de: 44init44(sel:.top.<ottom)> 4 ! sel:.num + top 6 sel:.den + <ottom

/otice that the $ormal !arameter list contains three items -sel$, to!, bottom.= sel$ is a s!ecial !arameter that #ill al#ays be used as a re$erence bac, to the object itsel$= It must al#ays be the $irst $ormal !arameterU ho#ever, it #ill never be given an actual !arameter value u!on invocation= +s described earlier, $ractions re3uire t#o !ieces o$ state data, the numerator and the denominator= 'he notation sel$=num in the constructor de$ines the $raction object to have an internal data object called num as !art o$ its state= Li,e#ise, sel$=den creates the denominator= 'he values o$ the t#o $ormal !arameters are initially assigned to the state, allo#ing the ne# $raction object to ,no# its starting value= 'o create an instance o$ the 6raction class, #e must invo,e the constructor= 'his ha!!ens by using the name o$ the class and !assing actual values $or the necessary state -note that #e never directly invo,e OOinitOO.= 6or e*am!le,
m0:raction + *raction( .!)

creates an object called my$raction re!resenting the $raction ;B -three4$i$ths.= Figure 5 sho#s this object as it is no# im!lemented=

;B

+n Instance o$ the 6raction Class 'he ne*t thing #e need to do is im!lement the behavior that the abstract data ty!e re3uires= 'o begin, consider #hat ha!!ens #hen #e try to !rint a 6raction object=
>>> m0: + *raction( .!) >>> print(m0:) ,44main44.*raction instance at 0340$<1acc>

'he $raction object, my$, does not ,no# ho# to res!ond to this re3uest to !rint= 'he !rint $unction re3uires that the object convert itsel$ into a string so that the string can be #ritten to the out!ut= 'he only choice my$ has is to sho# the actual re$erence that is stored in the variable -the address itsel$.= 'his is not #hat #e #ant= 'here are t#o #ays #e can solve this !roblem= One is to de$ine a method called sho# that #ill allo# the 6raction object to !rint itsel$ as a string= e can im!lement this method as sho#n in !isting 3= I$ #e create a 6raction object as be$ore, #e can as, it to sho# itsel$, in other #ords, !rint itsel$ in the !ro!er $ormat= 5n$ortunately, this does not #or, in general= In order to ma,e !rinting #or, !ro!erly, #e need to tell the 6raction class ho# to convert itsel$ into a string= 'his is #hat the !rint $unction needs in order to do its job=
de: shoF(sel:)> print(sel:.num."'".sel:.den) 1 >>> m0: + *raction( .!) 2 >>> m0:.shoF() ' ! 4 >>> print(m0:) ! ,44main44.*raction instance at 0340<ce$ac> 6 >>>

In %ython, all classes have a set o$ standard methods that are !rovided but may not #or, !ro!erly= One o$ these, OOstrOO, is the method to convert an object into a string= 'he de$ault im!lementation $or this method is to return the instance address string as #e have already seen= hat #e need to do is !rovide a ?better@ im!lementation $or this method= e #ill say that this im!lementation overrides the !revious one, or that it rede$ines the method:s behavior=

;C

'o do this, #e sim!ly de$ine a method #ith the name OOstrOO and give it a ne# im!lementation as sho#n in !isting 4= 'his de$inition does not need any other in$ormation e*ce!t the s!ecial !arameter sel$= In turn, the method #ill build a string re!resentation by converting each !iece o$ internal state data to a string and then !lacing a M character in bet#een the strings using string concatenation= 'he resulting string #ill be returned any time a 6raction object is as,ed to convert itsel$ to a string= /otice the various #ays that this $unction is used=
de: 44str44(sel:)> return str(sel:.num)%"'"%str(sel:.den) 1 >>> m0: + *raction( .!) 2 >>> print(m0:) '! 4 >>> print("9 ate". m0:. "o: the piRRa") ! 9 ate '! o: the piRRa 6 >>> m0:.44str44() " 6 '!6 # >>> str(m0:) $ 6 '!6 10 >>>

e can override many other methods $or our ne# 6raction class= Some o$ the most im!ortant o$ these are the basic arithmetic o!erations= e #ould li,e to be able to create t#o 6raction objects and then add them together using the standard ?K@ notation= +t this !oint, i$ #e try to add t#o $ractions, #e get the $ollo#ing0
1 >>> :1 + *raction(1.4) 2 >>> :2 + *raction(1.2) >>> :1%:2 4 ! )race<ac= (most recent call last)> 6 *ile ",p0shell?1" >". line 1. in 5tople2el5 " :1%:2 # )0pe@rror> unsupported operand t0pe(s) :or %> $ 6instance6 and 6instance6 10 >>>

I$ you loo, closely at the error, you see that the !roblem is that the ?K@ o!erator does not understand the 6raction o!erands= e can $i* this by !roviding the 6raction class #ith a method that overrides the addition method= In %ython, this method is called OOaddOO and it re3uires t#o !arameters= 'he $irst, sel$, is al#ays needed, and the second re!resents the other o!erand in the e*!ression= 6or e*am!le,
:1.44add44(:2)

#ould as, the 6raction object $2 to add the 6raction object $9 to itsel$= 'his can be #ritten in the standard notation, $2K$9= '#o $ractions must have the same denominator to be added= 'he easiest #ay to ma,e sure they have the same denominator is to sim!ly use the !roduct o$ the t#o denominators as a common denominator so that abKcdPadbdKcbbdPadKcbbd 'he im!lementation is sho#n in

;D

!isting 5= 'he addition $unction returns a ne# 6raction object #ith the numerator and denominator o$ the sum= e can use this method by #riting a standard arithmetic e*!ression involving $ractions, assigning the result o$ the addition, and then !rinting our result= It is also #orth noting that the ^ in line ; is called the continuation character, #hich is necessary #hen a %ython statement is bro,en across more than one line=
1 de: 44add44(sel:.other:raction)> 2 neFnum + sel:.num&other:raction.den % S 4 sel:.den&other:raction.num ! neFden + sel:.den & other:raction.den 6 " return *raction(neFnum.neFden) 1 >>> :1+*raction(1.4) 2 >>> :2+*raction(1.2) >>> : +:1%:2 4 >>> print(: ) ! 6'# 6 >>>

'he addition method #or,s as #e desire, but one thing could be better= /ote that CMF is the correct result -2<K29. but that it is not in the ?lo#est terms@ re!resentation= 'he best re!resentation #ould be ;M<= In order to be sure that our results are al#ays in the lo#est terms, #e need a hel!er $unction that ,no#s ho# to reduce $ractions= 'his $unction #ill need to loo, $or the greatest common divisor, or GCD= e can then divide the numerator and the denominator by the GCD and the result #ill be reduced to lo#est terms= 'he best4,no#n algorithm $or $inding a greatest common divisor is )uclid:s +lgorithm, #hich #ill be discussed in detail in Cha!ter F= )uclid:s +lgorithm states that the greatest common divisor o$ t#o integers " and n is n i$ n divides " evenly= 1o#ever, i$ n does not divide " evenly, then the ans#er is the greatest common divisor o$ n and the remainder o$

" divided by n=

e #ill sim!ly !rovide an iterative im!lementation here -see !isting 6.= /ote that this im!lementation o$ the GCD algorithm only #or,s #hen the denominator is !ositive= 'his is acce!table $or our $raction class because #e have said that a negative $raction #ill be re!resented by a negative numerator=

1 2 4 ! 6 " # $ 10 11 12

;F

de: gcd(m.n)> Fhile m(n Q+ 0> oldm + m oldn + n m + oldn n + oldm(oldn return n print gcd(20.10)

-gcdOcl.

/o# #e can use this $unction to hel! reduce any $raction= 'o !ut a $raction in lo#est terms, #e #ill divide the numerator and the denominator by their greatest common divisor= So, $or the $raction CMF, the greatest common divisor is 9= Dividing the to! and the bottom by 9 creates a ne# $raction, ;M< -see !isting 7.=
1 >>> :1+*raction(1.4) 2 >>> :2+*raction(1.2) >>> : +:1%:2 4 >>> print(: ) ! '4 6 >>> 1 de: 44add44(sel:.other:raction)> 2 neFnum + sel:.num&other:raction.den % S sel:.den&other:raction.num 4 neFden + sel:.den & other:raction.den ! common + gcd(neFnum.neFden) 6 return *raction(neFnum''common.neFden''common)

+n Instance o$ the 6raction Class #ith '#o Methods

;E

Our 6raction object no# has t#o very use$ul methods and loo,s li,e Figure 6= +n additional grou! o$ methods that #e need to include in our e*am!le 6raction class #ill allo# t#o $ractions to com!are themselves to one another= +ssume #e have t#o 6raction objects, $2 and $9= $2PP$9 #ill only be 'rue i$ they are re$erences to the same object= '#o di$$erent objects #ith the same numerators and denominators #ould not be e3ual under this im!lementation= 'his is called shallow e-uality -see Figure 7.=

Shallo# )3uality 7ersus Dee! )3uality e can create deep e-uality -see Figure 7.Ae3uality by the same value, not the same re$erenceAby overriding the OOe3OO method= 'he OOe3OO method is another standard method available in any class= 'he OOe3OO method com!ares t#o objects and returns 'rue i$ their values are the same, 6alse other#ise=

<G

In the 6raction class, #e can im!lement the OOe3OO method by again !utting the t#o $ractions in common terms and then com!aring the numerators -see !isting 8.= It is im!ortant to note that there are other relational o!erators that can be overridden= 6or e*am!le, the OOleOO method !rovides the less than or e3ual $unctionality=
1 de: 44eq44(sel:. other)> 2 :irstnum + sel:.num & other.den secondnum + other.num & sel:.den 4 ! return :irstnum ++ secondnum

'he com!lete 6raction class, u! to this !oint, is sho#n in !isting #= arithmetic and relational methods as e*ercises=

e leave the remaining

1 2 4 ! 6 " # $ 10 11 12 1 14 1! 16 1" 1# 1$ 20 21 22 2 24 2! 26 2" 2# 2$ 0 class *raction> de: 44init44(sel:.top.<ottom)> sel:.num + top sel:.den + <ottom de: 44str44(sel:)> return str(sel:.num)%"'"%str(sel:.den) de: shoF(sel:)> print(sel:.num."'".sel:.den)

<2

de: 44add44(sel:.other:raction)> neFnum + sel:.num&other:raction.den % S sel:.den&other:raction.num neFden + sel:.den & other:raction.den common + gcd(neFnum.neFden) return *raction(neFnum''common.neFden''common) de: 44eq44(sel:. other)> :irstnum + sel:.num & other.den secondnum + other.num & sel:.den return :irstnum ++ secondnum 3 + *raction(1.2) 0 + *raction(2. ) print(3%0) print(3 ++ 0)

-$ractionOclass.

Sel$ Chec, 'o ma,e sure you understand ho# o!erators are im!lemented in %ython classes, and ho# to !ro!erly #rite methods, #rite some methods to im!lement L, M, and 4 = +lso im!lement com!arison o!erators J and Q

Inheritance. /ogic Gates and #ircuits


Our $inal section #ill introduce another im!ortant as!ect o$ object4oriented !rogramming= Inheritance is the ability $or one class to be related to another class in much the same #ay that !eo!le can be related to one another= Children inherit characteristics $rom their !arents= Similarly, %ython child classes can inherit characteristic data and behavior $rom a !arent class= 'hese classes are o$ten re$erred to as subclasses and superclasses=

<9

Figure 8 sho#s the built4in %ython collections and their relationshi!s to one another= e call a relationshi! structure such as this an inheritance hierarchy= 6or e*am!le, the list is a child o$ the se3uential collection= In this case, #e call the list the child and the se3uence the !arent -or subclass list and su!erclass se3uence.= 'his is o$ten re$erred to as an IS4+ Relationshi! -the list IS&A se3uential collection.= 'his im!lies that lists inherit im!ortant characteristics $rom se3uences, namely the ordering o$ the underlying data and o!erations such as concatenation, re!etition, and inde*ing=

+n Inheritance 1ierarchy $or %ython Collections Lists, tu!les, and strings are all ty!es o$ se3uential collections= 'hey all inherit common data organi8ation and o!erations= 1o#ever, each o$ them is distinct based on #hether the data is homogeneous and #hether the collection is immutable= 'he children all gain $rom their !arents but distinguish themselves by adding additional characteristics= By organi8ing classes in this hierarchical $ashion, object4oriented !rogramming languages allo# !reviously #ritten code to be e*tended to meet the needs o$ a ne# situation= In addition, by organi8ing data in this hierarchical manner, #e can better understand the relationshi!s that e*ist= e can be more e$$icient in building our abstract re!resentations= 'o e*!lore this idea $urther, #e #ill construct a simulation, an a!!lication to simulate digital circuits= 'he basic building bloc, $or this simulation #ill be the logic gate= 'hese electronic s#itches re!resent boolean algebra relationshi!s bet#een their in!ut and their out!ut= In general, gates have a single out!ut line= 'he value o$ the out!ut is de!endent on the values given on the in!ut lines= +/D gates have t#o in!ut lines, each o$ #hich can be either G or 2 -re!resenting 6alse or 'rue, re!ectively.= I$ both o$ the in!ut lines have the value 2, the resulting out!ut is 2= 1o#ever, i$ either or both o$ the in!ut lines is G, the result is G= OR gates also have t#o in!ut lines and !roduce a 2 i$ one or both o$ the in!ut values is a 2= In the case #here both in!ut lines are G, the result is G=

<;

/O' gates di$$er $rom the other t#o gates in that they only have a single in!ut line= 'he out!ut value is sim!ly the o!!osite o$ the in!ut value= I$ G a!!ears on the in!ut, 2 is !roduced on the out!ut= Similarly, 2 !roduces G= Figure # sho#s ho# each o$ these gates is ty!ically re!resented= )ach gate also has a truth table o$ values sho#ing the in!ut4to4out!ut ma!!ing that is !er$ormed by the gate=

'hree 'y!es o$ Logic Gates By combining these gates in various !atterns and then a!!lying a set o$ in!ut values, #e can build circuits that have logical $unctions= Figure 1$ sho#s a circuit consisting o$ t#o +/D gates, one OR gate, and a single /O' gate= 'he out!ut lines $rom the t#o +/D gates $eed directly into the OR gate, and the resulting out!ut $rom the OR gate is given to the /O' gate= I$ #e a!!ly a set o$ in!ut values to the $our in!ut lines -t#o $or each +/D gate., the values are !rocessed and a result a!!ears at the out!ut o$ the /O' gate= Figure 1$ also sho#s an e*am!le #ith values=

Circuit In order to im!lement a circuit, #e #ill $irst build a re!resentation $or logic gates= Logic gates are easily organi8ed into a class inheritance hierarchy as sho#n in Figure 11= +t the to! o$ the hierarchy, the LogicGate class re!resents the most general characteristics o$ logic gates0 namely, a label $or the gate and an out!ut line= 'he ne*t level o$ subclasses brea,s the logic gates into t#o $amilies, those that have one in!ut line and those that have t#o= Belo# that, the s!eci$ic logic $unctions o$ each a!!ear=

<<

+n Inheritance 1ierarchy $or Logic Gates e can no# start to im!lement the classes by starting #ith the most general, LogicGate= +s noted earlier, each gate has a label $or identi$ication and a single out!ut line= In addition, #e need methods to allo# a user o$ a gate to as, the gate $or its label= 'he other behavior that every logic gate needs is the ability to ,no# its out!ut value= 'his #ill re3uire that the gate !er$orm the a!!ro!riate logic based on the current in!ut= In order to !roduce out!ut, the gate needs to ,no# s!eci$ically #hat that logic is= 'his means calling a method to !er$orm the logic com!utation= 'he com!lete class is sho#n in !isting 1$=

1 2 4 ! 6 " # $ 10 11 12 1 14 class 1ogicTate> de: 44init44(sel:.n)> sel:.la<el + n sel:.output + 7one de: get1a<el(sel:)> return sel:.la<el de: getKutput(sel:)> sel:.output + sel:.per:ormTate1ogic() return sel:.output

<B

-logicgateOclass.

+t this !oint, #e #ill not im!lement the !er$ormGateLogic $unction= 'he reason $or this is that #e do not ,no# ho# each gate #ill !er$orm its o#n logic o!eration= 'hose details #ill be included by each individual gate that is added to the hierarchy= 'his is a very !o#er$ul idea in object4oriented !rogramming= e are #riting a method that #ill use code that does not e*ist yet= 'he !arameter sel$ is a re$erence to the actual gate object invo,ing the method= +ny ne# logic gate that gets added to the hierarchy #ill sim!ly need to im!lement the !er$ormGateLogic $unction and it #ill be used at the a!!ro!riate time= Once done, the gate can !rovide its out!ut value= 'his ability to e*tend a hierarchy that currently e*ists and !rovide the s!eci$ic $unctions that the hierarchy needs to use the ne# class is e*tremely im!ortant $or reusing e*isting code= e categori8ed the logic gates based on the number o$ in!ut lines= 'he +/D gate has t#o in!ut lines= 'he OR gate also has t#o in!ut lines= /O' gates have one in!ut line= 'he BinaryGate class #ill be a subclass o$ LogicGate and #ill add t#o in!ut lines= 'he 5naryGate class #ill also subclass LogicGate but #ill have only a single in!ut line= In com!uter circuit design, these lines are sometimes called ?!ins@ so #e #ill use that terminology in our im!lementation=

1 2 4 ! 6 " # $ 10 11 12 1 14 1! 16 1" class Pinar0Tate(1ogicTate)> de: 44init44(sel:.n)> 1ogicTate.44init44(sel:.n) sel:.pinA + 7one

<C

sel:.pinP + 7one de: getNinA(sel:)> return int(input("@nter Nin A input :or gate "% S sel:.get1a<el()%"55>")) de: getNinP(sel:)> return int(input("@nter Nin P input :or gate "% S sel:.get1a<el()%"55>"))

-binarygateOclass.

1 class Inar0Tate(1ogicTate)> 2 de: 44init44(sel:.n)> 4 1ogicTate.44init44(sel:.n) ! 6 sel:.pin + 7one " # de: getNin(sel:)> $ return int(input("@nter Nin input :or gate "% S 10 sel:.get1a<el()%"55>"))

Listings binarygateclass and unarygateclass im!lement these t#o classes= 'he constructors in both o$ these classes start #ith an e*!licit call to the constructor o$ the !arent class using the su!er $unction= hen creating an instance o$ the BinaryGate class, #e $irst #ant to initiali8e any data items that are inherited $rom LogicGate= In this case, that means the label $or the gate= 'he constructor then goes on to add the t#o in!ut lines -!in+ and !inB.= 'his is a very common !attern that you should al#ays use #hen building class hierarchies= Child class constructors need to call !arent class constructors and then move on to their o#n distinguishing data= 'he only behavior that the BinaryGate class adds is the ability to get the values $rom the t#o in!ut lines= Since these values come $rom some e*ternal !lace, #e #ill sim!ly as, the user via an in!ut statement to !rovide them= 'he same im!lementation occurs $or the 5naryGate class e*ce!t that there is only one in!ut line= /o# that #e have a general class $or gates de!ending on the number o$ in!ut lines, #e can build s!eci$ic gates that have uni3ue behavior= 6or e*am!le, the +ndGate class #ill be a subclass o$ BinaryGate since +/D gates have t#o in!ut lines= +s be$ore, the $irst line o$ the constructor calls u!on the !arent class constructor -BinaryGate., #hich in turn calls its !arent class constructor -LogicGate.= /ote that the +ndGate class does not !rovide any ne# data since it inherits t#o in!ut lines, one out!ut line, and a label=

<D

2 4 ! 6 " # $ 10 11 12 1 14 1! class AndTate(Pinar0Tate)> de: 44init44(sel:.n)> Pinar0Tate.44init44(sel:.n) de: per:ormTate1ogic(sel:)> a + sel:.getNinA() < + sel:.getNinP() i: a++1 and <++1> return 1 else> return 0

-andgateOclass.

'he only thing +ndGate needs to add is the s!eci$ic behavior that !er$orms the boolean o!eration that #as described earlier= 'his is the !lace #here #e can !rovide the !er$ormGateLogic method= 6or an +/D gate, this method $irst must get the t#o in!ut values and then only return 2 i$ both in!ut values are 2= 'he com!lete class is sho#n in !isting 11= e can sho# the +ndGate class in action by creating an instance and as,ing it to com!ute its out!ut= 'he $ollo#ing session sho#s an +ndGate object, g2, that has an internal label _G2_= hen #e invo,e the getOut!ut method, the object must $irst call its !er$ormGateLogic method #hich in turn 3ueries the t#o in!ut lines= Once the values are !rovided, the correct out!ut is sho#n=

1 2 4 g1 + AndTate("T1")

<F

print(g1.getKutput())

-andgateOtest.

'he same develo!ment can be done $or OR gates and /O' gates= 'he OrGate class #ill also be a subclass o$ BinaryGate and the /otGate class #ill e*tend the 5naryGate class= Both o$ these classes #ill need to !rovide their o#n !er$ormGateLogic $unctions, as this is their s!eci$ic behavior= e can use a single gate by $irst constructing an instance o$ one o$ the gate classes and then as,ing the gate $or its out!ut -#hich #ill in turn need in!uts to be !rovided.= 6or e*am!le0
1 >>> g2 + KrTate("T2") 2 >>> g2.getKutput() @nter Nin A input :or gate 4 @nter Nin P input :or gate !1 6 >>> g2.getKutput() " @nter Nin A input :or gate # @nter Nin P input :or gate $0 10 >>> g + 7otTate("T ") 11 >>> g .getKutput() 12 @nter Nin input :or gate T 1 1

T255>1 T255>1 T255>0 T255>0

55>0

/o# that #e have the basic gates #or,ing, #e can turn our attention to building circuits= In order to create a circuit, #e need to connect gates together, the out!ut o$ one $lo#ing into the in!ut o$ another= 'o do this, #e #ill im!lement a ne# class called Connector= 'he Connector class #ill not reside in the gate hierarchy= It #ill, ho#ever, use the gate hierarchy in that each connector #ill have t#o gates, one on either end -see Figure 12.= 'his relationshi! is very im!ortant in object4oriented !rogramming= It is called the 0AS&A Relationship= Recall earlier that #e used the !hrase ?IS4+ Relationshi!@ to say that a child class is related to a !arent class, $or e*am!le 5naryGate IS4+ LogicGate=

+ Connector Connects the Out!ut o$ One Gate to the In!ut o$ +nother

<E

/o#, #ith the Connector class, #e say that a Connector 1+S4+ LogicGate meaning that connectors #ill have instances o$ the LogicGate class #ithin them but are not !art o$ the hierarchy= hen designing classes, it is very im!ortant to distinguish bet#een those that have the IS4+ relationshi! -#hich re3uires inheritance. and those that have 1+S4+ relationshi!s -#ith no inheritance.= !isting 12 sho#s the Connector class= 'he t#o gate instances #ithin each connector object #ill be re$erred to as the $romgate and the togate, recogni8ing that data values #ill ?$lo#@ $rom the out!ut o$ one gate into an in!ut line o$ the ne*t= 'he call to set/e*t%in is very im!ortant $or ma,ing connections -see !isting x.= e need to add this method to our gate classes so that each togate can choose the !ro!er in!ut line $or the connection=
1 class Jonnector> 2 de: 44init44(sel:. :gate. tgate)> 4 sel:.:romgate + :gate ! sel:.togate + tgate 6 " tgate.set7e3tNin(sel:) # $ de: get*rom(sel:)> 10 return sel:.:romgate 11 12 de: get)o(sel:)> 1 return sel:.togate

In the BinaryGate class, $or gates #ith t#o !ossible in!ut lines, the connector must be connected to only one line= I$ both o$ them are available, #e #ill choose !in+ by de$ault= I$ !in+ is already connected, then #e #ill choose !inB= It is not !ossible to connect to a gate #ith no available in!ut lines=
1 de: set7e3tNin(sel:.source)> 2 i: sel:.pinA ++ 7one> sel:.pinA + source 4 else> ! i: sel:.pinP ++ 7one> 6 sel:.pinP + source " else> # raise Luntime@rror("@rror> 7K @GN)M N97S")

/o# it is !ossible to get in!ut $rom t#o !laces0 e*ternally, as be$ore, and $rom the out!ut o$ a gate that is connected to that in!ut line= 'his re3uires a change to the get%in+ and get%inB methods -see !isting 13.= I$ the in!ut line is not connected to anything -/one., then as, the user e*ternally as be$ore= 1o#ever, i$ there is a connection, the connection is accessed and $romgate:s out!ut value is retrieved= 'his in turn causes that gate to !rocess its logic= 'his continues until all in!ut is available and the $inal out!ut value becomes the re3uired in!ut $or the gate in 3uestion= In a sense, the circuit #or,s bac,#ards to $ind the in!ut necessary to $inally !roduce out!ut=
1 de: getNinA(sel:)> 2 i: sel:.pinA ++ 7one> return input("@nter Nin A input :or gate "% S 4 sel:.get7ame()%"55>") ! else>

BG

return sel:.pinA.get*rom().getKutput()

'he $ollo#ing $ragment constructs the circuit sho#n earlier in the section0
1 >>> g1 2 >>> g2 >>> g 4 >>> g4 ! >>> c1 6 >>> c2 " >>> c + + + + + + + AndTate("T1") AndTate("T2") KrTate("T ") 7otTate("T4") Jonnector(g1.g ) Jonnector(g2.g ) Jonnector(g .g4)

'he out!uts $rom the t#o +/D gates -g2 and g9. are connected to the OR gate -g;. and that out!ut is connected to the /O' gate -g<.= 'he out!ut $rom the /O' gate is the out!ut o$ the entire circuit= 6or e*am!le0
1 >>> g4.getKutput() 2 Nin A input :or gate Nin P input :or gate 4 Nin A input :or gate ! Nin P input :or gate 60 " >>> T155>0 T155>1 T255>1 T255>1

+ com!lete listing o$ the circuit simulation classes is available on the com!anion #ebsite $or this boo, htt!0MM###=!ython#or,s=org= Sel$ Chec, Create a t#o ne# gate clasess one called /orGate the other called /andGate= /andGates #or, li,e +ndGates that have a /ot attached to the out!ut= /orGates #or, la,e OrGates that have a /ot attached to the out!ut= Create a series o$ gates that !rove the $ollo#ing e3uality /O' -- + and B. or -C and D.. is that same as /O'- + and B . and /O' -C and D.= Ma,e sure to use some o$ your ne# gates in the simulation=

Summary

Com!uter science is the study o$ !roblem solving= Com!uter science uses abstraction as a tool $or re!resenting both !rocesses and data=

B2

+bstract data ty!es allo# !rogrammers to manage the com!le*ity o$ a !roblem domain by hiding the details o$ the data= %ython is a !o#er$ul, yet easy4to4use, object4oriented language= Lists, tu!les, and strings are built in %ython se3uential collections= Dictionaries and sets are nonse3uential collections o$ data= Classes allo# !rogrammers to im!lement abstract data ty!es= %rogrammers can override standard methods as #ell as create ne# methods= Classes can be organi8ed into hierarchies= + class constructor should al#ays invo,e the constructor o$ its !arent be$ore continuing on #ith its o#n data and behavior=

1ey Terms
abstract data type class data structure dictionary $ormat o!erator inheritance hierarchy list mutability !rogramming shallo# e3uality subclass Htab0,ey#ordsI abstraction com!utable data ty!e enca!sulation $ormatted strings inter$ace object !rom!t simulation su!erclass algorithm data abstraction dee! e3uality e*ce!tion 1+S4+ relationshi! IS4+ relationshi! !rocedural abstraction sel$ string truth table

im!lementation4inde!endent in$ormation hiding inheritance list com!rehension method

Discussion 2uestions
2= Construct a class hierarchy $or !eo!le on a college cam!us= Include $aculty, sta$$, and students= hat do they have in common" hat distinguishes them $rom one another" 9= Construct a class hierarchy $or ban, accounts= ;= Construct a class hierarchy $or di$$erent ty!es o$ com!uters= <= 5sing the classes !rovided in the cha!ter, interactively construct a circuit and test it=

Programming ()ercises
2= Im!lement the sim!le methods get/um and getDen that #ill return the numerator and denominator o$ a $raction= 9= In many #ays it #ould be better i$ all $ractions #ere maintained in lo#est terms right $rom the start= Modi$y the constructor $or the 6raction class so that GCD is used to reduce $ractions immediately= /otice that this means the OOaddOO $unction no longer needs to reduce= Ma,e the necessary modi$ications= B9

;= Im!lement the remaining sim!le arithmetic o!erators -OOsubOO, OOmulOO, and OOtruedivOO.= <= Im!lement the remaining relational o!erators -OOgtOO, OOgeOO, OOltOO, OOleOO, and OOneOO. B= Modi$y the constructor $or the $raction class so that it chec,s to ma,e sure that the numerator and denominator are both integers= I$ either is not an integer the constructor should raise an e*ce!tion= C= In the de$inition o$ $ractions #e assumed that negative $ractions have a negative numerator and a !ositive denominator= 5sing a negative denominator #ould cause some o$ the relational o!erators to give incorrect results= In general, this is an unnecessary constraint= Modi$y the constructor to allo# the user to !ass a negative denominator so that all o$ the o!erators continue to #or, !ro!erly= D= Research the OOraddOO method= 1o# does it di$$er $rom OOaddOO" hen is it used" Im!lement OOraddOO= F= Re!eat the last 3uestion but this time consider the OOiaddOO method= E= Research the OOre!rOO method= 1o# does it di$$er $rom OOstrOO" hen is it used" Im!lement OOre!rOO= 2G= Research other ty!es o$ gates that e*ist -such as /+/D, /OR, and `OR.= +dd them to the circuit hierarchy= 1o# much additional coding did you need to do" 22= 'he most sim!le arithmetic circuit is ,no#n as the hal$4adder= Research the sim!le hal$4adder circuit= Im!lement this circuit= 29= /o# e*tend that circuit and im!lement an F bit $ull4adder= 2;= 'he circuit simulation sho#n in this cha!ter #or,s in a bac,#ard direction= In other #ords, given a circuit, the out!ut is !roduced by #or,ing bac, through the in!ut values, #hich in turn cause other out!uts to be 3ueried= 'his continues until e*ternal in!ut lines are $ound, at #hich !oint the user is as,ed $or values= Modi$y the im!lementation so that the action is in the $or#ard directionU u!on receiving in!uts the circuit !roduces an out!ut= 2<= Design a class to re!resent a !laying card= /o# design a class to re!resent a dec, o$ cards= 5sing these t#o classes, im!lement a $avorite card game= 2B= 6ind a Sudo,u !u88le in the local ne#s!a!er= rite a !rogram to solve the !u88le=

B;

Algorithm Analysis
!b"ectives

'o understand #hy algorithm analysis is im!ortant= 'o be able to use ?Big4O@ to describe e*ecution time= 'o understand the ?Big4O@ e*ecution time o$ common o!erations on %ython lists and dictionaries= 'o understand ho# the im!lementation o$ %ython data im!acts algorithm analysis= 'o understand ho# to benchmar, sim!le %ython !rograms=

What Is Algorithm Analysis$


It is very common $or beginning com!uter science students to com!are their !rograms #ith one another= >ou may also have noticed that it is common $or com!uter !rograms to loo, very similar, es!ecially the sim!le ones= +n interesting 3uestion o$ten arises= hen t#o !rograms solve the same !roblem but loo, di$$erent, is one !rogram better than the other" In order to ans#er this 3uestion, #e need to remember that there is an im!ortant di$$erence bet#een a !rogram and the underlying algorithm that the !rogram is re!resenting= +s #e stated in Cha!ter 2, an algorithm is a generic, ste!4by4ste! list o$ instructions $or solving a !roblem= It is a method $or solving any instance o$ the !roblem such that given a !articular in!ut, the algorithm !roduces the desired result= + !rogram, on the other hand, is an algorithm that has been encoded into some !rogramming language= 'here may be many !rograms $or the same algorithm, de!ending on the !rogrammer and the !rogramming language being used= 'o e*!lore this di$$erence $urther, consider the $unction sho#n in !isting= 'his $unction solves a $amiliar !roblem, com!uting the sum o$ the $irst n integers= 'he algorithm uses the idea o$ an accumulator variable that is initiali8ed to G= 'he solution then iterates through the n integers, adding each to the accumulator=

1 2 4 ! 6 " # $ 10 de: sumK:7(n)> theSum + 0 :or i in range(1.n%1)>

B<

theSum + theSum % i return theSum print(sumK:7(10))

Summation o$ the 6irst n Integers -active2.

/o# loo, at the $unction in !isting 2= +t $irst glance it may loo, strange, but u!on $urther ins!ection you can see that this $unction is essentially doing the same thing as the !revious one= 'he reason this is not obvious is !oor coding= e did not use good identi$ier names to assist #ith readability, and #e used an e*tra assignment statement during the accumulation ste! that #as not really necessary=

1 2 4 ! 6 " # $ 10 11 de: :oo(tom)> :red + 0 :or <ill in range(1.tom%1)> <arne0 + <ill :red + :red % <arne0 return :red print(:oo(10))

+nother Summation o$ the 6irst n Integers -active9.

'he 3uestion #e raised earlier as,ed #hether one $unction is better than another= 'he ans#er de!ends on your criteria= 'he $unction sumK:7 is certainly better than the $unction :oo i$ you

BB

are concerned #ith readability= In $act, you have !robably seen many e*am!les o$ this in your introductory !rogramming course since one o$ the goals there is to hel! you #rite !rograms that are easy to read and easy to understand= In this course, ho#ever, #e are also interested in characteri8ing the algorithm itsel$= - e certainly ho!e that you #ill continue to strive to #rite readable, understandable code=. +lgorithm analysis is concerned #ith com!aring algorithms based u!on the amount o$ com!uting resources that each algorithm uses= e #ant to be able to consider t#o algorithms and say that one is better than the other because it is more e$$icient in its use o$ those resources or !erha!s because it sim!ly uses $e#er= 6rom this !ers!ective, the t#o $unctions above seem very similar= 'hey both use essentially the same algorithm to solve the summation !roblem= +t this !oint, it is im!ortant to thin, more about #hat #e really mean by com!uting resources= 'here are t#o di$$erent #ays to loo, at this= One #ay is to consider the amount o$ s!ace or memory an algorithm re3uires to solve the !roblem= 'he amount o$ s!ace re3uired by a !roblem solution is ty!ically dictated by the !roblem instance itsel$= )very so o$ten, ho#ever, there are algorithms that have very s!eci$ic s!ace re3uirements, and in those cases #e #ill be very care$ul to e*!lain the variations= +s an alternative to s!ace re3uirements, #e can analy8e and com!are algorithms based on the amount o$ time they re3uire to e*ecute= 'his measure is sometimes re$erred to as the ?e*ecution time@ or ?running time@ o$ the algorithm= One #ay #e can measure the e*ecution time $or the $unction sumK:7 is to do a benchmar, analysis= 'his means that #e #ill trac, the actual time re3uired $or the !rogram to com!ute its result= In %ython, #e can benchmar, a $unction by noting the starting time and ending time #ith res!ect to the system #e are using= In the time module there is a $unction called time that #ill return the current system cloc, time in seconds since some arbitrary starting !oint= By calling this $unction t#ice, at the beginning and at the end, and then com!uting the di$$erence, #e can get an e*act number o$ seconds -$ractions in most cases. $or e*ecution=
import time de: sumK:72(n)> start + time.time() theSum + 0 :or i in range(1.n%1)> theSum + theSum % i end + time.time() return theSum.end5start

!isting 3 sho#s the original sumK:7 $unction #ith the timing calls embedded be$ore and a$ter the summation= 'he $unction returns a tu!le consisting o$ the result and the amount o$ time -in seconds. re3uired $or the calculation= I$ #e !er$orm B invocations o$ the $unction, each com!uting the sum o$ the $irst 2G,GGG integers, #e get the $ollo#ing0
>>>:or i in range(!)> print("Sum is (d required (10.": seconds"(sumK:7(10000)) Sum is !000!000 required 0.001#$!0 seconds Sum is !000!000 required 0.001#620 seconds

BC

Sum is !000!000 required Sum is !000!000 required Sum is !000!000 required

0.001$1"1 seconds 0.001$162 seconds 0.001$ 60 seconds

e discover that the time is $airly consistent and it ta,es on average about G=GG2E seconds to e*ecute that code= hat i$ #e run the $unction adding the $irst 2GG,GGG integers"
>>>:or i in range(!)> print("Sum is (d required (10.": seconds"(sumK:7(100000)) Sum is !0000!0000 required 0.01$$420 seconds Sum is !0000!0000 required 0.01#0$"2 seconds Sum is !0000!0000 required 0.01$4#21 seconds Sum is !0000!0000 required 0.01"#$## seconds Sum is !0000!0000 required 0.01##$4$ seconds >>>

+gain, the time re3uired $or each run, although longer, is very consistent, averaging about 2G times more seconds= 6or n e3ual to 2,GGG,GGG #e get0
>>>:or i in range(!)> print("Sum is (d required (10.": Sum is !00000!00000 required 0.1$4#$## Sum is !00000!00000 required 0.1#!02$0 Sum is !00000!00000 required 0.1#0$""1 Sum is !00000!00000 required 0.1"2$2!0 Sum is !00000!00000 required 0.16462$$ >>> seconds"(sumK:7(1000000)) seconds seconds seconds seconds seconds

In this case, the average again turns out to be about 2G times the !revious= /o# consider !isting 3, #hich sho#s a di$$erent means o$ solving the summation !roblem= 'his $unction, sumK:7 , ta,es advantage o$ a closed e3uation aniP2iP-n.-nK2.9 to com!ute the sum o$ the $irst n integers #ithout iterating=

1 2 4 ! 6 de: sumK:7 (n)> return (n&(n%1))'2 print(sumK:7 (10))

Summation

ithout Iteration -active;.

BD

I$ #e do the same benchmar, measurement $or sumK:7 , using $ive di$$erent values $or n -2G,GGG, 2GG,GGG, 2,GGG,GGG, 2G,GGG,GGG, and 2GG,GGG,GGG., #e get the $ollo#ing results0
Sum Sum Sum Sum Sum is is is is is !000!000 required 0.000000$! seconds !0000!0000 required 0.000001$1 seconds !00000!00000 required 0.000000$! seconds !000000!000000 required 0.000000$! seconds !0000000!0000000 required 0.0000011$ seconds

'here are t#o im!ortant things to notice about this out!ut= 6irst, the times recorded above are shorter than any o$ the !revious e*am!les= Second, they are very consistent no matter #hat the value o$ n= It a!!ears that sumK:7 is hardly im!acted by the number o$ integers being added= But #hat does this benchmar, really tell us" Intuitively, #e can see that the iterative solutions seem to be doing more #or, since some !rogram ste!s are being re!eated= 'his is li,ely the reason it is ta,ing longer= +lso, the time re3uired $or the iterative solution seems to increase as #e increase the value o$ n= 1o#ever, there is a !roblem= I$ #e ran the same $unction on a di$$erent com!uter or used a di$$erent !rogramming language, #e #ould li,ely get di$$erent results= It could ta,e even longer to !er$orm sumK:7 i$ the com!uter #ere older= e need a better #ay to characteri8e these algorithms #ith res!ect to e*ecution time= 'he benchmar, techni3ue com!utes the actual time to e*ecute= It does not really !rovide us #ith a use$ul measurement, because it is de!endent on a !articular machine, !rogram, time o$ day, com!iler, and !rogramming language= Instead, #e #ould li,e to have a characteri8ation that is inde!endent o$ the !rogram or com!uter being used= 'his measure #ould then be use$ul $or judging the algorithm alone and could be used to com!are algorithms across im!lementations=

(ig&O )otation
hen trying to characteri8e an algorithm:s e$$iciency in terms o$ e*ecution time, inde!endent o$ any !articular !rogram or com!uter, it is im!ortant to 3uanti$y the number o$ o!erations or ste!s that the algorithm #ill re3uire= I$ each o$ these ste!s is considered to be a basic unit o$ com!utation, then the e*ecution time $or an algorithm can be e*!ressed as the number o$ ste!s re3uired to solve the !roblem= Deciding on an a!!ro!riate basic unit o$ com!utation can be a com!licated !roblem and #ill de!end on ho# the algorithm is im!lemented= + good basic unit o$ com!utation $or com!aring the summation algorithms sho#n earlier might be to count the number o$ assignment statements !er$ormed to com!ute the sum= In the $unction sumK:7, the number o$ assignment statements is 2 -theSu"PG. !lus the value o$ n -the number o$ times #e !er$orm theSu"PtheSu"Ki.= e can denote this by a $unction, call it ', #here T-n.P2Kn= 'he !arameter n is o$ten re$erred to as the ?si8e o$ the !roblem,@ and #e can read this as ?T%&%n. is the time it ta,es to solve a !roblem o$ si8e n, namely 2KLnL ste!s=@ In the summation $unctions given above, it ma,es sense to use the number o$ terms in the summation to denote the si8e o$ the !roblem= e can then say that the sum o$ the $irst BF

2GG,GGG integers is a bigger instance o$ the summation !roblem than the sum o$ the $irst 2,GGG= Because o$ this, it might seem reasonable that the time re3uired to solve the larger case #ould be greater than $or the smaller case= Our goal then is to sho# ho# the algorithm:s e*ecution time changes #ith res!ect to the si8e o$ the !roblem= Com!uter scientists !re$er to ta,e this analysis techni3ue one ste! $urther= It turns out that the e*act number o$ o!erations is not as im!ortant as determining the most dominant !art o$ the T-n. $unction= In other #ords, as the !roblem gets larger, some !ortion o$ the T-n. $unction tends to over!o#er the rest= 'his dominant term is #hat, in the end, is used $or com!arison= 'he order o% magnitude $unction describes the !art o$ T-n. that increases the $astest as the value o$ n increases= Order o$ magnitude is o$ten called Big&! notation -$or ?order@. and #ritten as '-(-n..= It !rovides a use$ul a!!ro*imation to the actual number o$ ste!s in the com!utation= 'he $unction (-n. !rovides a sim!le re!resentation o$ the dominant !art o$ the original T-n.= In the above e*am!le, T-n.P2Kn= +s n gets large, the constant 2 #ill become less and less signi$icant to the $inal result= I$ #e are loo,ing $or an a!!ro*imation $or T-n., then #e can dro! the 2 and sim!ly say that the running time is '-n.= It is im!ortant to note that the 2 is certainly signi$icant $or T-n.= 1o#ever, as n gets large, our a!!ro*imation #ill be just as accurate #ithout it= +s another e*am!le, su!!ose that $or some algorithm, the e*act number o$ ste!s is T-n.PBn9K9DnK2GGB= hen n is small, say 2 or 9, the constant 2GGB seems to be the dominant !art o$ the $unction= 1o#ever, as n gets larger, the n9 term becomes the most im!ortant= In $act, #hen n is really large, the other t#o terms become insigni$icant in the role that they !lay in determining the $inal result= +gain, to a!!ro*imate T-n. as n gets large, #e can ignore the other terms and $ocus on Bn9= In addition, the coe$$icient B becomes insigni$icant as n gets large= e #ould say then that the $unction T-n. has an order o$ magnitude (-n.Pn9, or sim!ly that it is '-n9.= +lthough #e do not see this in the summation e*am!le, sometimes the !er$ormance o$ an algorithm de!ends on the e*act values o$ the data rather than sim!ly the si8e o$ the !roblem= 6or these ,inds o$ algorithms #e need to characteri8e their !er$ormance in terms o$ best case, worst case, or average case !er$ormance= 'he #orst case !er$ormance re$ers to a !articular data set #here the algorithm !er$orms es!ecially !oorly= hereas a di$$erent data set $or the e*act same algorithm might have e*traordinarily good !er$ormance= 1o#ever, in most cases the algorithm !er$orms some#here in bet#een these t#o e*tremes -average case.= It is im!ortant $or a com!uter scientist to understand these distinctions so they are not misled by one !articular case= %3n4 'ame Constant Logarithmic

2 logn

BE

%3n4

'ame Linear Log Linear (uadratic Cubic )*!onential

n nlogn n9 n; 9n

HCommon 6unctions $or Big4OI + number o$ very common order o$ magnitude $unctions #ill come u! over and over as you study algorithms= 'hese are sho#n in Table 1= In order to decide #hich o$ these $unctions is the dominant !art o$ any T-n. $unction, #e must see ho# they com!are #ith one another as n gets large= Figure 1 sho#s gra!hs o$ the common $unctions $rom Table 1= /otice that #hen n is small, the $unctions are not very #ell de$ined #ith res!ect to one another= It is hard to tell #hich is dominant= 1o#ever, as n gro#s, there is a de$inite relationshi! and it is easy to see ho# they com!are #ith one another=

CG

%lot o$ Common Big4O 6unctions +s a $inal e*am!le, su!!ose that #e have the $ragment o$ %ython code sho#n in !isting 5= +lthough this !rogram does not really do anything, it is instructive to see ho# #e can ta,e actual code and analy8e !er$ormance=
a+! <+6 c+10 :or i in range(n)> :or A in range(n)> 3 + i & i 0 + A & A R + i & A :or = in range(n)> F + a&= % 4! 2 + <&< d +

'he number o$ assignment o!erations is the sum o$ $our terms= 'he $irst term is the constant ;, re!resenting the three assignment statements at the start o$ the $ragment= 'he second term is ;n9, since there are three statements that are !er$ormed n9 times due to the nested iteration= 'he third term is 9n, t#o statements iterated n times= 6inally, the $ourth term is the constant 2, re!resenting the $inal assignment statement= 'his gives us T-n.P;K;n9K9nK2P;n9K9nK<= By loo,ing at the e*!onents, #e can easily see that the n9 term #ill be dominant and there$ore this $ragment o$ code is '-n9.= /ote that all o$ the other terms as #ell as the coe$$icient on the dominant term can be ignored as n gro#s larger=

C2

Com!aring T-n. #ith Common Big4O 6unctions Figure 2 sho#s a $e# o$ the common Big4O $unctions as they com!are #ith the T-n. $unction discussed above= /ote that T-n. is initially larger than the cubic $unction= 1o#ever, as n gro#s, the cubic $unction 3uic,ly overta,es T-n.= It is easy to see that T-n. then $ollo#s the 3uadratic $unction as n continues to gro#= Sel$ Chec, rite t#o %ython $unctions to $ind the minimum number in a list= 'he $irst $unction should com!are each number to every other number on the list= '-n9.= 'he second $unction should be linear '-n.=

C9

An Anagram Detection !ample


+ good e*am!le !roblem $or sho#ing algorithms #ith di$$erent orders o$ magnitude is the classic anagram detection !roblem $or strings= One string is an anagram o$ another i$ the second is sim!ly a rearrangement o$ the $irst= 6or e*am!le, 6heart6 and 6earth6 are anagrams= 'he strings 6p0thon6 and 6t0phon6 are anagrams as #ell= 6or the sa,e o$ sim!licity, #e #ill assume that the t#o strings in 3uestion are o$ e3ual length and that they are made u! o$ symbols $rom the set o$ 9C lo#ercase al!habetic characters= Our goal is to #rite a boolean $unction that #ill ta,e t#o strings and return #hether they are anagrams=

Solution 5. #hec ing !%%


Our $irst solution to the anagram !roblem #ill chec, to see that each character in the $irst string actually occurs in the second= I$ it is !ossible to ?chec,o$$@ each character, then the t#o strings must be anagrams= Chec,ing o$$ a character #ill be accom!lished by re!lacing it #ith the s!ecial %ython value 7one= 1o#ever, since strings in %ython are immutable, the $irst ste! in the !rocess #ill be to convert the second string to a list= )ach character $rom the $irst string can be chec,ed against the characters in the list and i$ $ound, chec,ed o$$ by re!lacement= !isting 6 sho#s this $unction=

1 2 4 ! 6 " # $ 10 11 12 1 14 1! 16 1"

C;

1# 1$ 20 21 22 2 24 2! 26 2" de: anagramSolution1(s1.s2)> alist + list(s2) pos1 + 0 stillKU + )rue Fhile pos1 , len(s1) and stillKU> pos2 + 0 :ound + *alse Fhile pos2 , len(alist) and not :ound> i: s1-pos1/ ++ alist-pos2/> :ound + )rue else> pos2 + pos2 % 1 i: :ound> alist-pos2/ + 7one else> stillKU + *alse pos1 + pos1 % 1 return stillKU print(anagramSolution1(6a<cd6.6dc<a6))

Chec,ing O$$ -activeB.

'o analy8e this algorithm, #e need to note that each o$ the n characters in s1 #ill cause an iteration through u! to n characters in the list $rom s2= )ach o$ the n !ositions in the list #ill be visited once to match a character $rom s1= 'he number o$ visits then becomes the sum o$ the integers $rom 2 to n= e stated earlier that this can be #ritten as

aiP2niPn-nK2.9P29n9K29n
+s n gets large, the n9 term #ill dominate the n term and the 29 can be ignored= 'here$ore, this solution is '-n9.=

C<

Solution 6. Sort and #ompare


+nother solution to the anagram !roblem #ill ma,e use o$ the $act that even though s1 and s2 are di$$erent, they are anagrams only i$ they consist o$ e*actly the same characters= So, i$ #e begin by sorting each string al!habetically, $rom a to 8, #e #ill end u! #ith the same string i$ the original t#o strings are anagrams= !isting 7 sho#s this solution= +gain, in %ython #e can use the built4in sort method on lists by sim!ly converting each string to a list at the start=

1 2 4 ! 6 " # $ 10 11 12 1 14 1! 16 1" 1# 1$ 20 21 de: anagramSolution2(s1.s2)> alist1 + list(s1) alist2 + list(s2) alist1.sort() alist2.sort() pos + 0 matches + )rue Fhile pos , len(s1) and matches> i: alist1-pos/++alist2-pos/> pos + pos % 1 else> matches + *alse return matches print(anagramSolution2(6a<cde6.6edc<a6))

Sort and Com!are -activeC. CB

+t $irst glance you may be tem!ted to thin, that this algorithm is '-n., since there is one sim!le iteration to com!are the n characters a$ter the sorting !rocess= 1o#ever, the t#o calls to the %ython sort method are not #ithout their o#n cost= +s #e #ill see in a later cha!ter, sorting is ty!ically either '-n9. or '-nlogn., so the sorting o!erations dominate the iteration= In the end, this algorithm #ill have the same order o$ magnitude as that o$ the sorting !rocess=

Solution 7. Brute ,orce


+ brute %orce techni3ue $or solving a !roblem ty!ically tries to e*haust all !ossibilities= 6or the anagram detection !roblem, #e can sim!ly generate a list o$ all !ossible strings using the characters $rom s1 and then see i$ s2 occurs= 1o#ever, there is a di$$iculty #ith this a!!roach= hen generating all !ossible strings $rom s1, there are n !ossible $irst characters, n[2 !ossible characters $or the second !osition, n[9 $or the third, and so on= 'he total number o$ candidate strings is n-n[2.-n[9.===;92, #hich is nR= +lthough some o$ the strings may be du!licates the !rogram cannot ,no# this ahead o$ time and so it #ill still generate nR di$$erent strings= It turns out that nR gro#s even $aster than 9n as n gets large= In $act, i$ s1 #ere 9G characters long, there #ould be 9GRP9,<;9,EG9,GGF,2DC,C<G,GGG !ossible candidate strings= I$ #e !rocessed one !ossibility every second, it #ould still ta,e us DD,2<C,F2C,BEC years to go through the entire list= 'his is !robably not going to be a good solution=

Solution 8. #ount and #ompare


Our $inal solution to the anagram !roblem ta,es advantage o$ the $act that any t#o anagrams #ill have the same number o$ a:s, the same number o$ b:s, the same number o$ c:s, and so on= In order to decide #hether t#o strings are anagrams, #e #ill $irst count the number o$ times each character occurs= Since there are 9C !ossible characters, #e can use a list o$ 9C counters, one $or each !ossible character= )ach time #e see a !articular character, #e #ill increment the counter at that !osition= In the end, i$ the t#o lists o$ counters are identical, the strings must be anagrams= !isting 8 sho#s this solution=

1 2 4 ! 6 "

CC

# $ 10 11 12 1 14 1! 16 1" 1# 1$ 20 21 22 2 24 2! de: anagramSolution4(s1.s2)> c1 + -0/&26 c2 + -0/&26 :or i in range(len(s1))> pos + ord(s1-i/)5ord(6a6) c1-pos/ + c1-pos/ % 1 :or i in range(len(s2))> pos + ord(s2-i/)5ord(6a6) c2-pos/ + c2-pos/ % 1 A + 0 stillKU + )rue Fhile A,26 and stillKU> i: c1-A/++c2-A/> A + A % 1 else> stillKU + *alse return stillKU print(anagramSolution4(6apple6.6pleap6))

Count and Com!are -activeD.

+gain, the solution has a number o$ iterations= 1o#ever, unli,e the $irst solution, none o$ them are nested= 'he $irst t#o iterations used to count the characters are both based on n= 'he third iteration, com!aring the t#o lists o$ counts, al#ays ta,es 9C ste!s since there are 9C !ossible characters in the strings= +dding it all u! gives us T-n.P9nK9C ste!s= 'hat is

'-n.=

e have $ound a linear order o$ magnitude algorithm $or solving this !roblem=

CD

Be$ore leaving this e*am!le, #e need to say something about s!ace re3uirements= +lthough the last solution #as able to run in linear time, it could only do so by using additional storage to ,ee! the t#o lists o$ character counts= In other #ords, this algorithm sacri$iced s!ace in order to gain time= 'his is a common occurrence= On many occasions you #ill need to ma,e decisions bet#een time and s!ace trade4o$$s= In this case, the amount o$ e*tra s!ace is not signi$icant= 1o#ever, i$ the underlying al!habet had millions o$ characters, there #ould be more concern= +s a com!uter scientist, #hen given a choice o$ algorithms, it #ill be u! to you to determine the best use o$ com!uting resources given a !articular !roblem= Sel$ Chec,
Ti2en the :olloFing code :ragment. Fhat is its Pig5K running timeV test + 0 :or i in range(n)> :or A in range(n)> test + test % i & A

a. O-n. b. O-nb9. c. O-log n.


Ti2en the :olloFing code :ragment Fhat is its Pig5K running timeV test + 0 :or i in range(n)> test + test % 1 :or A in range(n)> test + test 5 1

d. O-nb;.

a. O-n. b. O-nb9. c. O-log n. d. O-nb;.


Ti2en the :olloFing code :ragment Fhat is its Pig5K running timeV i + n Fhile i > 0> = + 2 % 2 i + i '' 2

a. O-n. b. O-nb9. c. O-log n. d. O-nb;.

Per%ormance o% Python Data Structures


/o# that you have a general idea o$ Big4O notation and the di$$erences in bet#een the di$$erent $unctions, our goal in this section is to tell you about the Big4O !er$ormance $or the CF

o!erations on %ython lists and dictionaries= e #ill then sho# you some timing e*!eriments that illustrate the costs and bene$its o$ using certain o!erations on each data structure= It is im!ortant $or you to understand the e$$iciency o$ these %ython data structures because they are the building bloc,s #e #ill use as #e im!lement other data structures in the remainder o$ the boo,= In this section #e are not going to e*!lain #hy the !er$ormance is #hat it is= In later cha!ters you #ill see some !ossible im!lementations o$ both lists and dictionaries and ho# the !er$ormance de!ends on the im!lementation=

*ists
'he designers o$ %ython had many choices to ma,e #hen they im!lemented the list data structure= )ach o$ these choices could have an im!act on ho# $ast list o!erations !er$orm= 'o hel! them ma,e the right choices they loo,ed at the #ays that !eo!le #ould most commonly use the list data structure and they o!timi8ed their im!lementation o$ a list so that the most common o!erations #ere very $ast= O$ course they also tried to ma,e the less common o!erations $ast, but #hen a tradeo$$ had to be made the !er$ormance o$ a less common o!eration #as o$ten sacri$iced in $avor o$ the more common o!eration= '#o common o!erations are inde*ing and assigning to an inde* !osition= Both o$ these o!erations ta,e the same amount o$ time no matter ho# large the list becomes= hen an o!eration li,e this is inde!endent o$ the si8e o$ the list they are '-2.= +nother very common !rogramming tas, is to gro# a list= 'here are t#o #ays to create a longer list either using the a!!end method, or the concatenation o!erator= 'he a!!end method is '-2.= 1o#ever, the concatenation o!erator is '-). #here ) is the si8e o$ the list that is being concatenated= 'his is im!ortant $or you to ,no# because it can hel! you ma,e your o#n !rograms more e$$icient by choosing the right tool $or the job= Lets loo, at $our di$$erent #ays #e might generate a list o$ n numbers starting #ith G= 6irst #e:ll try a :or loo! and create the list by concatenation, then #e:ll use a!!end rather than concatenation= /e*t, #e:ll try creating the list using list com!rehension and $inally, and !erha!s the most obvious #ay, using the range $unction #ra!!ed by a call to the list constructor= !isting # sho#s the code $or ma,ing our list $our di$$erent #ays= In the remainder o$ this section #e #ill assume this code is saved in the $ile list:uns.p0=
de: test1()> l + -/ :or i in range(1000)> l + l % -i/ de: test2()> l + -/ :or i in range(1000)> l.append(i) de: test ()> l + -i :or i in range(1000)/ de: test4()> l + list(range(1000))

CE

'o ca!ture the time it ta,es $or each o$ our $unctions to e*ecute #e #ill use %ython:s timeit module= 'he timeit module is designed to allo# %ython develo!ers to ma,e cross4!lat$orm timing measurements by running $unctions in a consistent environment and using timing mechanisms that are as similar as !ossible across o!erating systems= 'o use timeit you create a )imer object #hose !arameters are t#o %ython statements= 'he $irst !arameter is a %ython statement that you #ant to timeU the second !arameter is a statement that #ill run once to set u! the test= 'he timeit module #ill then time ho# long it ta,es to e*ecute the statement some number o$ times= By de$ault timeit #ill try to run the statement one million times= hen its done it returns the time as a $loating !oint value re!resenting the total number o$ seconds= 1o#ever, since it e*ecutes the statement a million times you can read the result as the number o$ microseconds to e*ecute the test one time= >ou can also !ass timeit a named !arameter called num<er that allo#s you to s!eci$y ho# many times the test statement is e*ecuted= 'he $ollo#ing session sho#s ho# long it ta,es to run each o$ our test $unctions 2GGG times=
t1 + )imer("test1()". ":rom 44main44 import test1") print("concat ".t1.timeit(num<er+1000). "milliseconds") t2 + )imer("test2()". ":rom 44main44 import test2") print("append ".t2.timeit(num<er+1000). "milliseconds") t + )imer("test ()". ":rom 44main44 import test ") print("comprehension ".t .timeit(num<er+1000). "milliseconds") t4 + )imer("test4()". ":rom 44main44 import test4") print("list range ".t4.timeit(num<er+1000). "milliseconds") concat 6.!4 !2#0"$$$ milliseconds append 0. 062$20!"0 " milliseconds comprehension 0.14"661$24 62 milliseconds list range 0.06!!00020$#0# milliseconds

In the e*!eriment above the statement that #e are timing is the $unction call to test1(), test2(), and so on= 'he setu! statement may loo, very strange to you, so let:s consider it in more detail= >ou are !robably very $amiliar #ith the :rom, import statement, but this is usually used at the beginning o$ a %ython !rogram $ile= In this case the statement :rom 44main44 import test1 im!orts the $unction test1 $rom the HOOmainOOI names!ace into the names!ace that timeit sets u! $or the timing e*!eriment= 'he timeit module does this because it #ants to run the timing tests in an environment that is uncluttered by any stray variables you may have created, that may inter$ere #ith your $unction:s !er$ormance in some un$oreseen #ay= 6rom the e*!eriment above it is clear that the a!!end o!eration at G=;G milliseconds is much $aster than concatenation at C=B< milliseconds= In the above e*!eriment #e also sho# the times $or t#o additional methods $or creating a listU using the list constructor #ith a call to range and a list com!rehension= It is interesting to note that the list com!rehension is t#ice as $ast as a :or loo! #ith an append o!eration= One $inal observation about this little e*!eriment is that all o$ the times that you see above include some overhead $or actually calling the test $unction, but #e can assume that the $unction call overhead is identical in all $our cases so #e still get a meaning$ul com!arison o$ the o!erations= So it #ould not be accurate to say that the concatenation o!eration ta,es C=B< milliseconds but rather the concatenation test $unction ta,es C=B< milliseconds= +s an e*ercise

DG

you could test the time it ta,es to call an em!ty $unction and subtract that $rom the numbers above= !peration inde* ST a!!end !o!-. !o!-i. insert-i,item. del o!erator iteration contains -in. get slice S*0yT del slice set slice reverse concatenate sort Big&! (%%iciency O-2. O-2. O-2. O-n. O-n. O-n. O-n. O-n. O-,. O-n. O-nK,. O-n. O-,. O-n log n.

inde* assignment O-2.

multi!ly O-n,. Big4O )$$iciency o$ %ython List O!erations /o# that #e have seen ho# !er$ormance can be measured concretely you can loo, at Table 2 to see the Big4O e$$iciency o$ all the basic list o!erations= +$ter thin,ing care$ully about Table 2, you may be #ondering about the t#o di$$erent times $or pop= hen pop is called on the end o$ the list it ta,es '-2. but #hen !o! is called on the $irst element in the list or any#here in the middle it is '-n.= 'he reason $or this lies in ho# %ython chooses to im!lement lists= hen an item is ta,en $rom the $ront o$ the list, in %ython:s im!lementation, all the other elements in the list are shi$ted one !osition closer to the beginning= 'his may seem silly to you no#, but i$ you loo, at Table 2 you #ill see that this im!lementation also allo#s the inde* o!eration to be '-2.= 'his is a tradeo$$ that the %ython im!lementors thought #as a good one= +s a #ay o$ demonstrating this di$$erence in !er$ormance let:s do another e*!eriment using the timeit module= Our goal is to be able to veri$y the !er$ormance o$ the pop o!eration on a list o$ a ,no#n si8e #hen the !rogram !o!s $rom the end o$ the list, and again #hen the !rogram !o!s $rom the beginning o$ the list= e #ill also #ant to measure this time $or lists o$ di$$erent si8es= hat #e #ould e*!ect to see is that the time re3uired to !o! $rom the end o$ the list #ill stay constant even as the list gro#s in si8e, #hile the time to !o! $rom the beginning o$ the list #ill continue to increase as the list gro#s= !isting 1$ sho#s one attem!t to measure the di$$erence bet#een the t#o uses o$ !o!= +s you can see $rom this $irst e*am!le !o!!ing $rom the end ta,es G=GGG; milliseconds, #hereas D2

!o!!ing $rom the beginning ta,es <=F9 milliseconds= 6or a list o$ t#o million elements this is a $actor o$ 2C,GGG= 'here are a cou!le o$ things to notice about !isting 1$= 'he $irst is the statement :rom 44main44 import 3= +lthough #e did not de$ine a $unction #e do #ant to be able to use the list object * in our test= 'his a!!roach allo#s us to time just the single pop statement and get the most accurate measure o$ the time $or that single o!eration= Because the timer re!eats 2GGG times it is also im!ortant to !oint out that the list is decreasing in si8e by 2 each time through the loo!= But since the initial list is t#o million elements in si8e #e only reduce the overall si8e by G=GBN
popRero + timeit.)imer("3.pop(0)". ":rom 44main44 import 3") popend + timeit.)imer("3.pop()". ":rom 44main44 import 3") 3 + list(range(2000000)) popRero.timeit(num<er+1000) 4.#21 !60!#120"2"! 3 + list(range(2000000)) popend.timeit(num<er+1000) 0.000 1614 0 !###6"1$

hile our $irst test does sho# that pop(0) is indeed slo#er than pop(), it does not validate the claim that pop(0) is '-n. #hile pop() is '-2.= 'o validate that claim #e need to loo, at the !er$ormance o$ both calls over a range o$ list si8es= !isting 11 im!lements this test=
popRero + )imer("3.pop(0)". ":rom 44main44 import 3") popend + )imer("3.pop()". ":rom 44main44 import 3") print("pop(0) pop()") :or i in range(1000000.100000001.1000000)> 3 + list(range(i)) pt + popend.timeit(num<er+1000) 3 + list(range(i)) pR + popRero.timeit(num<er+1000) print("(1!.!:. (1!.!:" ((pR.pt))

Figure 3 sho#s the results o$ our e*!eriment= >ou can see that as the list gets longer and longer the time it ta,es to pop(0) also increases #hile the time $or pop stays very $lat= 'his is e*actly #hat #e #ould e*!ect to see $or a '-n. and '-2. algorithm= Some sources o$ error in our little e*!eriment include the $act that there are other !rocesses running on the com!uter as #e measure that may slo# do#n our code, so even though #e try to minimi8e other things ha!!ening on the com!uter there is bound to be some variation in time= 'hat is #hy the loo! runs the test one thousand times in the $irst !lace to statistically gather enough in$ormation to ma,e the measurement reliable=

D9

Com!aring the %er$ormance o$ pop and pop(0)

Dictionaries
'he second major %ython data structure is the dictionary= +s you !robably recall, dictionaries di$$er $rom lists in that you can access items in a dictionary by a ,ey rather than a !osition= Later in this boo, you #ill see that there are many #ays to im!lement a dictionary= 'he thing that is most im!ortant to notice right no# is that the get item and set item o!erations on a dictionary are '-2.= +nother im!ortant dictionary o!eration is the contains o!eration= Chec,ing to see #hether a ,ey is in the dictionary or not is also '-2.= 'he e$$iciency o$ all dictionary o!erations is summari8ed in Table 3= One im!ortant side note on dictionary !er$ormance is that the e$$iciencies #e !rovide in the table are $or average !er$ormance= In some rare cases the contains, get item, and set item o!erations can degenerate into '-n.

D;

!er$ormance but #e #ill get into that in a later cha!ter #hen #e tal, about the di$$erent #ays that a dictionary could be im!lemented= operation Big&! (%%iciency co!y get item set item delete item O-n. O-2. O-2. O-2.

contains -in. O-2. iteration O-n. HBig4O )$$iciency o$ %ython Dictionary O!erationsI 6or our last !er$ormance e*!eriment #e #ill com!are the !er$ormance o$ the contains o!eration bet#een lists and dictionaries= In the !rocess #e #ill con$irm that the contains o!erator $or lists is '-n. and the contains o!erator $or dictionaries is '-2.= 'he e*!eriment #e #ill use to com!are the t#o is sim!le= e:ll ma,e a list #ith a range o$ numbers in it= 'hen #e #ill !ic, numbers at random and chec, to see i$ the numbers are in the list= I$ our !er$ormance tables are correct the bigger the list the longer it should ta,e to determine i$ any one number is contained in the list= e #ill re!eat the same e*!eriment $or a dictionary that contains numbers as the ,eys= In this e*!eriment #e should see that determining #hether or not a number is in the dictionary is not only much $aster, but the time it ta,es to chec, should remain constant even as the dictionary gro#s larger= !isting 12 im!lements this com!arison= /otice that #e are !er$orming e*actly the same o!eration, num<er in container= 'he di$$erence is that on line D 3 is a list, and on line E 3 is a dictionary=
import timeit import random :or i in range(10000.1000001.20000)> t + timeit.)imer("random.randrange((d) in 3"(i. ":rom 44main44 import random.3") 3 + list(range(i)) lst4time + t.timeit(num<er+1000) 3 + BA>7one :or A in range(i)C d4time + t.timeit(num<er+1000) print("(d.(10. :.(10. :" ( (i. lst4time. d4time))

Figure 4 summari8es the results o$ running !isting 12= >ou can see that the dictionary is consistently $aster= 6or the smallest list si8e o$ 2G,GGG elements a dictionary is FE=< times $aster than a list= 6or the largest list si8e o$ EEG,GGG elements the dictionary is 22,CG; times $asterR >ou can also see that the time it ta,es $or the contains o!erator on the list gro#s linearly #ith the si8e o$ the list= 'his veri$ies the assertion that the contains o!erator on a list is '-n.= It can also be seen that the time $or the contains o!erator on a dictionary is constant even as the dictionary si8e gro#s= In $act $or a dictionary si8e o$ 2G,GGG the contains

D<

o!eration too, G=GG< milliseconds and $or the dictionary si8e o$ EEG,GGG it also too, G=GG< milliseconds=

Com!aring the in O!erator $or %ython Lists and Dictionaries Since %ython is an evolving language, there are al#ays changes going on behind the scenes= 'he latest in$ormation on the !er$ormance o$ %ython data structures can be $ound on the %ython #ebsite= +s o$ this #riting the %ython #i,i has a nice time com!le*ity !age that can be $ound at http>''Fi=i.p0thon.org'moin')imeJomple3it0= Sel$ Chec, hich o$ the above list o!erations is not O-2."

DB

a. list=!o!-G. b. list=!o!-. c. list=a!!end-. d. listS2GT e. all o$ the above are O-2. hich o$ the above dictionary o!erations is O-2." a. X*X in mydict b. del mydictSX*XT c. mydictSX*XT PP 2G d. mydictSX*XT P mydictSX*XT K 2 e. all o$ the above are O-2.

Summary

+lgorithm analysis is an im!lementation4inde!endent #ay o$ measuring an algorithm= Big4O notation allo#s algorithms to be classi$ied by their dominant !rocess #ith res!ect to the si8e o$ the !roblem=

1ey Terms
average case Big4O notation brute $orce chec,ing o$$ e*!onential log linear 3uadratic logarithmic linear order o$ magnitude

time com!le*ity #orst case

Discussion 2uestions
2= Give the Big4O !er$ormance o$ the $ollo#ing code $ragment0
2. :or i in range(n)> . :or A in range(n)>

DC

4.

= + 2 % 2

B= Give the Big4O !er$ormance o$ the $ollo#ing code $ragment0


6. :or i in range(n)> ". = + 2 % 2

F= Give the Big4O !er$ormance o$ the $ollo#ing code $ragment0


$. i + n 10. Fhile i > 0> 11. = + 2 % 2 12. i + i '' 2

2;= Give the Big4O !er$ormance o$ the $ollo#ing code $ragment0


14. :or i in range(n)> 1!. :or A in range(n)> 16. :or = in range(n)> 1". = + 2 % 2

2F= Give the Big4O !er$ormance o$ the $ollo#ing code $ragment0


1$. i + n 20. Fhile i > 0> 21. = + 2 % 2 22. i + i '' 2

9;= Give the Big4O !er$ormance o$ the $ollo#ing code $ragment0


24. :or i in range(n)> 2!. = + 2 % 2 26. :or A in range(n)> 2". = + 2 % 2 2#. :or = in range(n)> 2$. = + 2 % 2

Programming ()ercises
2= Devise an e*!eriment to veri$y that the list inde* o!erator is '-2. 9= Devise an e*!eriment to veri$y that get item and set item are '-2. $or dictionaries= ;= Devise an e*!eriment that com!ares the !er$ormance o$ the del o!erator on lists and dictionaries= <= Given a list o$ numbers in random order #rite a linear time algorithm to $ind the ,th smallest number in the list= )*!lain #hy your algorithm is linear= B= Can you im!rove the algorithm $rom the !revious !roblem to be 'nlog-n."

DD

Basic Data Structures


!b"ectives

'o understand the abstract data ty!es stac,, 3ueue, de3ue, and list= 'o be able to im!lement the +D's stac,, 3ueue, and de3ue using %ython lists= 'o understand the !er$ormance o$ the im!lementations o$ basic linear data structures= 'o understand !re$i*, in$i*, and !ost$i* e*!ression $ormats= 'o use stac,s to evaluate !ost$i* e*!ressions= 'o use stac,s to convert e*!ressions $rom in$i* to !ost$i*= 'o use 3ueues $or basic timing simulations= 'o be able to recogni8e !roblem !ro!erties #here stac,s, 3ueues, and de3ues are a!!ro!riate data structures= 'o be able to im!lement the abstract data ty!e list as a lin,ed list using the node and re$erence !attern= 'o be able to com!are the !er$ormance o$ our lin,ed list im!lementation #ith %ython:s list im!lementation=

What Are /inear Structures$


e #ill begin our study o$ data structures by considering $our sim!le but very !o#er$ul conce!ts= Stac,s, 3ueues, de3ues, and lists are e*am!les o$ data collections #hose items are ordered de!ending on ho# they are added or removed= Once an item is added, it stays in that !osition relative to the other elements that came be$ore and came a$ter it= Collections such as these are o$ten re$erred to as linear data structures= Linear structures can be thought o$ as having t#o ends= Sometimes these ends are re$erred to as the ?le$t@ and the ?right@ or in some cases the ?$ront@ and the ?rear=@ >ou could also call them the ?to!@ and the ?bottom=@ 'he names given to the ends are not signi$icant= hat distinguishes one linear structure $rom another is the #ay in #hich items are added and removed, in !articular the location #here these additions and removals occur= 6or e*am!le, a structure might allo# ne# items to be added at only one end= Some structures might allo# items to be removed $rom either end= 'hese variations give rise to some o$ the most use$ul data structures in com!uter science= 'hey a!!ear in many algorithms and can be used to solve a variety o$ im!ortant !roblems=

Stac s
What is a Stac $
+ stac -sometimes called a ?!ush4do#n stac,@. is an ordered collection o$ items #here the addition o$ ne# items and the removal o$ e*isting items al#ays ta,es !lace at the same end= 'his end is commonly re$erred to as the ?to!=@ 'he end o!!osite the to! is ,no#n as the ?base=@

DF

'he base o$ the stac, is signi$icant since items stored in the stac, that are closer to the base re!resent those that have been in the stac, the longest= 'he most recently added item is the one that is in !osition to be removed $irst= 'his ordering !rinci!le is sometimes called /I,!, last&in %irst&out= It !rovides an ordering based on length o$ time in the collection= /e#er items are near the to!, #hile older items are near the base= Many e*am!les o$ stac,s occur in everyday situations= +lmost any ca$eteria has a stac, o$ trays or !lates #here you ta,e the one at the to!, uncovering a ne# tray or !late $or the ne*t customer in line= Imagine a stac, o$ boo,s on a des, -Figure 1.= 'he only boo, #hose cover is visible is the one on to!= 'o access others in the stac,, #e need to remove the ones that are sitting on to! o$ them= Figure 2 sho#s another stac,= 'his one contains a number o$ !rimitive %ython data objects=

+ Stac, o$ Boo,s

+ Stac, o$ %rimitive %ython Objects One o$ the most use$ul ideas related to stac,s comes $rom the sim!le observation o$ items as they are added and then removed= +ssume you start out #ith a clean des,to!= /o# !lace boo,s one at a time on to! o$ each other= >ou are constructing a stac,= Consider #hat ha!!ens #hen you begin removing boo,s= 'he order that they are removed is e*actly the reverse o$ the order that they #ere !laced= Stac,s are $undamentally im!ortant, as they can be used to reverse the order o$ items= 'he order o$ insertion is the reverse o$ the order o$ removal= Figure 3 sho#s the %ython data object stac, as it #as created and then again as items are removed= /ote the order o$ the objects=

DE

'he Reversal %ro!erty o$ Stac,s Considering this reversal !ro!erty, you can !erha!s thin, o$ e*am!les o$ stac,s that occur as you use your com!uter= 6or e*am!le, every #eb bro#ser has a Bac, button= +s you navigate $rom #eb !age to #eb !age, those !ages are !laced on a stac, -actually it is the 5RLs that are going on the stac,.= 'he current !age that you are vie#ing is on the to! and the $irst !age you loo,ed at is at the base= I$ you clic, on the Bac, button, you begin to move in reverse order through the !ages=

The Stac Abstract Data Type


'he stac, abstract data ty!e is de$ined by the $ollo#ing structure and o!erations= + stac, is structured, as described above, as an ordered collection o$ items #here items are added to and removed $rom the end called the ?to!=@ Stac,s are ordered LI6O= 'he stac, o!erations are given belo#=

creates a ne# stac, that is em!ty= It needs no !arameters and returns an em!ty stac,= push(item) adds a ne# item to the to! o$ the stac,= It needs the item and returns nothing= pop() removes the to! item $rom the stac,= It needs no !arameters and returns the item= 'he stac, is modi$ied= pee=() returns the to! item $rom the stac, but does not remove it= It needs no !arameters= 'he stac, is not modi$ied= is@mpt0() tests to see #hether the stac, is em!ty= It needs no !arameters and returns a boolean value= siRe() returns the number o$ items on the stac,= It needs no !arameters and returns an integer=
Stac=()

6or e*am!le, i$ s is a stac, that has been created and starts out em!ty, then Table 1 sho#s the results o$ a se3uence o$ stac, o!erations= 5nder stac, contents, the to! item is listed at the $ar right= Stac !peration
s.is@mpt0() -/

Stac #ontents

Return 9alue
)rue

FG

Stac !peration
s.push(4) s.push(6dog6) s.pee=() s.push()rue) s.siRe() s.is@mpt0() s.push(#.4) s.pop() s.pop() s.siRe()

Stac #ontents
-4/ -4.6dog6/ -4.6dog6/ -4.6dog6.)rue/ -4.6dog6.)rue/ -4.6dog6.)rue/ -4.6dog6.)rue.#.4/ -4.6dog6.)rue/ -4.6dog6/ -4.6dog6/

Return 9alue

6dog6

*alse #.4 )rue 2

Sam!le Stac, O!erations

Implementing a Stac in Python


/o# that #e have clearly de$ined the stac, as an abstract data ty!e #e #ill turn our attention to using %ython to im!lement the stac,= Recall that #hen #e give an abstract data ty!e a !hysical im!lementation #e re$er to the im!lementation as a data structure= +s #e described in Cha!ter 2, in %ython, as in any object4oriented !rogramming language, the im!lementation o$ choice $or an abstract data ty!e such as a stac, is the creation o$ a ne# class= 'he stac, o!erations are im!lemented as methods= 6urther, to im!lement a stac,, #hich is a collection o$ elements, it ma,es sense to utili8e the !o#er and sim!licity o$ the !rimitive collections !rovided by %ython= e #ill use a list= Recall that the list class in %ython !rovides an ordered collection mechanism and a set o$ methods= 6or e*am!le, i$ #e have the list S9,B,;,C,D,<T, #e need only to decide #hich end o$ the list #ill be considered the to! o$ the stac, and #hich #ill be the base= Once that decision is made, the o!erations can be im!lemented using the list methods such as append and pop= 'he $ollo#ing stac, im!lementation -!isting 1. assumes that the end o$ the list #ill hold the to! element o$ the stac,= +s the stac, gro#s -as push o!erations occur., ne# items #ill be added on the end o$ the list= pop o!erations #ill mani!ulate that same end=

1 2 4 ! 6 " # $ 10

F2

11 12 1 14 1! 16 1" 1# 1$ 20 class Stac=> de: 44init44(sel:)> sel:.items + -/ de: is@mpt0(sel:)> return sel:.items ++ -/ de: push(sel:. item)> sel:.items.append(item) de: pop(sel:)> return sel:.items.pop() de: pee=(sel:)> return sel:.items-len(sel:.items)51/ de: siRe(sel:)> return len(sel:.items)

-stac,O2.

'he $ollo#ing interactive %ython session sho#s the Stac= class in action as #e !er$orm the se3uence o$ o!erations $rom Table 1=

1 2 4 ! 6 " # $ 10 11 12 1 14

F9

s+Stac=() print(s.is@mpt0()) s.push(4) s.push(6dog6) print(s.pee=()) s.push()rue) print(s.siRe()) print(s.is@mpt0()) s.push(#.4) print(s.pop()) print(s.pop()) print(s.siRe())

-stac,Oe*O2.

It is im!ortant to note that #e could have chosen to im!lement the stac, using a list #here the to! is at the beginning instead o$ at the end= In this case, the !revious pop and append methods #ould no longer #or, and #e #ould have to inde* !osition G -the $irst item in the list. e*!licitly using pop and insert= 'he im!lementation is sho#n in !isting 2= 2 class Stac,0 9 de$ OOinitOO-sel$.0 ; sel$=items P ST < B de$ is)m!ty-sel$.0 C return sel$=items PP ST D F de$ !ush-sel$, item.0 E sel$=items=insert-G,item. 2G 22 de$ !o!-sel$.0 29 return sel$=items=!o!-G. 2; 2< de$ !ee,-sel$.0 2B return sel$=itemsSGT 2C 2D de$ si8e-sel$.0 2F return len-sel$=items. 2E 9G s P Stac,-. 92 s=!ush-XhelloX. 99 s=!ush-XtrueX. 9; !rint-s=!o!-..

F;

Ste! 2 o$ 92 line that has just e*ecuted ne*t line to e*ecute 6rames Objects -stac,OclO2. 'his ability to change the !hysical im!lementation o$ an abstract data ty!e #hile maintaining the logical characteristics is an e*am!le o$ abstraction at #or,= 1o#ever, even though the stac, #ill #or, either #ay, i$ #e consider the !er$ormance o$ the t#o im!lementations, there is de$initely a di$$erence= Recall that the append and pop() o!erations #ere both O-2.= 'his means that the $irst im!lementation #ill !er$orm !ush and !o! in constant time no matter ho# many items are on the stac,= 'he !er$ormance o$ the second im!lementation su$$ers in that the insert(0) and pop(0) o!erations #ill both re3uire O-n. $or a stac, o$ si8e n= Clearly, even though the im!lementations are logically e3uivalent, they #ould have very di$$erent timings #hen !er$orming benchmar, testing= Sel$ Chec,
Ti2en the :olloFing sequence o: stac= operations Fhat is the top item on the stac=V m + Stac=() m.push(636) m.push(606) m.pop()> m.push(6R6) m.pee=()

a. X*X b. XyX c. X8X


Ti2en the :olloFing sequence o: stac= operations. Fhat is the top item on the stac=V m + Stac=() m.push(636) m.push(606) m.push(6R6) Fhile not m.is@mpt0()> m.pop() m.pop()

d. 'he stac, is em!ty

a. X*X b. the stac, is em!ty c. an error #ill occur d. X8X rite a $unction re*string&"+str, that uses a stac, to reverse the characters in a string=

F<

Simple Balanced Parentheses


e no# turn our attention to using stac,s to solve real com!uter science !roblems= >ou have no doubt #ritten arithmetic e*!ressions such as

-BKC.-DKF.M-<K;.
#here !arentheses are used to order the !er$ormance o$ o!erations= >ou may also have some e*!erience !rogramming in a language such as Lis! #ith constructs li,e
(de:un square(n) (& n n))

'his de$ines a $unction called square that #ill return the s3uare o$ its argument n= Lis! is notorious $or using lots and lots o$ !arentheses= In both o$ these e*am!les, !arentheses must a!!ear in a balanced $ashion= Balanced parentheses means that each o!ening symbol has a corres!onding closing symbol and the !airs o$ !arentheses are !ro!erly nested= Consider the $ollo#ing correctly balanced strings o$ !arentheses0
(()()()()) (((()))) (()((())()))

Com!are those #ith the $ollo#ing, #hich are not balanced0


((((((()) ())) (()()(()

'he ability to di$$erentiate bet#een !arentheses that are correctly balanced and those that are unbalanced is an im!ortant !art o$ recogni8ing many !rogramming language structures=

FB

'he challenge then is to #rite an algorithm that #ill read a string o$ !arentheses $rom le$t to right and decide #hether the symbols are balanced= 'o solve this !roblem #e need to ma,e an im!ortant observation= +s you !rocess symbols $rom le$t to right, the most recent o!ening !arenthesis must match the ne*t closing symbol -see Figure 4.= +lso, the $irst o!ening symbol !rocessed may have to #ait until the very last symbol $or its match= Closing symbols match o!ening symbols in the reverse order o$ their a!!earanceU they match $rom the inside out= 'his is a clue that stac,s can be used to solve the !roblem=

Matching %arentheses Once you agree that a stac, is the a!!ro!riate data structure $or ,ee!ing the !arentheses, the statement o$ the algorithm is straight$or#ard= Starting #ith an em!ty stac,, !rocess the !arenthesis strings $rom le$t to right= I$ a symbol is an o!ening !arenthesis, !ush it on the stac, as a signal that a corres!onding closing symbol needs to a!!ear later= I$, on the other hand, a symbol is a closing !arenthesis, !o! the stac,= +s long as it is !ossible to !o! the stac, to match every closing symbol, the !arentheses remain balanced= I$ at any time there is no o!ening symbol on the stac, to match a closing symbol, the string is not balanced !ro!erly= +t the end o$ the string, #hen all symbols have been !rocessed, the stac, should be em!ty= 'he %ython code to im!lement this algorithm is sho#n in !isting 3=

1 2 4 ! 6 " # $ 10 11 12 1 14 1! 16 1" 1# 1$ 20 21 22

FC

2 24 2! 26 2" :rom p0thonds.<asic.stac= import Stac= de: parJhec=er(s0m<olString)> s + Stac=() <alanced + )rue inde3 + 0 Fhile inde3 , len(s0m<olString) and <alanced> s0m<ol + s0m<olString-inde3/ i: s0m<ol ++ "("> s.push(s0m<ol) else> i: s.is@mpt0()> <alanced + *alse else> s.pop() inde3 + inde3 % 1 i: <alanced and s.is@mpt0()> return )rue else> return *alse print(parJhec=er(6((()))6)) print(parJhec=er(6(()6))

-!archec,2.

'his $unction, parJhec=er, assumes that a Stac= class is available and returns a boolean result as to #hether the string o$ !arentheses is balanced= /ote that the boolean variable <alanced is initiali8ed to )rue as there is no reason to assume other#ise at the start= I$ the current symbol is (, then it is !ushed on the stac, -lines EA2G.= /ote also in line 2B that pop sim!ly removes a symbol $rom the stac,= 'he returned value is not used since #e ,no# it must be an o!ening symbol seen earlier= +t the end -lines 2EA99., as long as the e*!ression is balanced and the stac, has been com!letely cleaned o$$, the string re!resents a correctly balanced se3uence o$ !arentheses=

Balanced Symbols 3A General #ase4


'he balanced !arentheses !roblem sho#n above is a s!eci$ic case o$ a more general situation that arises in many !rogramming languages= 'he general !roblem o$ balancing and nesting di$$erent ,inds o$ o!ening and closing symbols !ro!erly occurs $re3uently= 6or e*am!le, in %ython s3uare brac,ets, S and T, are used $or listsU curly braces, H and I, are used $or dictionariesU and !arentheses, - and ., are used $or tu!les and arithmetic e*!ressions= It is

FD

!ossible to mi* symbols as long as each maintains its o#n o!en and close relationshi!= Strings o$ symbols such as
B B ( - / - / ) C ( ) C - - B B ( ( ) ) C C / / - / - / - / ( ) B C

are !ro!erly balanced in that not only does each o!ening symbol have a corres!onding closing symbol, but the ty!es o$ symbols match as #ell= Com!are those #ith the $ollo#ing strings that are not balanced0
( - ) / ( ( ( ) / ) ) - B ( ) /

'he sim!le !arentheses chec,er $rom the !revious section can easily be e*tended to handle these ne# ty!es o$ symbols= Recall that each o!ening symbol is sim!ly !ushed on the stac, to #ait $or the matching closing symbol to a!!ear later in the se3uence= hen a closing symbol does a!!ear, the only di$$erence is that #e must chec, to be sure that it correctly matches the ty!e o$ the o!ening symbol on to! o$ the stac,= I$ the t#o symbols do not match, the string is not balanced= Once again, i$ the entire string is !rocessed and nothing is le$t on the stac,, the string is correctly balanced= 'he %ython !rogram to im!lement this is sho#n in !isting 4= 'he only change a!!ears in line 2D #here #e call a hel!er $unction to assist #ith symbol4matching= )ach symbol that is removed $rom the stac, must be chec,ed to see that it matches the current closing symbol= I$ a mismatch occurs, the boolean variable <alanced is set to *alse=

1 2 4 ! 6 " # $ 10 11 12 1 14 1! 16 1" 1#

FF

1$ 20 21 22 2 24 2! 26 2" 2# :rom p0thonds.<asic.stac= import Stac= de: parJhec=er(s0m<olString)> s + Stac=() <alanced + )rue inde3 + 0 Fhile inde3 , len(s0m<olString) and <alanced> s0m<ol + s0m<olString-inde3/ i: s0m<ol in "(-B"> s.push(s0m<ol) else> i: s.is@mpt0()> <alanced + *alse else> top + s.pop() i: not matches(top.s0m<ol)> <alanced + *alse inde3 + inde3 % 1 i: <alanced and s.is@mpt0()> return )rue else> return *alse de: matches(open.close)> opens + "(-B" closers + ")/C" return opens.inde3(open) ++ closers.inde3(close)

-!archec,9.

'hese t#o e*am!les sho# that stac,s are very im!ortant data structures $or the !rocessing o$ language constructs in com!uter science= +lmost any notation you can thin, o$ has some ty!e o$ nested symbol that must be matched in a balanced order= 'here are a number o$ other im!ortant uses $or stac,s in com!uter science= e #ill continue to e*!lore them ne*t=

#onverting Decimal 'umbers to Binary 'umbers


In your study o$ com!uter science, you have !robably been e*!osed in one #ay or another to the idea o$ a binary number= Binary re!resentation is im!ortant in com!uter science since all values stored #ithin a com!uter e*ist as a string o$ binary digits, a string o$ Gs and 2s=

FE

ithout the ability to convert bac, and $orth bet#een common re!resentations and binary numbers, #e #ould need to interact #ith com!uters in very a#,#ard #ays= Integer values are common data items= 'hey are used in com!uter !rograms and com!utation all the time= e learn about them in math class and o$ course re!resent them using the decimal number system, or base 2G= 'he decimal number 9;;2G and its corres!onding binary e3uivalent 222G2GG29 are inter!reted res!ectively as

9c2G9K;c2G2K;c2GG
and

2c9DK2c9CK2c9BKGc9<K2c9;KGc99KGc92K2c9G
But ho# can #e easily convert integer values into binary numbers" 'he ans#er is an algorithm called ?Divide by 9@ that uses a stac, to ,ee! trac, o$ the digits $or the binary result= 'he Divide by 9 algorithm assumes that #e start #ith an integer greater than G= + sim!le iteration then continually divides the decimal number by 9 and ,ee!s trac, o$ the remainder= 'he $irst division by 9 gives in$ormation as to #hether the value is even or odd= +n even value #ill have a remainder o$ G= It #ill have the digit G in the ones !lace= +n odd value #ill have a remainder o$ 2 and #ill have the digit 2 in the ones !lace= e thin, about building our binary number as a se3uence o$ digitsU the $irst remainder #e com!ute #ill actually be the last digit in the se3uence= +s sho#n in Figure 5, #e again see the reversal !ro!erty that signals that a stac, is li,ely to be the a!!ro!riate data structure $or solving the !roblem=

Decimal4to4Binary Conversion 'he %ython code in !isting 5 im!lements the Divide by 9 algorithm= 'he $unction di2ideP02 ta,es an argument that is a decimal number and re!eatedly divides it by 9= Line C uses the built4in modulo o!erator, N, to e*tract the remainder and line D then !ushes it on the stac,= +$ter the division !rocess reaches G, a binary string is constructed in lines 2GA29= Line 2G

EG

creates an em!ty string= 'he binary digits are !o!!ed $rom the stac, one at a time and a!!ended to the right4hand end o$ the string= 'he binary string is then returned=

1 2 4 ! 6 " # $ 10 11 12 1 14 1! 16 1" 1# :rom p0thonds.<asic.stac= import Stac= de: di2ideP02(dec7um<er)> remstac= + Stac=() Fhile dec7um<er > 0> rem + dec7um<er ( 2 remstac=.push(rem) dec7um<er + dec7um<er '' 2 <inString + "" Fhile not remstac=.is@mpt0()> <inString + <inString % str(remstac=.pop()) return <inString print(di2ideP02(42))

-divby9.

'he algorithm $or binary conversion can easily be e*tended to !er$orm the conversion $or any base= In com!uter science it is common to use a number o$ di$$erent encodings= 'he most common o$ these are binary, octal -base F., and he*adecimal -base 2C.= 'he decimal number 9;; and its corres!onding octal and he*adecimal e3uivalents ;B2F and -E2C are inter!reted as E2

;cF9KBcF2K2cFG
and

2Bc2C2KEc2CG
'he $unction di2ideP02 can be modi$ied to acce!t not only a decimal value but also a base $or the intended conversion= 'he ?Divide by 9@ idea is sim!ly re!laced #ith a more general ?Divide by base=@ + ne# $unction called <aseJon2erter, sho#n in !isting 6, ta,es a decimal number and any base bet#een 9 and 2C as !arameters= 'he remainders are still !ushed onto the stac, until the value being converted becomes G= 'he same le$t4to4right string construction techni3ue can be used #ith one slight change= Base 9 through base 2G numbers need a ma*imum o$ 2G digits, so the ty!ical digit characters G, 2, 9, ;, <, B, C, D, F, and E #or, $ine= 'he !roblem comes #hen #e go beyond base 2G= e can no longer sim!ly use the remainders, as they are themselves re!resented as t#o4digit decimal numbers= Instead #e need to create a set o$ digits that can be used to re!resent those remainders beyond E=

1 2 4 ! 6 " # $ 10 11 12 1 14 1! 16 1" 1# 1$ 20 :rom p0thonds.<asic.stac= import Stac= de: <aseJon2erter(dec7um<er.<ase)> digits + "012 4!6"#$APJD@*" remstac= + Stac=() Fhile dec7um<er > 0> rem + dec7um<er ( <ase remstac=.push(rem) dec7um<er + dec7um<er '' <ase neFString + "" Fhile not remstac=.is@mpt0()> neFString + neFString % digits-remstac=.pop()/

E9

return neFString print(<aseJon2erter(2!.2))

-baseconvert.

+ solution to this !roblem is to e*tend the digit set to include some al!habet characters= 6or e*am!le, he*adecimal uses the ten decimal digits along #ith the $irst si* al!habet characters $or the 2C digits= 'o im!lement this, a digit string is created -line ; in !isting 6. that stores the digits in their corres!onding !ositions= G is at !osition G, 2 is at !osition 2, + is at !osition 2G, B is at !osition 22, and so on= hen a remainder is removed $rom the stac,, it can be used to inde* into the digit string and the correct resulting digit can be a!!ended to the ans#er= 6or e*am!le, i$ the remainder 2; is removed $rom the stac,, the digit D is a!!ended to the resulting string= Sel$ Chec, hat is value o$ 9B e*!ressed as an octal number -base F. hat is value o$ 9BC e*!ressed as a he*idecimal number -base 2C. hat is value o$ 9C e*!ressed in base 9C

In%i): Pre%i) and Post%i) ()pressions


hen you #rite an arithmetic e*!ression such as B L C, the $orm o$ the e*!ression !rovides you #ith in$ormation so that you can inter!ret it correctly= In this case #e ,no# that the variable B is being multi!lied by the variable C since the multi!lication o!erator L a!!ears bet#een them in the e*!ression= 'his ty!e o$ notation is re$erred to as in%i) since the o!erator is in bet een the t#o o!erands that it is #or,ing on=

E;

Consider another in$i* e*am!le, + K B L C= 'he o!erators K and L still a!!ear bet#een the o!erands, but there is a !roblem= hich o!erands do they #or, on" Does the K #or, on + and B or does the L ta,e B and C" 'he e*!ression seems ambiguous= In $act, you have been reading and #riting these ty!es o$ e*!ressions $or a long time and they do not cause you any !roblem= 'he reason $or this is that you ,no# something about the o!erators K and L= )ach o!erator has a precedence level= O!erators o$ higher !recedence are used be$ore o!erators o$ lo#er !recedence= 'he only thing that can change that order is the !resence o$ !arentheses= 'he !recedence order $or arithmetic o!erators !laces multi!lication and division above addition and subtraction= I$ t#o o!erators o$ e3ual !recedence a!!ear, then a le$t4to4right ordering or associativity is used= Let:s inter!ret the troublesome e*!ression + K B L C using o!erator !recedence= B and C are multi!lied $irst, and + is then added to that result= -+ K B. L C #ould $orce the addition o$ + and B to be done $irst be$ore the multi!lication= In e*!ression + K B K C, by !recedence -via associativity., the le$tmost K #ould be done $irst= +lthough all this may be obvious to you, remember that com!uters need to ,no# e*actly #hat o!erators to !er$orm and in #hat order= One #ay to #rite an e*!ression that guarantees there #ill be no con$usion #ith res!ect to the order o$ o!erations is to create #hat is called a %ully parenthesi;ed e*!ression= 'his ty!e o$ e*!ression uses one !air o$ !arentheses $or each o!erator= 'he !arentheses dictate the order o$ o!erationsU there is no ambiguity= 'here is also no need to remember any !recedence rules= 'he e*!ression + K B L C K D can be re#ritten as --+ K -B L C.. K D. to sho# that the multi!lication ha!!ens $irst, $ollo#ed by the le$tmost addition= + K B K C K D can be #ritten as ---+ K B. K C. K D. since the addition o!erations associate $rom le$t to right= 'here are t#o other very im!ortant e*!ression $ormats that may not seem obvious to you at $irst= Consider the in$i* e*!ression + K B= hat #ould ha!!en i$ #e moved the o!erator be$ore the t#o o!erands" 'he resulting e*!ression #ould be K + B= Li,e#ise, #e could move the o!erator to the end= e #ould get + B K= 'hese loo, a bit strange= 'hese changes to the !osition o$ the o!erator #ith res!ect to the o!erands create t#o ne# e*!ression $ormats, pre%i) and post%i)= %re$i* e*!ression notation re3uires that all o!erators !recede the t#o o!erands that they #or, on= %ost$i*, on the other hand, re3uires that its o!erators come a$ter the corres!onding o!erands= + $e# more e*am!les should hel! to ma,e this a bit clearer -see Table 2.= + K B L C #ould be #ritten as K + L B C in !re$i*= 'he multi!lication o!erator comes immediately be$ore the o!erands B and C, denoting that L has !recedence over K= 'he addition o!erator then a!!ears be$ore the + and the result o$ the multi!lication= In !ost$i*, the e*!ression #ould be + B C L K= +gain, the order o$ o!erations is !reserved since the L a!!ears immediately a$ter the B and the C, denoting that L has !recedence, #ith K coming a$ter= +lthough the o!erators moved and no# a!!ear either be$ore or a$ter their res!ective o!erands, the order o$ the o!erands stayed e*actly the same relative to one another=

E<

In%i) ()pression Pre%i) ()pression Post%i) ()pression +KB K+B +BK +KBLC K+LBC +BCLK )*am!les o$ In$i*, %re$i*, and %ost$i* /o# consider the in$i* e*!ression -+ K B. L C= Recall that in this case, in$i* re3uires the !arentheses to $orce the !er$ormance o$ the addition be$ore the multi!lication= 1o#ever, #hen + K B #as #ritten in !re$i*, the addition o!erator #as sim!ly moved be$ore the o!erands, K + B= 'he result o$ this o!eration becomes the $irst o!erand $or the multi!lication= 'he multi!lication o!erator is moved in $ront o$ the entire e*!ression, giving us L K + B C= Li,e#ise, in !ost$i* + B K $orces the addition to ha!!en $irst= 'he multi!lication can be done to that result and the remaining o!erand C= 'he !ro!er !ost$i* e*!ression is then + B K C L= Consider these three e*!ressions again -see Table 3.= Something very im!ortant has ha!!ened= here did the !arentheses go" hy don:t #e need them in !re$i* and !ost$i*" 'he ans#er is that the o!erators are no longer ambiguous #ith res!ect to the o!erands that they #or, on= Only in$i* notation re3uires the additional symbols= 'he order o$ o!erations #ithin !re$i* and !ost$i* e*!ressions is com!letely determined by the !osition o$ the o!erator and nothing else= In many #ays, this ma,es in$i* the least desirable notation to use= In%i) ()pression Pre%i) ()pression Post%i) ()pression -+ K B. L C LK+BC +n )*!ression #ith %arentheses +BKCL

Table 4 sho#s some additional e*am!les o$ in$i* e*!ressions and the e3uivalent !re$i* and !ost$i* e*!ressions= Be sure that you understand ho# they are e3uivalent in terms o$ the order o$ the o!erations being !er$ormed= In%i) ()pression Pre%i) ()pression Post%i) ()pression +KBLCKD +LBKCLD KK+LBCD KL+BLCD +BCLKDK +BKCDKL +BLCDLK -+ K B. L -C K D. L K + B K C D

+KBKCKD KKK+BCD +BKCKDK +dditional )*am!les o$ In$i*, %re$i*, and %ost$i*

#onversion o% In%i) ()pressions to Pre%i) and Post%i)


So $ar, #e have used ad hoc methods to convert bet#een in$i* e*!ressions and the e3uivalent !re$i* and !ost$i* e*!ression notations= +s you might e*!ect, there are algorithmic #ays to !er$orm the conversion that allo# any e*!ression o$ any com!le*ity to be correctly trans$ormed= 'he $irst techni3ue that #e #ill consider uses the notion o$ a $ully !arenthesi8ed e*!ression that #as discussed earlier= Recall that + K B L C can be #ritten as -+ K -B L C.. to sho# e*!licitly that the multi!lication has !recedence over the addition= On closer observation,

EB

ho#ever, you can see that each !arenthesis !air also denotes the beginning and the end o$ an o!erand !air #ith the corres!onding o!erator in the middle= Loo, at the right !arenthesis in the sube*!ression -B L C. above= I$ #e #ere to move the multi!lication symbol to that !osition and remove the matching le$t !arenthesis, giving us B C L, #e #ould in e$$ect have converted the sube*!ression to !ost$i* notation= I$ the addition o!erator #ere also moved to its corres!onding right !arenthesis !osition and the matching le$t !arenthesis #ere removed, the com!lete !ost$i* e*!ression #ould result -see Figure 6.=

Moving O!erators to the Right $or %ost$i* /otation I$ #e do the same thing but instead o$ moving the symbol to the !osition o$ the right !arenthesis, #e move it to the le$t, #e get !re$i* notation -see Figure 7.= 'he !osition o$ the !arenthesis !air is actually a clue to the $inal !osition o$ the enclosed o!erator=

Moving O!erators to the Le$t $or %re$i* /otation So in order to convert an e*!ression, no matter ho# com!le*, to either !re$i* or !ost$i* notation, $ully !arenthesi8e the e*!ression using the order o$ o!erations= 'hen move the enclosed o!erator to the !osition o$ either the le$t or the right !arenthesis de!ending on #hether you #ant !re$i* or !ost$i* notation= 1ere is a more com!le* e*!ression0 -+ K B. L C 4 -D 4 ). L -6 K G.= Figure 8 sho#s the conversion to !ost$i* and !re$i* notations=

Converting a Com!le* )*!ression to %re$i* and %ost$i* /otations

General In%i)&to&Post%i) #onversion


e need to develo! an algorithm to convert any in$i* e*!ression to a !ost$i* e*!ression= 'o do this #e #ill loo, closer at the conversion !rocess=

EC

Consider once again the e*!ression + K B L C= +s sho#n above, + B C L K is the !ost$i* e3uivalent= e have already noted that the o!erands +, B, and C stay in their relative !ositions= It is only the o!erators that change !osition= Let:s loo, again at the o!erators in the in$i* e*!ression= 'he $irst o!erator that a!!ears $rom le$t to right is K= 1o#ever, in the !ost$i* e*!ression, K is at the end since the ne*t o!erator, L, has !recedence over addition= 'he order o$ the o!erators in the original e*!ression is reversed in the resulting !ost$i* e*!ression= +s #e !rocess the e*!ression, the o!erators have to be saved some#here since their corres!onding right o!erands are not seen yet= +lso, the order o$ these saved o!erators may need to be reversed due to their !recedence= 'his is the case #ith the addition and the multi!lication in this e*am!le= Since the addition o!erator comes be$ore the multi!lication o!erator and has lo#er !recedence, it needs to a!!ear a$ter the multi!lication o!erator is used= Because o$ this reversal o$ order, it ma,es sense to consider using a stac, to ,ee! the o!erators until they are needed= hat about -+ K B. L C" Recall that + B K C L is the !ost$i* e3uivalent= +gain, !rocessing this in$i* e*!ression $rom le$t to right, #e see K $irst= In this case, #hen #e see L, K has already been !laced in the result e*!ression because it has !recedence over L by virtue o$ the !arentheses= e can no# start to see ho# the conversion algorithm #ill #or,= hen #e see a le$t !arenthesis, #e #ill save it to denote that another o!erator o$ high !recedence #ill be coming= 'hat o!erator #ill need to #ait until the corres!onding right !arenthesis a!!ears to denote its !osition -recall the $ully !arenthesi8ed techni3ue.= hen that right !arenthesis does a!!ear, the o!erator can be !o!!ed $rom the stac,= +s #e scan the in$i* e*!ression $rom le$t to right, #e #ill use a stac, to ,ee! the o!erators= 'his #ill !rovide the reversal that #e noted in the $irst e*am!le= 'he to! o$ the stac, #ill al#ays be the most recently saved o!erator= henever #e read a ne# o!erator, #e #ill need to consider ho# that o!erator com!ares in !recedence #ith the o!erators, i$ any, already on the stac,= +ssume the in$i* e*!ression is a string o$ to,ens delimited by s!aces= 'he o!erator to,ens are L, M, K, and 4, along #ith the le$t and right !arentheses, - and .= 'he o!erand to,ens are the single4character identi$iers +, B, C, and so on= 'he $ollo#ing ste!s #ill !roduce a string o$ to,ens in !ost$i* order= 2= Create an em!ty stac, called opstac= $or ,ee!ing o!erators= Create an em!ty list $or out!ut= 9= Convert the in!ut in$i* string to a list by using the string method split= ;= Scan the to,en list $rom le$t to right= o I$ the to,en is an o!erand, a!!end it to the end o$ the out!ut list= o I$ the to,en is a le$t !arenthesis, !ush it on the opstac== o I$ the to,en is a right !arenthesis, !o! the opstac= until the corres!onding le$t !arenthesis is removed= +!!end each o!erator to the end o$ the out!ut list= o I$ the to,en is an o!erator, L, M, K, or 4, !ush it on the opstac== 1o#ever, $irst remove any o!erators already on the opstac= that have higher or e3ual !recedence and a!!end them to the out!ut list= <= hen the in!ut e*!ression has been com!letely !rocessed, chec, the opstac== +ny o!erators still on the stac, can be removed and a!!ended to the end o$ the out!ut list=

ED

Figure # sho#s the conversion algorithm #or,ing on the e*!ression + L B K C L D= /ote that the $irst L o!erator is removed u!on seeing the K o!erator= +lso, K stays on the stac, #hen the second L occurs, since multi!lication has !recedence over addition= +t the end o$ the in$i* e*!ression the stac, is !o!!ed t#ice, removing both o!erators and !lacing K as the last o!erator in the !ost$i* e*!ression=

Converting + L B K C L D to %ost$i* /otation In order to code the algorithm in %ython, #e #ill use a dictionary called prec to hold the !recedence values $or the o!erators= 'his dictionary #ill ma! each o!erator to an integer that can be com!ared against the !recedence levels o$ other o!erators -#e have arbitrarily used the integers ;, 9, and 2.= 'he le$t !arenthesis #ill receive the lo#est value !ossible= 'his #ay any o!erator that is com!ared against it #ill have higher !recedence and #ill be !laced on to! o$ it= /ote that #e have also im!orted the string module #hich contains a number o$ !rede$ined variables= In this case #e are using a string containing all !ossible u!!er4case al!habet characters -Hstring=asciiOu!!ercaseI. to re!resent all !ossible o!erands= 'he com!lete conversion $unction is sho#n in !isting 7=

1 2 4 ! 6 " # $ 10 11 12 1 14 1! 16 1" 1# 1$ 20

EF

21 22 2 24 2! 26 2" 2# 2$ 0 1 2 4 ! 6 " :rom p0thonds.<asic.stac= import Stac= de: in:i3)oNost:i3(in:i3e3pr)> prec + BC prec-"&"/ + prec-"'"/ + prec-"%"/ + 2 prec-"5"/ + 2 prec-"("/ + 1 opStac= + Stac=() post:i31ist + -/ to=en1ist + in:i3e3pr.split() :or to=en in to=en1ist> i: to=en in "APJD@*TO9WU1G7KNXLS)I8H;MY" or to=en in "012 4!6"#$"> post:i31ist.append(to=en) eli: to=en ++ 6(6> opStac=.push(to=en) eli: to=en ++ 6)6> top)o=en + opStac=.pop() Fhile top)o=en Q+ 6(6> post:i31ist.append(top)o=en) top)o=en + opStac=.pop() else> Fhile (not opStac=.is@mpt0()) and S (prec-opStac=.pee=()/ >+ prec-to=en/)> post:i31ist.append(opStac=.pop()) opStac=.push(to=en) Fhile not opStac=.is@mpt0()> post:i31ist.append(opStac=.pop()) return " ".Aoin(post:i31ist) print(in:i3)oNost:i3("A & P % J & D")) print(in:i3)oNost:i3("( A % P ) & J 5 ( D 5 @ ) & ( * % T )"))

Converting In$i* )*!ressions to %ost$i* )*!ressions -into!ost.

EE

+ $e# e*am!les o$ e*ecution in the %ython shell are sho#n belo#=


>>> in:i3topost:i3("( A % P ) & ( J % D )") 6A P % J D % &6 >>> in:i3topost:i3("( A % P ) & J") 6A P % J &6 >>> in:i3topost:i3("A % P & J") 6A P J & %6 >>>

Post%i) (valuation
+s a $inal stac, e*am!le, #e #ill consider the evaluation o$ an e*!ression that is already in !ost$i* notation= In this case, a stac, is again the data structure o$ choice= 1o#ever, as you scan the !ost$i* e*!ression, it is the o!erands that must #ait, not the o!erators as in the conversion algorithm above= +nother #ay to thin, about the solution is that #henever an o!erator is seen on the in!ut, the t#o most recent o!erands #ill be used in the evaluation= 'o see this in more detail, consider the !ost$i* e*!ression 4 ! 6 & %= +s you scan the e*!ression $rom le$t to right, you $irst encounter the o!erands < and B= +t this !oint, you are still unsure #hat to do #ith them until you see the ne*t symbol= %lacing each on the stac, ensures that they are available i$ an o!erator comes ne*t= In this case, the ne*t symbol is another o!erand= So, as be$ore, !ush it and chec, the ne*t symbol= /o# #e see an o!erator, L= 'his means that the t#o most recent o!erands need to be used in a multi!lication o!eration= By !o!!ing the stac, t#ice, #e can get the !ro!er o!erands and then !er$orm the multi!lication -in this case getting the result ;G.= e can no# handle this result by !lacing it bac, on the stac, so that it can be used as an o!erand $or the later o!erators in the e*!ression= hen the $inal o!erator is !rocessed, there #ill be only one value le$t on the stac,= %o! and return it as the result o$ the e*!ression= Figure 1$ sho#s the stac, contents as this entire e*am!le e*!ression is being !rocessed=

Stac, Contents During )valuation Figure 11 sho#s a slightly more com!le* e*am!le, D F K ; 9 K M= 'here are t#o things to note in this e*am!le= 6irst, the stac, si8e gro#s, shrin,s, and then gro#s again as the sube*!ressions are evaluated= Second, the division o!eration needs to be handled care$ully= 2GG

Recall that the o!erands in the !ost$i* e*!ression are in their original order since !ost$i* changes only the !lacement o$ o!erators= hen the o!erands $or the division are !o!!ed $rom the stac,, they are reversed= Since division is not a commutative o!erator, in other #ords 2BMB is not the same as BM2B, #e must be sure that the order o$ the o!erands is not s#itched=

+ More Com!le* )*am!le o$ )valuation +ssume the !ost$i* e*!ression is a string o$ to,ens delimited by s!aces= 'he o!erators are L, M, K, and 4 and the o!erands are assumed to be single4digit integer values= 'he out!ut #ill be an integer result= 2= Create an em!ty stac, called operandStac== 9= Convert the string to a list by using the string method split= ;= Scan the to,en list $rom le$t to right= o I$ the to,en is an o!erand, convert it $rom a string to an integer and !ush the value onto the operandStac== o I$ the to,en is an o!erator, L, M, K, or 4, it #ill need t#o o!erands= %o! the operandStac= t#ice= 'he $irst !o! is the second o!erand and the second !o! is the $irst o!erand= %er$orm the arithmetic o!eration= %ush the result bac, on the operandStac== <= hen the in!ut e*!ression has been com!letely !rocessed, the result is on the stac,= %o! the operandStac= and return the value= 'he com!lete $unction $or the evaluation o$ !ost$i* e*!ressions is sho#n in !isting 8= 'o assist #ith the arithmetic, a hel!er $unction doGath is de$ined that #ill ta,e t#o o!erands and an o!erator and then !er$orm the !ro!er arithmetic o!eration=

1 2 4 ! 6 "

2G2

# $ 10 11 12 1 14 1! 16 1" 1# 1$ 20 21 22 2 24 2! 26 2" :rom p0thonds.<asic.stac= import Stac= de: post:i3@2al(post:i3@3pr)> operandStac= + Stac=() to=en1ist + post:i3@3pr.split() :or to=en in to=en1ist> i: to=en in "012 4!6"#$"> operandStac=.push(int(to=en)) else> operand2 + operandStac=.pop() operand1 + operandStac=.pop() result + doGath(to=en.operand1.operand2) operandStac=.push(result) return operandStac=.pop() de: doGath(op. op1. op2)> i: op ++ "&"> return op1 & op2 eli: op ++ "'"> return op1 ' op2 eli: op ++ "%"> return op1 % op2 else> return op1 5 op2

%ost$i* )valuation -!ost$i*eval.

It is im!ortant to note that in both the !ost$i* conversion and the !ost$i* evaluation !rograms #e assumed that there #ere no errors in the in!ut e*!ression= 5sing these !rograms as a starting !oint, you can easily see ho# error detection and re!orting can be included= e leave this as an e*ercise at the end o$ the cha!ter=

2G9

Sel$ Chec, ithout using the activecode in$i*'o%ost$i* $unction, convert the $ollo#ing e*!ression to !ost$i* 2G K ; L B M -2C 4 <. 2D 2G K ; L E M PP Modi$y the in$i*'o%ost$i* $unction so that it can convert the $ollo#ing e*!ression0 B L ; b -< 4 9. %aste the ans#er here0

2ueues
e no# turn our attention to another linear data structure= 'his one is called -ueue= Li,e stac,s, 3ueues are relatively sim!le and yet can be used to solve a #ide range o$ im!ortant !roblems=

What Is a 2ueue$
+ 3ueue is an ordered collection o$ items #here the addition o$ ne# items ha!!ens at one end, called the ?rear,@ and the removal o$ e*isting items occurs at the other end, commonly called the ?$ront=@ +s an element enters the 3ueue it starts at the rear and ma,es its #ay to#ard the $ront, #aiting until that time #hen it is the ne*t element to be removed= 'he most recently added item in the 3ueue must #ait at the end o$ the collection= 'he item that has been in the collection the longest is at the $ront= 'his ordering !rinci!le is sometimes called ,I,!, %irst&in %irst&out= It is also ,no#n as ?$irst4come $irst4served=@ 'he sim!lest e*am!le o$ a 3ueue is the ty!ical line that #e all !artici!ate in $rom time to time= e #ait in a line $or a movie, #e #ait in the chec,4out line at a grocery store, and #e #ait in the ca$eteria line -so that #e can !o! the tray stac,.= ell4behaved lines, or 3ueues, are very restrictive in that they have only one #ay in and only one #ay out= 'here is no jum!ing in the middle and no leaving be$ore you have #aited the necessary amount o$ time to get to the $ront= Figure 1 sho#s a sim!le 3ueue o$ %ython data objects=

2G;

+ (ueue o$ %ython Data Objects Com!uter science also has common e*am!les o$ 3ueues= Our com!uter laboratory has ;G com!uters net#or,ed #ith a single !rinter= hen students #ant to !rint, their !rint tas,s ?get in line@ #ith all the other !rinting tas,s that are #aiting= 'he $irst tas, in is the ne*t to be com!leted= I$ you are last in line, you must #ait $or all the other tas,s to !rint ahead o$ you= e #ill e*!lore this interesting e*am!le in more detail later= In addition to !rinting 3ueues, o!erating systems use a number o$ di$$erent 3ueues to control !rocesses #ithin a com!uter= 'he scheduling o$ #hat gets done ne*t is ty!ically based on a 3ueuing algorithm that tries to e*ecute !rograms as 3uic,ly as !ossible and serve as many users as it can= +lso, as #e ty!e, sometimes ,eystro,es get ahead o$ the characters that a!!ear on the screen= 'his is due to the com!uter doing other #or, at that moment= 'he ,eystro,es are being !laced in a 3ueue4li,e bu$$er so that they can eventually be dis!layed on the screen in the !ro!er order=

The 2ueue Abstract Data Type


'he 3ueue abstract data ty!e is de$ined by the $ollo#ing structure and o!erations= + 3ueue is structured, as described above, as an ordered collection o$ items #hich are added at one end, called the ?rear,@ and removed $rom the other end, called the ?$ront=@ (ueues maintain a 6I6O ordering !ro!erty= 'he 3ueue o!erations are given belo#=

creates a ne# 3ueue that is em!ty= It needs no !arameters and returns an em!ty 3ueue= enqueue(item) adds a ne# item to the rear o$ the 3ueue= It needs the item and returns nothing= dequeue() removes the $ront item $rom the 3ueue= It needs no !arameters and returns the item= 'he 3ueue is modi$ied= is@mpt0() tests to see #hether the 3ueue is em!ty= It needs no !arameters and returns a boolean value= siRe() returns the number o$ items in the 3ueue= It needs no !arameters and returns an integer=
Xueue()

+s an e*am!le, i$ #e assume that q is a 3ueue that has been created and is currently em!ty, then Table 1 sho#s the results o$ a se3uence o$ 3ueue o!erations= 'he 3ueue contents are sho#n such that the $ront is on the right= < #as the $irst item en3ueued so it is the $irst item returned by de3ueue= 2ueue !peration
q.is@mpt0() -/

2ueue #ontents

Return 9alue
)rue

2G<

2ueue !peration
q.enqueue(4)

2ueue #ontents
-4/

Return 9alue

q.enqueue(6dog6) -6dog6.4/ q.enqueue()rue) q.siRe() q.is@mpt0() q.enqueue(#.4) q.dequeue() q.dequeue() q.siRe() -)rue.6dog6.4/ -)rue.6dog6.4/ -)rue.6dog6. / -#.4.)rue.6dog6.4/ -#.4.)rue.6dog6/ -#.4.)rue/ -#.4.)rue/ 4 6dog6 2 *alse

)*am!le (ueue O!erations

Implementing a 2ueue in Python


It is again a!!ro!riate to create a ne# class $or the im!lementation o$ the abstract data ty!e 3ueue= +s be$ore, #e #ill use the !o#er and sim!licity o$ the list collection to build the internal re!resentation o$ the 3ueue= e need to decide #hich end o$ the list to use as the rear and #hich to use as the $ront= 'he im!lementation sho#n in !isting 1 assumes that the rear is at !osition G in the list= 'his allo#s us to use the insert $unction on lists to add ne# elements to the rear o$ the 3ueue= 'he pop o!eration can be used to remove the $ront element -the last element o$ the list.= Recall that this also means that en3ueue #ill be O-n. and de3ueue #ill be O-2.=
class Xueue> de: 44init44(sel:)> sel:.items + -/ de: is@mpt0(sel:)> return sel:.items ++ -/ de: enqueue(sel:. item)> sel:.items.insert(0.item) de: dequeue(sel:)> return sel:.items.pop() de: siRe(sel:)> return len(sel:.items)

'he $ollo#ing interactive %ython session sho#s the Xueue class in action as #e !er$orm the se3uence o$ o!erations $rom Table 1= 2 class (ueue0 9 de$ OOinitOO-sel$.0 ; sel$=items P ST < B de$ is)m!ty-sel$.0 C return sel$=items PP ST 2GB

D F de$ en3ueue-sel$, item.0 E sel$=items=insert-G,item. 2G 22 de$ de3ueue-sel$.0 29 return sel$=items=!o!-. 2; 2< de$ si8e-sel$.0 2B return len-sel$=items. 2C 2D 3P(ueue-. 2F 3=is)m!ty-. 2E 9G 3=en3ueue-XdogX. 92 3=en3ueue-<. 99 3P(ueue-. 9; 3=is)m!ty-. 9< 9B 3=en3ueue-<. 9C 3=en3ueue-XdogX. 9D 3=en3ueue-'rue. Ste! 2 o$ ;B line that has just e*ecuted ne*t line to e*ecute 6rames Objects -3u3ueuetest.
>>> q.siRe() >>> q.is@mpt0() *alse >>> q.enqueue(#.4) >>> q.dequeue() 4 >>> q.dequeue() 6dog6 >>> q.siRe() 2

Sel$ Chec, 0
Suppose 0ou ha2e the :olloFing series o: queue operations. q + Xueue() q.enqueue(6hello6)

2GC

q.enqueue(6dog6) q.enqueue( ) q.dequeue() Hhat items are le:t on the queueV

a. XhelloX, XdogX b. XdogX, ; c. XhelloX, ; d. XhelloX, XdogX, ;

Simulation. 0ot Potato


One o$ the ty!ical a!!lications $or sho#ing a 3ueue in action is to simulate a real situation that re3uires data to be managed in a 6I6O manner= 'o begin, let:s consider the children:s game 1ot %otato= In this game -see Figure 2. children line u! in a circle and !ass an item $rom neighbor to neighbor as $ast as they can= +t a certain !oint in the game, the action is sto!!ed and the child #ho has the item -the !otato. is removed $rom the circle= %lay continues until only one child is le$t=

+ Si* %erson Game o$ 1ot %otato 'his game is a modern4day e3uivalent o$ the $amous dose!hus !roblem= Based on a legend about the $amous $irst4century historian 6lavius dose!hus, the story is told that in the de#ish revolt against Rome, dose!hus and ;E o$ his comrades held out against the Romans in a cave= ith de$eat imminent, they decided that they #ould rather die than be slaves to the Romans= 'hey arranged themselves in a circle= One man #as designated as number one, and !roceeding cloc,#ise they ,illed every seventh man= dose!hus, according to the legend, #as among other things an accom!lished mathematician= 1e instantly $igured out #here he ought to sit in order to be the last to go= hen the time came, instead o$ ,illing himsel$, he joined the Roman side= >ou can $ind many di$$erent versions o$ this story= Some count every third man and some allo# the last man to esca!e on a horse= In any case, the idea is the same=

2GD

e #ill im!lement a general simulation o$ 1ot %otato= Our !rogram #ill in!ut a list o$ names and a constant, call it ?num,@ to be used $or counting= It #ill return the name o$ the last !erson remaining a$ter re!etitive counting by num= hat ha!!ens at that !oint is u! to you= 'o simulate the circle, #e #ill use a 3ueue -see Figure 3.= +ssume that the child holding the !otato #ill be at the $ront o$ the 3ueue= 5!on !assing the !otato, the simulation #ill sim!ly de3ueue and then immediately en3ueue that child, !utting her at the end o$ the line= She #ill then #ait until all the others have been at the $ront be$ore it #ill be her turn again= +$ter num de3ueueMen3ueue o!erations, the child at the $ront #ill be removed !ermanently and another cycle #ill begin= 'his !rocess #ill continue until only one name remains -the si8e o$ the 3ueue is 2.=

+ (ueue Im!lementation o$ 1ot %otato 'he !rogram is sho#n in !isting 2= + call to the hotNotato $unction using D as the counting constant returns0

1 2 4 ! 6 " # $ 10 11 12 1 14 1! 16 1" :rom p0thonds.<asic.queue import Xueue

2GF

de: hotNotato(namelist. num)> simqueue + Xueue() :or name in namelist> simqueue.enqueue(name) Fhile simqueue.siRe() > 1> :or i in range(num)> simqueue.enqueue(simqueue.dequeue()) simqueue.dequeue() return simqueue.dequeue() print(hotNotato(-"Pill"."Da2id"."Susan"."Wane"."Uent"."Prad"/."))

1ot %otato Simulation -3ujose!hussim.

/ote that in this e*am!le the value o$ the counting constant is greater than the number o$ names in the list= 'his is not a !roblem since the 3ueue acts li,e a circle and counting continues bac, at the beginning until the value is reached= +lso, notice that the list is loaded into the 3ueue such that the $irst name on the list #ill be at the $ront o$ the 3ueue= Pill in this case is the $irst item in the list and there$ore moves to the $ront o$ the 3ueue= + variation o$ this im!lementation, described in the e*ercises, allo#s $or a random counter=

Simulation. Printing Tas s


+ more interesting simulation allo#s us to study the behavior o$ the !rinting 3ueue described earlier in this section= Recall that as students send !rinting tas,s to the shared !rinter, the tas,s are !laced in a 3ueue to be !rocessed in a $irst4come $irst4served manner= Many 3uestions arise #ith this con$iguration= 'he most im!ortant o$ these might be #hether the !rinter is ca!able o$ handling a certain amount o$ #or,= I$ it cannot, students #ill be #aiting too long $or !rinting and may miss their ne*t class= Consider the $ollo#ing situation in a com!uter science laboratory= On any average day about 2G students are #or,ing in the lab at any given hour= 'hese students ty!ically !rint u! to t#ice during that time, and the length o$ these tas,s ranges $rom 2 to 9G !ages= 'he !rinter in the lab is older, ca!able o$ !rocessing 2G !ages !er minute o$ dra$t 3uality= 'he !rinter could be s#itched to give better 3uality, but then it #ould !roduce only $ive !ages !er minute= 'he slo#er !rinting s!eed could ma,e students #ait too long= hat !age rate should be used" e could decide by building a simulation that models the laboratory= e #ill need to construct re!resentations $or students, !rinting tas,s, and the !rinter -Figure 4.= +s students submit !rinting tas,s, #e #ill add them to a #aiting list, a 3ueue o$ !rint tas,s attached to the !rinter= hen the !rinter com!letes a tas,, it #ill loo, at the 3ueue to see i$ there are any remaining tas,s to !rocess= O$ interest $or us is the average amount o$ time students #ill #ait

2GE

$or their !a!ers to be !rinted= 'his is e3ual to the average amount o$ time a tas, #aits in the 3ueue=

Com!uter Science Laboratory %rinting (ueue 'o model this situation #e need to use some !robabilities= 6or e*am!le, students may !rint a !a!er $rom 2 to 9G !ages in length= I$ each length $rom 2 to 9G is e3ually li,ely, the actual length $or a !rint tas, can be simulated by using a random number bet#een 2 and 9G inclusive= 'his means that there is e3ual chance o$ any length $rom 2 to 9G a!!earing= I$ there are 2G students in the lab and each !rints t#ice, then there are 9G !rint tas,s !er hour on average= hat is the chance that at any given second, a !rint tas, is going to be created" 'he #ay to ans#er this is to consider the ratio o$ tas,s to time= '#enty tas,s !er hour means that on average there #ill be one tas, every 2FG seconds0 0math0ZlabelHtas,e3uationI $rac H9Gtas,sIH2hourI times $rac H2hourI HCGminutesI times $rac H2minuteI HCGsecondsI P $rac H2tas,I H2FGsecondsI Z 6or every second #e can simulate the chance that a !rint tas, occurs by generating a random number bet#een 2 and 2FG inclusive= I$ the number is 2FG, #e say a tas, has been created= /ote that it is !ossible that many tas,s could be created in a ro# or #e may #ait 3uite a #hile $or a tas, to a!!ear= 'hat is the nature o$ simulation= >ou #ant to simulate the real situation as closely as !ossible given that you ,no# general !arameters=

+ain Simulation Steps


1ere is the main simulation=

22G

2= Create a 3ueue o$ !rint tas,s= )ach tas, #ill be given a timestam! u!on its arrival= 'he 3ueue is em!ty to start= 9= 6or each second -currentSecond.0 o Does a ne# !rint tas, get created" I$ so, add it to the 3ueue #ith the currentSecond as the timestam!= o I$ the !rinter is not busy and i$ a tas, is #aiting, Remove the ne*t tas, $rom the !rint 3ueue and assign it to the !rinter= Subtract the timestam! $rom the currentSecond to com!ute the #aiting time $or that tas,= +!!end the #aiting time $or that tas, to a list $or later !rocessing= Based on the number o$ !ages in the !rint tas,, $igure out ho# much time #ill be re3uired= o 'he !rinter no# does one second o$ !rinting i$ necessary= It also subtracts one second $rom the time re3uired $or that tas,= o I$ the tas, has been com!leted, in other #ords the time re3uired has reached 8ero, the !rinter is no longer busy= ;= +$ter the simulation is com!lete, com!ute the average #aiting time $rom the list o$ #aiting times generated=

Python Implementation
'o design this simulation #e #ill create classes $or the three real4#orld objects described above0 Nrinter, )as=, and NrintXueue= 'he Nrinter class -!isting 3. #ill need to trac, #hether it has a current tas,= I$ it does, then it is busy -lines 2;A2D. and the amount o$ time needed can be com!uted $rom the number o$ !ages in the tas,= 'he constructor #ill also allo# the !ages4!er4minute setting to be initiali8ed= 'he tic= method decrements the internal timer and sets the !rinter to idle -line 22. i$ the tas, is com!leted=

1 2 4 ! 6 " # $ 10 11 12 1 14 1! 16 1" 1# 1$

222

20 21 22 2 24 class Nrinter> de: 44init44(sel:. ppm)> sel:.pagerate + ppm sel:.current)as= + 7one sel:.timeLemaining + 0 de: tic=(sel:)> i: sel:.current)as= Q+ 7one> sel:.timeLemaining + sel:.timeLemaining 5 1 i: sel:.timeLemaining ,+ 0> sel:.current)as= + 7one de: <us0(sel:)> i: sel:.current)as= Q+ 7one> return )rue else> return *alse de: start7e3t(sel:.neFtas=)> sel:.current)as= + neFtas= sel:.timeLemaining + neFtas=.getNages() S & 60'sel:.pagerate

-!rinterde$.

'he 'as, class -!isting 4. #ill re!resent a single !rinting tas,= hen the tas, is created, a random number generator #ill !rovide a length $rom 2 to 9G !ages= e have chosen to use the randrange $unction $rom the random module=
>>> import random >>> random.randrange(1.21) 1# >>> random.randrange(1.21) # >>>

)ach tas, #ill also need to ,ee! a timestam! to be used $or com!uting #aiting time= 'his timestam! #ill re!resent the time that the tas, #as created and !laced in the !rinter 3ueue= 'he Fait)ime method can then be used to retrieve the amount o$ time s!ent in the 3ueue be$ore !rinting begins=

229

1 2 4 ! 6 " # $ 10 11 12 1 14 1! 16 import random class )as=> de: 44init44(sel:.time)> sel:.timestamp + time sel:.pages + random.randrange(1.21) de: getStamp(sel:)> return sel:.timestamp de: getNages(sel:)> return sel:.pages de: Fait)ime(sel:. currenttime)> return currenttime 5 sel:.timestamp

-tas,de$.

'he main simulation -!isting 5. im!lements the algorithm described above= 'he printXueue object is an instance o$ our e*isting 3ueue +D'= + boolean hel!er $unction, neFNrint)as=, decides #hether a ne# !rinting tas, has been created= e have again chosen to use the randrange $unction $rom the random module to return a random integer bet#een 2 and 2FG= %rint tas,s arrive once every 2FG seconds= By arbitrarily choosing 2FG $rom the range o$ random integers -line ;<., #e can simulate this random event= 'he simulation $unction allo#s us to set the total time and the !ages !er minute $or the !rinter=

1 2 4 !

22;

6 " # $ 10 11 12 1 14 1! 16 1" 1# 1$ 20 21 22 2 24 2! 26 2" 2# 2$ 0 1 2 4 ! 6 " # $ 40 :rom p0thonds.<asic.queue import Xueue import random de: simulation(numSeconds. pagesNerGinute)> la<printer + Nrinter(pagesNerGinute) printXueue + Xueue() Faitingtimes + -/ :or currentSecond in range(numSeconds)> i: neFNrint)as=()> tas= + )as=(currentSecond) printXueue.enqueue(tas=) i: (not la<printer.<us0()) and S (not printXueue.is@mpt0())> ne3ttas= + printXueue.dequeue() Faitingtimes.append( S ne3ttas=.Fait)ime(currentSecond)) la<printer.start7e3t(ne3ttas=) la<printer.tic=() a2erageHait+sum(Faitingtimes)'len(Faitingtimes)

22<

print("A2erage Hait (6.2: secs ( d tas=s remaining."S ((a2erageHait.printXueue.siRe())) de: neFNrint)as=()> num + random.randrange(1.1#1) i: num ++ 1#0> return )rue else> return *alse :or i in range(10)> simulation( 600.!)

%rinter (ueue Simulation44'he Main Simulation -3umainsim.

hen #e run the simulation, #e should not be concerned that the results are di$$erent each time= 'his is due to the !robabilistic nature o$ the random numbers= e are interested in the trends that may be occurring as the !arameters to the simulation are adjusted= 1ere are some results= 6irst, #e #ill run the simulation $or a !eriod o$ CG minutes -;,CGG seconds. using a !age rate o$ $ive !ages !er minute= In addition, #e #ill run 2G inde!endent trials= Remember that because the simulation #or,s #ith random numbers each run #ill return di$$erent results=
>>>:or i in range(10)> simulation( 600.!) A2erage A2erage A2erage A2erage A2erage A2erage A2erage A2erage A2erage A2erage Hait 16!. # secs Hait $!.0" secs Hait 6!.0! secs Hait $$."4 secs Hait 1".2" secs Hait 2 $.61 secs Hait "!.11 secs Hait 4#. secs Hait $. 1 secs Hait "6.0! secs 2 1 2 1 0 ! 1 0 tas=s tas=s tas=s tas=s tas=s tas=s tas=s tas=s tas=s 1 tas=s remaining. remaining. remaining. remaining. remaining. remaining. remaining. remaining. remaining. remaining.

+$ter running our 2G trials #e can see that the mean average #ait time is 299=2BB seconds= >ou can also see that there is a large variation in the average #eight time #ith a minimum average o$ 2D=9D seconds and a ma*imum o$ 9;E=C2 seconds= >ou may also notice that in only t#o o$ the cases #ere all the tas,s com!leted= /o#, #e #ill adjust the !age rate to 2G !ages !er minute, and run the 2G trials again, #ith a $aster !age rate our ho!e #ould be that more tas,s #ould be com!leted in the one hour time $rame=
>>>:or i in range(10)> simulation( 600.10)

22B

A2erage A2erage A2erage A2erage A2erage A2erage A2erage A2erage A2erage A2erage

Hait Hait Hait Hait Hait Hait Hait Hait Hait Hait

1.2$ ".00 2#.$6 1 .!! 12.6" 6.46 22. 12. $ ".2" 1#.1"

secs secs secs secs secs secs secs secs secs secs

0 0 1 0 0 0 0 0 0 0

tas=s tas=s tas=s tas=s tas=s tas=s tas=s tas=s tas=s tas=s

remaining. remaining. remaining. remaining. remaining. remaining. remaining. remaining. remaining. remaining.

Discussion
e #ere trying to ans#er a 3uestion about #hether the current !rinter could handle the tas, load i$ it #ere set to !rint #ith a better 3uality but slo#er !age rate= 'he a!!roach #e too, #as to #rite a simulation that modeled the !rinting tas,s as random events o$ various lengths and arrival times= 'he out!ut above sho#s that #ith B !ages !er minute !rinting, the average #aiting time varied $rom a lo# o$ 2D seconds to a high o$ ;DC seconds -about C minutes.= ith a $aster !rinting rate, the lo# value #as 2 second #ith a high o$ only 9F= In addition, in F out o$ 2G runs at B !ages !er minute there #ere !rint tas,s still #aiting in the 3ueue at the end o$ the hour= 'here$ore, #e are !erha!s !ersuaded that slo#ing the !rinter do#n to get better 3uality may not be a good idea= Students cannot a$$ord to #ait that long $or their !a!ers, es!ecially #hen they need to be getting on to their ne*t class= + si*4minute #ait #ould sim!ly be too long= 'his ty!e o$ simulation analysis allo#s us to ans#er many 3uestions, commonly ,no#n as ?#hat i$@ 3uestions= +ll #e need to do is vary the !arameters used by the simulation and #e can simulate any number o$ interesting behaviors= 6or e*am!le,

hat i$ enrollment goes u! and the average number o$ students increases by 9G" hat i$ it is Saturday and students are not needing to get to class" Can they a$$ord to #ait" hat i$ the si8e o$ the average !rint tas, decreases since %ython is such a !o#er$ul language and !rograms tend to be much shorter"

'hese 3uestions could all be ans#ered by modi$ying the above simulation= 1o#ever, it is im!ortant to remember that the simulation is only as good as the assum!tions that are used to build it= Real data about the number o$ !rint tas,s !er hour and the number o$ students !er hour #as necessary to construct a robust simulation= Sel$ Chec, 1o# #ould you modi$y the !rinter simulation to re$lect a larger number o$ students" Su!!ose that the number o$ students #as doubled= >ou ma,e need to ma,e some reasonable assum!tions about ho# this simulation #as !ut together but #hat #ould you change" Modi$y the code= +lso su!!ose that the length o$ the average !rint tas, #as cut in hal$= Change the code to re$lect that change= 6inally 1o# #ould you !arameterti8e the number o$ students,

22C

rather than changing the code #e #ould li,e to ma,e the number o$ students a !arameter o$ the simulation=

De-ues
e #ill conclude this introduction to basic data structures by loo,ing at another variation on the theme o$ linear collections= 1o#ever, unli,e stac, and 3ueue, the de3ue -!ronounced ?dec,@. has very $e# restrictions= +lso, be care$ul that you do not con$use the s!elling o$ ?de3ue@ #ith the 3ueue removal o!eration ?de3ueue=@

What Is a De-ue$
+ de-ue, also ,no#n as a double4ended 3ueue, is an ordered collection o$ items similar to the 3ueue= It has t#o ends, a $ront and a rear, and the items remain !ositioned in the collection= hat ma,es a de3ue di$$erent is the unrestrictive nature o$ adding and removing items= /e# items can be added at either the $ront or the rear= Li,e#ise, e*isting items can be removed $rom either end= In a sense, this hybrid linear structure !rovides all the ca!abilities o$ stac,s and 3ueues in a single data structure= Figure 1 sho#s a de3ue o$ %ython data objects= It is im!ortant to note that even though the de3ue can assume many o$ the characteristics o$ stac,s and 3ueues, it does not re3uire the LI6O and 6I6O orderings that are en$orced by those data structures= It is u! to you to ma,e consistent use o$ the addition and removal o!erations=

+ De3ue o$ %ython Data Objects

The De-ue Abstract Data Type


'he de3ue abstract data ty!e is de$ined by the $ollo#ing structure and o!erations= + de3ue is structured, as described above, as an ordered collection o$ items #here items are added and removed $rom either end, either $ront or rear= 'he de3ue o!erations are given belo#=

creates a ne# de3ue that is em!ty= It needs no !arameters and returns an em!ty de3ue= add*ront(item) adds a ne# item to the $ront o$ the de3ue= It needs the item and returns nothing= addLear(item) adds a ne# item to the rear o$ the de3ue= It needs the item and returns nothing= remo2e*ront() removes the $ront item $rom the de3ue= It needs no !arameters and returns the item= 'he de3ue is modi$ied= remo2eLear() removes the rear item $rom the de3ue= It needs no !arameters and returns the item= 'he de3ue is modi$ied=
Deque()

22D

tests to see #hether the de3ue is em!ty= It needs no !arameters and returns a boolean value= siRe() returns the number o$ items in the de3ue= It needs no !arameters and returns an integer=
is@mpt0()

+s an e*am!le, i$ #e assume that d is a de3ue that has been created and is currently em!ty, then 'able Hde3ueo!erationsI sho#s the results o$ a se3uence o$ de3ue o!erations= /ote that the contents in $ront are listed on the right= It is very im!ortant to ,ee! trac, o$ the $ront and the rear as you move items in and out o$ the collection as things can get a bit con$using= De-ue !peration
d.is@mpt0() d.addLear(4) d.addLear(6dog6) -/ -4/ -6dog6.4./

De-ue #ontents

Return 9alue
)rue

d.add*ront(6cat6) -6dog6.4.6cat6/ d.add*ront()rue) d.siRe() d.is@mpt0() d.addLear(#.4) d.remo2eLear() d.remo2e*ront() -6dog6.4.6cat6.)rue/ -6dog6.4.6cat6.)rue/ -6dog6.4.6cat6.)rue/ -#.4.6dog6.4.6cat6.)rue/ -6dog6.4.6cat6.)rue/ -6dog6.4.6cat6/ #.4 )rue 4 *alse

)*am!les o$ De3ue O!erations

Implementing a De-ue in Python


+s #e have done in !revious sections, #e #ill create a ne# class $or the im!lementation o$ the abstract data ty!e de3ue= +gain, the %ython list #ill !rovide a very nice set o$ methods u!on #hich to build the details o$ the de3ue= Our im!lementation -!isting 1. #ill assume that the rear o$ the de3ue is at !osition G in the list=

1 2 4 ! 6 " # $ 10 11 12 1 14 1!

22F

16 1" 1# 1$ 20 21 22 2 class Deque> de: 44init44(sel:)> sel:.items + -/ de: is@mpt0(sel:)> return sel:.items ++ -/ de: add*ront(sel:. item)> sel:.items.append(item) de: addLear(sel:. item)> sel:.items.insert(0.item) de: remo2e*ront(sel:)> return sel:.items.pop() de: remo2eLear(sel:)> return sel:.items.pop(0) de: siRe(sel:)> return len(sel:.items)

-de3uecode.

In remo2e*ront #e use the pop method to remove the last element $rom the list= 1o#ever, in remo2eLear, the pop(0) method must remove the $irst element o$ the list= Li,e#ise, #e need to use the insert method -line 29. in addLear since the append method assumes the addition o$ a ne# element to the end o$ the list= 'he $ollo#ing interactive %ython session sho#s the Deque class in action as #e !er$orm the se3uence o$ o!erations $rom Table 1=

1 2 4 ! 6

22E

" # $ 10 11 12 1 d+Deque() print(d.is@mpt0()) d.addLear(4) d.addLear(6dog6) d.add*ront(6cat6) d.add*ront()rue) print(d.siRe()) print(d.is@mpt0()) d.addLear(#.4) print(d.remo2eLear()) print(d.remo2e*ront())

-de3test.

>ou can see many similarities to %ython code already described $or stac,s and 3ueues= >ou are also li,ely to observe that in this im!lementation adding and removing items $rom the $ront is O-2. #hereas adding and removing $rom the rear is O-n.= 'his is to be e*!ected given the common o!erations that a!!ear $or adding and removing items= +gain, the im!ortant thing is to be certain that #e ,no# #here the $ront and rear are assigned in the im!lementation=

Palindrome&#hec er
+n interesting !roblem that can be easily solved using the de3ue data structure is the classic !alindrome !roblem= + palindrome is a string that reads the same $or#ard and bac,#ard, $or e*am!le, radar, toot, and "ada"= e #ould li,e to construct an algorithm to in!ut a string o$ characters and chec, #hether it is a !alindrome= 'he solution to this !roblem #ill use a de3ue to store the characters o$ the string= e #ill !rocess the string $rom le$t to right and add each character to the rear o$ the de3ue= +t this !oint, the de3ue #ill be acting very much li,e an ordinary 3ueue= 1o#ever, #e can no# ma,e use o$ the dual $unctionality o$ the de3ue= 'he $ront o$ the de3ue #ill hold the $irst character o$ the string and the rear o$ the de3ue #ill hold the last character -see Figure 2.=

29G

+ De3ue Since #e can remove both o$ them directly, #e can com!are them and continue only i$ they match= I$ #e can ,ee! matching $irst and the last items, #e #ill eventually either run out o$ characters or be le$t #ith a de3ue o$ si8e 2 de!ending on #hether the length o$ the original string #as even or odd= In either case, the string must be a !alindrome= 'he com!lete $unction $or !alindrome4chec,ing a!!ears in !isting 2=

1 2 4 ! 6 " # $ 10 11 12 1 14 1! 16 1" 1#

292

1$ 20 21 :rom p0thonds.<asic.deque import Deque de: palchec=er(aString)> chardeque + Deque() :or ch in aString> chardeque.addLear(ch) still@qual + )rue Fhile chardeque.siRe() > 1 and still@qual> :irst + chardeque.remo2e*ront() last + chardeque.remo2eLear() i: :irst Q+ last> still@qual + *alse return still@qual print(palchec=er("lsd=A:s=:")) print(palchec=er("radar"))

-!alchec,er.

/ists
'hroughout the earlier sections o$ this cha!ter, #e have used %ython lists to im!lement the abstract data ty!es !resented= 'he list is a !o#er$ul, yet sim!le, collection mechanism that !rovides the !rogrammer #ith a #ide variety o$ o!erations= 1o#ever, not all !rogramming languages include a list collection= In these cases, the notion o$ a list must be im!lemented by the !rogrammer= + list is a collection o$ items #here each item holds a relative !osition #ith res!ect to the others= More s!eci$ically, #e #ill re$er to this ty!e o$ list as an unordered list= e can consider the list as having a $irst item, a second item, a third item, and so on= e can also re$er to the beginning o$ the list -the $irst item. or the end o$ the list -the last item.= 6or sim!licity #e #ill assume that lists cannot contain du!licate items= 6or e*am!le, the collection o$ integers B<, 9C, E;, 2D, DD, and ;2 might re!resent a sim!le unordered list o$ e*am scores= /ote that #e have #ritten them as comma4delimited values, a common #ay o$ sho#ing the list structure= O$ course, %ython #ould sho# this list as SB<,9C,E;,2D,DD,;2T=

The +nordered /ist Abstract Data Type


'he structure o$ an unordered list, as described above, is a collection o$ items #here each item holds a relative !osition #ith res!ect to the others= Some !ossible unordered list o!erations are given belo#=

299

1ist()

creates a ne# list that is em!ty= It needs no !arameters and returns an em!ty

list= adds a ne# item to the list= It needs the item and returns nothing= +ssume the item is not already in the list= remo2e(item) removes the item $rom the list= It needs the item and modi$ies the list= +ssume the item is !resent in the list= search(item) searches $or the item in the list= It needs the item and returns a boolean value= is@mpt0() tests to see #hether the list is em!ty= It needs no !arameters and returns a boolean value= length() returns the number o$ items in the list= It needs no !arameters and returns an integer= append(item) adds a ne# item to the end o$ the list ma,ing it the last item in the collection= It needs the item and returns nothing= +ssume the item is not already in the list= inde3(item) returns the !osition o$ item in the list= It needs the item and returns the inde*= +ssume the item is in the list= insert(pos.item) adds a ne# item to the list at !osition !os= It needs the item and returns nothing= +ssume the item is not already in the list and there are enough e*isting items to have !osition !os= pop() removes and returns the last item in the list= It needs nothing and returns an item= +ssume the list has at least one item= pop(pos) removes and returns the item at !osition !os= It needs the !osition and returns the item= +ssume the item is in the list=
add(item)

Implementing an +nordered /ist. /in ed /ists


In order to im!lement an unordered list, #e #ill construct #hat is commonly ,no#n as a lin ed list= Recall that #e need to be sure that #e can maintain the relative !ositioning o$ the items= 1o#ever, there is no re3uirement that #e maintain that !ositioning in contiguous memory= 6or e*am!le, consider the collection o$ items sho#n in Figure 1= It a!!ears that these values have been !laced randomly= I$ #e can maintain some e*!licit in$ormation in each item, namely the location o$ the ne*t item -see Figure 2., then the relative !osition o$ each item can be e*!ressed by sim!ly $ollo#ing the lin, $rom one item to the ne*t=

Items /ot Constrained in 'heir %hysical %lacement

29;

Relative %ositions Maintained by )*!licit Lin,s= It is im!ortant to note that the location o$ the $irst item o$ the list must be e*!licitly s!eci$ied= Once #e ,no# #here the $irst item is, the $irst item can tell us #here the second is, and so on= 'he e*ternal re$erence is o$ten re$erred to as the head o$ the list= Similarly, the last item needs to ,no# that there is no ne*t item=

The Node Class


'he basic building bloc, $or the lin,ed list im!lementation is the node= )ach node object must hold at least t#o !ieces o$ in$ormation= 6irst, the node must contain the list item itsel$= e #ill call this the data %ield o$ the node= In addition, each node must hold a re$erence to the ne*t node= !isting 1 sho#s the %ython im!lementation= 'o construct a node, you need to su!!ly the initial data value $or the node= )valuating the assignment statement belo# #ill yield a node object containing the value E; -see Figure 3.= >ou should note that #e #ill ty!ically re!resent a node object as sho#n in Figure 4= 'he 7ode class also includes the usual methods to access and modi$y the data and the ne*t re$erence=
>>> temp + 7ode($ ) >>> temp.getData() $

'he s!ecial %ython re$erence value 7one #ill !lay an im!ortant role in the 7ode class and later in the lin,ed list itsel$= + re$erence to 7one #ill denote the $act that there is no ne*t node= /ote in the constructor that a node is initially created #ith ne3t set to 7one= Since this is sometimes re$erred to as ?grounding the node,@ #e #ill use the standard ground symbol to denote a re$erence that is re$erring to 7one= It is al#ays a good idea to e*!licitly assign 7one to your initial ne*t re$erence values=

1 2 4 ! 6 " # $

29<

10 11 12 1 14 1! 16 1" 1# class 7ode> de: 44init44(sel:.initdata)> sel:.data + initdata sel:.ne3t + 7one de: getData(sel:)> return sel:.data de: get7e3t(sel:)> return sel:.ne3t de: setData(sel:.neFdata)> sel:.data + neFdata de: set7e3t(sel:.neFne3t)> sel:.ne3t + neFne3t

/ode Class -nodeclass.

+ /ode Object Contains the Item and a Re$erence to the /e*t /ode

+ 'y!ical Re!resentation $or a /ode

The Unordered

List

Class

+s #e suggested above, the unordered list #ill be built $rom a collection o$ nodes, each lin,ed to the ne*t by e*!licit re$erences= +s long as #e ,no# #here to $ind the $irst node -containing the $irst item., each item a$ter that can be $ound by successively $ollo#ing the ne*t lin,s= ith this in mind, the Inordered1ist class must maintain a re$erence to the $irst

29B

node= !isting 2 sho#s the constructor= /ote that each list object #ill maintain a single re$erence to the head o$ the list= Initially #hen #e construct a list, there are no items= 'he assignment statement
>>> m0list + Inordered1ist()

creates the lin,ed list re!resentation sho#n in Figure 5= +s #e discussed in the 7ode class, the s!ecial re$erence 7one #ill again be used to state that the head o$ the list does not re$er to anything= )ventually, the e*am!le list given earlier #ill be re!resented by a lin,ed list as sho#n in Figure 6= 'he head o$ the list re$ers to the $irst node #hich contains the $irst item o$ the list= In turn, that node holds a re$erence to the ne*t node -the ne*t item. and so on= It is very im!ortant to note that the list class itsel$ does not contain any node objects= Instead it contains a single re$erence to only the $irst node in the lin,ed structure=

+n )m!ty List

+ Lin,ed List o$ Integers


de: 44init44(sel:)> sel:.head + 7one

'he is@mpt0 method, sho#n in !isting 3, sim!ly chec,s to see i$ the head o$ the list is a re$erence to 7one= 'he result o$ the boolean e*!ression sel:.head++7one #ill only be true i$ there are no nodes in the lin,ed list= Since a ne# list is em!ty, the constructor and the chec, $or em!ty must be consistent #ith one another= 'his sho#s the advantage to using the re$erence 7one to denote the ?end@ o$ the lin,ed structure= In %ython, 7one can be com!ared to any re$erence= '#o re$erences are e3ual i$ they both re$er to the same object= e #ill use this o$ten in our remaining methods=
de: is@mpt0(sel:)> return sel:.head ++ 7one

So, ho# do #e get items into our list" e need to im!lement the add method= 1o#ever, be$ore #e can do that, #e need to address the im!ortant 3uestion o$ #here in the lin,ed list to !lace the ne# item= Since this list is unordered, the s!eci$ic location o$ the ne# item #ith

29C

res!ect to the other items already in the list is not im!ortant= 'he ne# item can go any#here= ith that in mind, it ma,es sense to !lace the ne# item in the easiest location !ossible= Recall that the lin,ed list structure !rovides us #ith only one entry !oint, the head o$ the list= +ll o$ the other nodes can only be reached by accessing the $irst node and then $ollo#ing ne3t lin,s= 'his means that the easiest !lace to add the ne# node is right at the head, or beginning, o$ the list= In other #ords, #e #ill ma,e the ne# item the $irst item o$ the list and the e*isting items #ill need to be lin,ed to this ne# $irst item so that they $ollo#= 'he lin,ed list sho#n in Figure 6 #as built by calling the add method a number o$ times=
>>> >>> >>> >>> >>> >>> m0list.add( 1) m0list.add("") m0list.add(1") m0list.add($ ) m0list.add(26) m0list.add(!4)

/ote that since ;2 is the $irst item added to the list, it #ill eventually be the last node on the lin,ed list as every other item is added ahead o$ it= +lso, since B< is the last item added, it #ill become the data value in the $irst node o$ the lin,ed list= 'he add method is sho#n in !isting 4= )ach item o$ the list must reside in a node object= Line 9 creates a ne# node and !laces the item as its data= /o# #e must com!lete the !rocess by lin,ing the ne# node into the e*isting structure= 'his re3uires t#o ste!s as sho#n in Figure 7= Ste! 2 -line ;. changes the ne3t re$erence o$ the ne# node to re$er to the old $irst node o$ the list= /o# that the rest o$ the list has been !ro!erly attached to the ne# node, #e can modi$y the head o$ the list to re$er to the ne# node= 'he assignment statement in line < sets the head o$ the list= 'he order o$ the t#o ste!s described above is very im!ortant= hat ha!!ens i$ the order o$ line ; and line < is reversed" I$ the modi$ication o$ the head o$ the list ha!!ens $irst, the result can be seen in Figure 8= Since the head #as the only e*ternal re$erence to the list nodes, all o$ the original nodes are lost and can no longer be accessed=
de: add(sel:.item)> temp + 7ode(item) temp.set7e3t(sel:.head) sel:.head + temp

+dding a /e# /ode is a '#o4Ste! %rocess

29D

Result o$ Reversing the Order o$ the '#o Ste!s 'he ne*t methods that #e #ill im!lementAlength, search, and remo2eAare all based on a techni3ue ,no#n as lin ed list traversal= 'raversal re$ers to the !rocess o$ systematically visiting each node= 'o do this #e use an e*ternal re$erence that starts at the $irst node in the list= +s #e visit each node, #e move the re$erence to the ne*t node by ?traversing@ the ne*t re$erence= 'o im!lement the length method, #e need to traverse the lin,ed list and ,ee! a count o$ the number o$ nodes that occurred= !isting 5 sho#s the %ython code $or counting the number o$ nodes in the list= 'he e*ternal re$erence is called current and is initiali8ed to the head o$ the list in line 9= +t the start o$ the !rocess #e have not seen any nodes so the count is set to G= Lines <AC actually im!lement the traversal= +s long as the current re$erence has not seen the end o$ the list -7one., #e move current along to the ne*t node via the assignment statement in line C= +gain, the ability to com!are a re$erence to 7one is very use$ul= )very time current moves to a ne# node, #e add 2 to count= 6inally, count gets returned a$ter the iteration sto!s= Figure # sho#s this !rocess as it !roceeds do#n the list=
de: length(sel:)> current + sel:.head count + 0 Fhile current Q+ 7one> count + count % 1 current + current.get7e3t() return count

'raversing the Lin,ed List $rom the 1ead to the )nd Searching $or a value in a lin,ed list im!lementation o$ an unordered list also uses the traversal techni3ue= +s #e visit each node in the lin,ed list #e #ill as, #hether the data stored there matches the item #e are loo,ing $or= In this case, ho#ever, #e may not have to traverse all the #ay to the end o$ the list= In $act, i$ #e do get to the end o$ the list, that means 29F

that the item #e are loo,ing $or must not be !resent= +lso, i$ #e do $ind the item, there is no need to continue= !isting 6 sho#s the im!lementation $or the search method= +s in the length method, the traversal is initiali8ed to start at the head o$ the list -line 9.= e also use a boolean variable called :ound to remember #hether #e have located the item #e are searching $or= Since #e have not $ound the item at the start o$ the traversal, :ound can be set to *alse -line ;.= 'he iteration in line < ta,es into account both conditions discussed above= +s long as there are more nodes to visit and #e have not $ound the item #e are loo,ing $or, #e continue to chec, the ne*t node= 'he 3uestion in line B as,s #hether the data item is !resent in the current node= I$ so, :ound can be set to )rue=
de: search(sel:.item)> current + sel:.head :ound + *alse Fhile current Q+ 7one and not :ound> i: current.getData() ++ item> :ound + )rue else> current + current.get7e3t() return :ound

+s an e*am!le, consider invo,ing the search method loo,ing $or the item 2D=
>>> m0list.search(1") )rue

Since 2D is in the list, the traversal !rocess needs to move only to the node containing 2D= +t that !oint, the variable :ound is set to )rue and the Fhile condition #ill $ail, leading to the return value seen above= 'his !rocess can be seen in Figure 1$=

Success$ul Search $or the 7alue 2D 'he remo2e method re3uires t#o logical ste!s= 6irst, #e need to traverse the list loo,ing $or the item #e #ant to remove= Once #e $ind the item -recall that #e assume it is !resent., #e must remove it= 'he $irst ste! is very similar to search= Starting #ith an e*ternal re$erence set to the head o$ the list, #e traverse the lin,s until #e discover the item #e are loo,ing $or= Since #e assume that item is !resent, #e ,no# that the iteration #ill sto! be$ore current gets to 7one= 'his means that #e can sim!ly use the boolean :ound in the condition=

29E

hen :ound becomes )rue, current #ill be a re$erence to the node containing the item to be removed= But ho# do #e remove it" One !ossibility #ould be to re!lace the value o$ the item #ith some mar,er that suggests that the item is no longer !resent= 'he !roblem #ith this a!!roach is the number o$ nodes #ill no longer match the number o$ items= It #ould be much better to remove the item by removing the entire node= In order to remove the node containing the item, #e need to modi$y the lin, in the !revious node so that it re$ers to the node that comes a$ter current= 5n$ortunately, there is no #ay to go bac,#ard in the lin,ed list= Since current re$ers to the node ahead o$ the node #here #e #ould li,e to ma,e the change, it is too late to ma,e the necessary modi$ication= 'he solution to this dilemma is to use t#o e*ternal re$erences as #e traverse do#n the lin,ed list= current #ill behave just as it did be$ore, mar,ing the current location o$ the traverse= 'he ne# re$erence, #hich #e #ill call pre2ious, #ill al#ays travel one node behind current= 'hat #ay, #hen current sto!s at the node to be removed, pre2ious #ill be re$erring to the !ro!er !lace in the lin,ed list $or the modi$ication= HI !isting 7 sho#s the com!lete remo2e method= Lines 9A; assign initial values to the t#o re$erences= /ote that current starts out at the list head as in the other traversal e*am!les= pre2ious, ho#ever, is assumed to al#ays travel one node behind current= 6or this reason, pre2ious starts out #ith a value o$ 7one since there is no node be$ore the head -see Figure 11.= 'he boolean variable :ound #ill again be used to control the iteration= In lines CAD #e as, #hether the item stored in the current node is the item #e #ish to remove= I$ so, :ound can be set to )rue= I$ #e do not $ind the item, pre2ious and current must both be moved one node ahead= +gain, the order o$ these t#o statements is crucial= pre2ious must $irst be moved one node ahead to the location o$ current= +t that !oint, current can be moved= 'his !rocess is o$ten re$erred to as ?inch4#orming@ as pre2ious must catch u! to current be$ore current moves ahead= Figure 12 sho#s the movement o$ pre2ious and current as they !rogress do#n the list loo,ing $or the node containing the value 2D=
de: remo2e(sel:.item)> current + sel:.head pre2ious + 7one :ound + *alse Fhile not :ound> i: current.getData() ++ item> :ound + )rue else> pre2ious + current current + current.get7e3t() i: pre2ious ++ 7one> sel:.head + current.get7e3t() else> pre2ious.set7e3t(current.get7e3t())

2;G

Initial 7alues $or the pre2ious and current Re$erences

pre2ious

and current Move Do#n the List

Once the searching ste! o$ the remo2e has been com!leted, #e need to remove the node $rom the lin,ed list= Figure 13 sho#s the lin, that must be modi$ied= 1o#ever, there is a s!ecial case that needs to be addressed= I$ the item to be removed ha!!ens to be the $irst item in the list, then current #ill re$erence the $irst node in the lin,ed list= 'his also means that pre2ious #ill be 7one= e said earlier that pre2ious #ould be re$erring to the node #hose ne*t re$erence needs to be modi$ied in order to com!lete the remove= In this case, it is not pre2ious but rather the head o$ the list that needs to be changed -see Figure 14.=

Removing an Item $rom the Middle o$ the List

2;2

Removing the 6irst /ode $rom the List Line 29 allo#s us to chec, #hether #e are dealing #ith the s!ecial case described above= I$ pre2ious did not move, it #ill still have the value 7one #hen the boolean :ound becomes )rue= In that case -line 2;. the head o$ the list is modi$ied to re$er to the node a$ter the current node, in e$$ect removing the $irst node $rom the lin,ed list= 1o#ever, i$ !revious is not 7one, the node to be removed is some#here do#n the lin,ed list structure= In this case the !revious re$erence is !roviding us #ith the node #hose ne*t re$erence must be changed= Line 2B uses the set7e3t method $rom pre2ious to accom!lish the removal= /ote that in both cases the destination o$ the re$erence change is current.get7e3t()= One 3uestion that o$ten arises is #hether the t#o cases sho#n here #ill also handle the situation #here the item to be removed is in the last node o$ the lin,ed list= e leave that $or you to consider= 'he remaining methods append, insert, inde3, and pop are le$t as e*ercises= Remember that each o$ these must ta,e into account #hether the change is ta,ing !lace at the head o$ the list or some!lace else= +lso, insert, inde3, and pop re3uire that #e name the !ositions o$ the list= e #ill assume that !osition names are integers starting #ith G= Sel$ Chec, %art I0 Im!lement the a!!end method $or 5norderedList= method you created" hat is the time com!le*ity o$ the

%art I0 >ou most li,ely created an a!!end method that #as '-n. I$ you add an instance variable to the 5norderedList class you can create an a!!end method that is '-2.= Modi$y your a!!end method to be '-2. Be Care$ulR 'o really do this correctly you #ill need to consider a cou!le o$ s!ecial cases that may re3uire you to ma,e a modi$ication to the add method as #ell=

The !rdered /ist Abstract Data Type


e #ill no# consider a ty!e o$ list ,no#n as an ordered list= 6or e*am!le, i$ the list o$ integers sho#n above #ere an ordered list -ascending order., then it could be #ritten as 2D, 9C, ;2, B<, DD, and E;= Since 2D is the smallest item, it occu!ies the $irst !osition in the list= Li,e#ise, since E; is the largest, it occu!ies the last !osition=

2;9

'he structure o$ an ordered list is a collection o$ items #here each item holds a relative !osition that is based u!on some underlying characteristic o$ the item= 'he ordering is ty!ically either ascending or descending and #e assume that list items have a meaning$ul com!arison o!eration that is already de$ined= Many o$ the ordered list o!erations are the same as those o$ the unordered list=

creates a ne# ordered list that is em!ty= It needs no !arameters and returns an em!ty list= add(item) adds a ne# item to the list ma,ing sure that the order is !reserved= It needs the item and returns nothing= +ssume the item is not already in the list= remo2e(item) removes the item $rom the list= It needs the item and modi$ies the list= +ssume the item is !resent in the list= search(item) searches $or the item in the list= It needs the item and returns a boolean value= is@mpt0() tests to see #hether the list is em!ty= It needs no !arameters and returns a boolean value= length() returns the number o$ items in the list= It needs no !arameters and returns an integer= inde3(item) returns the !osition o$ item in the list= It needs the item and returns the inde*= +ssume the item is in the list= pop() removes and returns the last item in the list= It needs nothing and returns an item= +ssume the list has at least one item= pop(pos) removes and returns the item at !osition !os= It needs the !osition and returns the item= +ssume the item is in the list=
Krdered1ist()

Implementing an !rdered /ist


In order to im!lement the ordered list, #e must remember that the relative !ositions o$ the items are based on some underlying characteristic= 'he ordered list o$ integers given above -2D, 9C, ;2, B<, DD, and E;. can be re!resented by a lin,ed structure as sho#n in Figure 15= +gain, the node and lin, structure is ideal $or re!resenting the relative !ositioning o$ the items=

+n Ordered Lin,ed List 'o im!lement the Krdered1ist class, #e #ill use the same techni3ue as seen !reviously #ith unordered lists= Once again, an em!ty list #ill be denoted by a head re$erence to 7one -see !isting 8.=
class Krdered1ist> de: 44init44(sel:)> sel:.head + 7one

+s #e consider the o!erations $or the ordered list, #e should note that the is@mpt0 and length methods can be im!lemented the same as #ith unordered lists since they deal only #ith the number o$ nodes in the list #ithout regard to the actual item values= Li,e#ise, the

2;;

method #ill #or, just $ine since #e still need to $ind the item and then lin, around the node to remove it= 'he t#o remaining methods, search and add, #ill re3uire some modi$ication=
remo2e

'he search o$ an unordered lin,ed list re3uired that #e traverse the nodes one at a time until #e either $ind the item #e are loo,ing $or or run out o$ nodes -7one.= It turns out that the same a!!roach #ould actually #or, #ith the ordered list and in $act in the case #here #e $ind the item it is e*actly #hat #e need= 1o#ever, in the case #here the item is not in the list, #e can ta,e advantage o$ the ordering to sto! the search as soon as !ossible= 6or e*am!le, Figure 16 sho#s the ordered lin,ed list as a search is loo,ing $or the value <B= +s #e traverse, starting at the head o$ the list, #e $irst com!are against 2D= Since 2D is not the item #e are loo,ing $or, #e move to the ne*t node, in this case 9C= +gain, this is not #hat #e #ant, so #e move on to ;2 and then on to B<= /o#, at this !oint, something is di$$erent= Since B< is not the item #e are loo,ing $or, our $ormer strategy #ould be to move $or#ard= 1o#ever, due to the $act that this is an ordered list, that #ill not be necessary= Once the value in the node becomes greater than the item #e are searching $or, the search can sto! and return *alse= 'here is no #ay the item could e*ist $urther out in the lin,ed list=

Searching an Ordered Lin,ed List !isting # sho#s the com!lete search method= It is easy to incor!orate the ne# condition discussed above by adding another boolean variable, stop, and initiali8ing it to *alse -line <.= hile stop is *alse -not stop. #e can continue to loo, $or#ard in the list -line B.= I$ any node is ever discovered that contains data greater than the item #e are loo,ing $or, #e #ill set stop to )rue -lines EA2G.= 'he remaining lines are identical to the unordered list search=
de: search(sel:.item)> current + sel:.head :ound + *alse stop + *alse Fhile current Q+ 7one and not :ound and not stop> i: current.getData() ++ item> :ound + )rue else> i: current.getData() > item> stop + )rue else> current + current.get7e3t() return :ound

'he most signi$icant method modi$ication #ill ta,e !lace in add= Recall that $or unordered lists, the add method could sim!ly !lace a ne# node at the head o$ the list= It #as the easiest 2;<

!oint o$ access= 5n$ortunately, this #ill no longer #or, #ith ordered lists= It is no# necessary that #e discover the s!eci$ic !lace #here a ne# item belongs in the e*isting ordered list= +ssume #e have the ordered list consisting o$ 2D, 9C, B<, DD, and E; and #e #ant to add the value ;2= 'he add method must decide that the ne# item belongs bet#een 9C and B<= Figure 17 sho#s the setu! that #e need= +s #e e*!lained earlier, #e need to traverse the lin,ed list loo,ing $or the !lace #here the ne# node #ill be added= e ,no# #e have $ound that !lace #hen either #e run out o$ nodes -current becomes 7one. or the value o$ the current node becomes greater than the item #e #ish to add= In our e*am!le, seeing the value B< causes us to sto!=

+dding an Item to an Ordered Lin,ed List +s #e sa# #ith unordered lists, it is necessary to have an additional re$erence, again called pre2ious, since current #ill not !rovide access to the node that must be modi$ied= !isting 1$ sho#s the com!lete add method= Lines 9A; set u! the t#o e*ternal re$erences and lines EA 2G again allo# pre2ious to $ollo# one node behind current every time through the iteration= 'he condition -line B. allo#s the iteration to continue as long as there are more nodes and the value in the current node is not larger than the item= In either case, #hen the iteration $ails, #e have $ound the location $or the ne# node= 'he remainder o$ the method com!letes the t#o4ste! !rocess sho#n in Figure 17= Once a ne# node has been created $or the item, the only remaining 3uestion is #hether the ne# node #ill be added at the beginning o$ the lin,ed list or some !lace in the middle= +gain, pre2ious ++ 7one -line 2;. can be used to !rovide the ans#er=
de: add(sel:.item)> current + sel:.head pre2ious + 7one stop + *alse Fhile current Q+ 7one and not stop> i: current.getData() > item> stop + )rue else> pre2ious + current current + current.get7e3t() temp + 7ode(item) i: pre2ious ++ 7one> temp.set7e3t(sel:.head)

2;B

sel:.head + temp else> temp.set7e3t(current) pre2ious.set7e3t(temp)

e leave the remaining methods as e*ercises= >ou should care$ully consider #hether the unordered im!lementations #ill #or, given that the list is no# ordered=

Analysis o# *in,ed *ists


'o analy8e the com!le*ity o$ the lin,ed list o!erations, #e need to consider #hether they re3uire traversal= Consider a lin,ed list that has n nodes= 'he is@mpt0 method is '-2. since it re3uires one ste! to chec, the head re$erence $or 7one= length, on the other hand, #ill al#ays re3uire n ste!s since there is no #ay to ,no# ho# many nodes are in the lin,ed list #ithout traversing $rom head to end= 'here$ore, length is '-n.= +dding an item to an unordered list #ill al#ays be O-2. since #e sim!ly !lace the ne# node at the head o$ the lin,ed list= 1o#ever, search and remo2e, as #ell as add $or an ordered list, all re3uire the traversal !rocess= +lthough on average they may need to traverse only hal$ o$ the nodes, these methods are all '-n. since in the #orst case each #ill !rocess every node in the list= >ou may also have noticed that the !er$ormance o$ this im!lementation di$$ers $rom the actual !er$ormance given earlier $or %ython lists= 'his suggests that lin,ed lists are not the #ay %ython lists are im!lemented= 'he actual im!lementation o$ a %ython list is based on the notion o$ an array= e discuss this in more detail in Cha!ter F=

Summary

Linear data structures maintain their data in an ordered $ashion= Stac,s are sim!le data structures that maintain a LI6O, last4in $irst4out, ordering= 'he $undamental o!erations $or a stac, are push, pop, and is@mpt0= (ueues are sim!le data structures that maintain a 6I6O, $irst4in $irst4out, ordering= 'he $undamental o!erations $or a 3ueue are enqueue, dequeue, and is@mpt0= %re$i*, in$i*, and !ost$i* are all #ays to #rite e*!ressions= Stac,s are very use$ul $or designing algorithms to evaluate and translate e*!ressions= Stac,s can !rovide a reversal characteristic= (ueues can assist in the construction o$ timing simulations= Simulations use random number generators to create a real4li$e situation and allo# us to ans#er ?#hat i$@ ty!es o$ 3uestions= De3ues are data structures that allo# hybrid behavior li,e that o$ stac,s and 3ueues= 'he $undamental o!erations $or a de3ue are add*ront, addLear, remo2e*ront, remo2eLear, and is@mpt0= Lists are collections o$ items #here each item holds a relative !osition= + lin,ed list im!lementation maintains logical order #ithout re3uiring !hysical storage re3uirements= Modi$ication to the head o$ the lin,ed list is a s!ecial case=

1ey Terms
2;C

balanced !arentheses in$i* lin,ed list node !recedence simulation

data $ield

de3ue head list !ost$i* 3ueue

$irst4in $irst4out -6I6O. $ully !arenthesi8ed lin,ed list traversal !alindrome !re$i* stac,

last4in $irst4out -LI6O. linear data structure

Discussion 2uestions
2= Convert the $ollo#ing values to binary using ?divide by 9=@ Sho# the stac, o$ remainders= o 2D o <B o EC 9= Convert the $ollo#ing in$i* e*!ressions to !re$i* -use $ull !arentheses.0 o -+KB.L-CKD.L-)K6. o +K--BKC.L-DK).. o +LBLCLDK)K6 ;= Convert the above in$i* e*!ressions to !ost$i* -use $ull !arentheses.= <= Convert the above in$i* e*!ressions to !ost$i* using the direct conversion algorithm= Sho# the stac, as the conversion ta,es !lace= B= )valuate the $ollo#ing !ost$i* e*!ressions= Sho# the stac, as each o!erand and o!erator is !rocessed= o 9;L<K o 29K;K<KBK o 29;<BLKLK C= 'he alternative im!lementation o$ the Xueue +D' is to use a list such that the rear o$ the 3ueue is at the end o$ the list= hat #ould this mean $or Big4O !er$ormance" D= hat is the result o$ carrying out both ste!s o$ the lin,ed list add method in reverse order" hat ,ind o$ re$erence results" hat ty!es o$ !roblems may result" F= )*!lain ho# the lin,ed list remo2e method #or,s #hen the item to be removed is in the last node= E= )*!lain ho# the remo2e method #or,s #hen the item is in the onl+ node in the lin,ed list=

Programming ()ercises
2= Modi$y the in$i*4to4!ost$i* algorithm so that it can handle errors= 9= Modi$y the !ost$i* evaluation algorithm so that it can handle errors= ;= Im!lement a direct in$i* evaluator that combines the $unctionality o$ in$i*4to4!ost$i* conversion and the !ost$i* evaluation algorithm= >our evaluator should !rocess in$i* to,ens $rom le$t to right and use t#o stac,s, one $or o!erators and one $or o!erands, to !er$orm the evaluation= 2;D

<= 'urn your direct in$i* evaluator $rom the !revious !roblem into a calculator= B= Im!lement the Xueue +D', using a list such that the rear o$ the 3ueue is at the end o$ the list= C= Design and im!lement an e*!eriment to do benchmar, com!arisons o$ the t#o 3ueue im!lementations= hat can you learn $rom such an e*!eriment" D= It is !ossible to im!lement a 3ueue such that both en3ueue and de3ueue have '-2. !er$ormance on a*erage= In this case it means that most o$ the time en3ueue and de3ueue #ill be '-2. e*ce!t in one !articular circumstance #here de3ueue #ill be

'-n.=
F= Consider a real li$e situation= 6ormulate a 3uestion and then design a simulation that can hel! to ans#er it= %ossible situations include0
o o o o

Cars lined u! at a car #ash Customers at a grocery store chec,4out +ir!lanes ta,ing o$$ and landing on a run#ay + ban, teller

Be sure to state any assum!tions that you ma,e and !rovide any !robabilistic data that must be considered as !art o$ the scenario= E= Modi$y the 1ot %otato simulation to allo# $or a randomly chosen counting value so that each !ass is not !redictable $rom the !revious one= 2G= Im!lement a radi* sorting machine= + radi* sort $or base 2G integers is a mechanical sorting techni3ue that utili8es a collection o$ bins, one main bin and 2G digit bins= )ach bin acts li,e a 3ueue and maintains its values in the order that they arrive= 'he algorithm begins by !lacing each number in the main bin= 'hen it considers each value digit by digit= 'he $irst value is removed and !laced in a digit bin corres!onding to the digit being considered= 6or e*am!le, i$ the ones digit is being considered, B;< is !laced in digit bin < and CCD is !laced in digit bin D= Once all the values are !laced in the corres!onding digit bins, the values are collected $rom bin G to bin E and !laced bac, in the main bin= 'he !rocess continues #ith the tens digit, the hundreds, and so on= +$ter the last digit is !rocessed, the main bin contains the values in order= 22= +nother e*am!le o$ the !arentheses matching !roblem comes $rom hy!erte*t mar,u! language -1'ML.= In 1'ML, tags e*ist in both o!ening and closing $orms and must be balanced to !ro!erly describe a #eb document= 'his very sim!le 1'ML document0
12. ,html> 1 . ,head> 14. ,title> 1!. @3ample 16. ,'title> 1". ,'head> 1#. 1$. ,<od0> 20. ,h1>Oello. Forld,'h1> 21. ,'<od0>

2;F

,'html>

is intended only to sho# the matching and nesting structure $or tags in the language= rite a !rogram that can chec, an 1'ML document $or !ro!er o!ening and closing tags= 99= )*tend the !rogram $rom Listing 9=2B to handle !alindromes #ith s!aces= 6or e*am!le, I %R)6)R %I is a !alindrome that reads the same $or#ard and bac,#ard i$ you ignore the blan, characters= 9;= 'o im!lement the length method, #e counted the number o$ nodes in the list= +n alternative strategy #ould be to store the number o$ nodes in the list as an additional !iece o$ data in the head o$ the list= Modi$y the Inordered1ist class to include this in$ormation and re#rite the length method= 9<= Im!lement the remo2e method so that it #or,s correctly in the case #here the item is not in the list= 9B= Modi$y the list classes to allo# du!licates= change" hich methods #ill be im!acted by this hat #ould be a good

9C= Im!lement Hthe OOstrOOI method in the 5norderedList class= string re!resentation $or a list"

9D= Im!lement Hthe OOstrOOI method so that lists are dis!layed the %ython #ay -#ith s3uare brac,ets.= 9F= Im!lement the remaining o!erations de$ined in the 5norderedList +D' -a!!end, inde*, !o!, insert.= 9E= Im!lement a slice method $or the Inordered1ist class= It should ta,e t#o !arameters, start and stop, and return a co!y o$ the list starting at the start !osition and going u! to but not including the stop !osition= ;G= Im!lement the remaining o!erations de$ined in the OrderedList +D'= ;2= Consider the relationshi! bet#een 5nordered and Ordered lists= Is it !ossible that inheritance could be used to build a more e$$icient im!lementation" Im!lement this inheritance hierarchy= ;9= Im!lement a stac, using lin,ed lists= ;;= Im!lement a 3ueue using lin,ed lists= ;<= Im!lement a de3ue using lin,ed lists= ;B= Design and im!lement an e*!eriment that #ill com!are the !er$ormance o$ a %ython list #ith a list im!lemented as a lin,ed list= ;C= Design and im!lement an e*!eriment that #ill com!are the !er$ormance o$ the %ython list based stac, and 3ueue #ith the lin,ed list im!lementation= 2;E

;D= 'he lin,ed list im!lementation given above is called a singly lin,ed list because each node has a single re$erence to the ne*t node in se3uence= +n alternative im!lementation is ,no#n as a doubly lin,ed list= In this im!lementation, each node has a re$erence to the ne*t node -commonly called ne*t. as #ell as a re$erence to the !receding node -commonly called bac,.= 'he head re$erence also contains t#o re$erences, one to the $irst node in the lin,ed list and one to the last= Code this im!lementation in %ython= ;F= Create an im!lementation o$ a 3ueue that #ould have an average !er$ormance o$ O-2. $or en3ueue and de3ueue o!erations=

2<G

Recursion !b"ectives
'he goals $or this cha!ter are as $ollo#s0

'o understand that com!le* !roblems that may other#ise be di$$icult to solve may have a sim!le recursive solution= 'o learn ho# to $ormulate !rograms recursively= 'o understand and a!!ly the three la#s o$ recursion= 'o understand recursion as a $orm o$ iteration= 'o im!lement the recursive $ormulation o$ a !roblem= 'o understand ho# recursion is im!lemented by a com!uter system=

What Is Recursion$
Recursion is a method o$ solving !roblems that involves brea,ing a !roblem do#n into smaller and smaller sub!roblems until you get to a small enough !roblem that it can be solved trivially= 5sually recursion involves a $unction calling itsel$= hile it may not seem li,e much on the sur$ace, recursion allo#s us to #rite elegant solutions to !roblems that may other#ise be very di$$icult to !rogram=

#alculating the Sum o% a /ist o% 'umbers


e #ill begin our investigation #ith a sim!le !roblem that you already ,no# ho# to solve #ithout using recursion= Su!!ose that you #ant to calculate the sum o$ a list o$ numbers such as0 S2,;,B,D,ET= +n iterative $unction that com!utes the sum is sho#n in !isting 1= 'he $unction uses an accumulator variable -theSum. to com!ute a running total o$ all the numbers in the list by starting #ith G and adding each number in the list=

1 2 4 ! 6 " # $ de: listsum(num1ist)> theSum + 0 :or i in num1ist> theSum + theSum % i

2<2

return theSum print(listsum(-1. .!.".$/))

-lstOitsum.

%retend $or a minute that you do not have Fhile loo!s or :or loo!s= 1o# #ould you com!ute the sum o$ a list o$ numbers" I$ you #ere a mathematician you might start by recalling that addition is a $unction that is de$ined $or t#o !arameters, a !air o$ numbers= 'o rede$ine the !roblem $rom adding a list to adding !airs o$ numbers, #e could re#rite the list as a $ully !arenthesi8ed e*!ression= Such an e*!ression loo,s li,e this0

----2K;.KB.KD.KE.
e can also !arenthesi8e the e*!ression the other #ay around,

-2K-;K-BK-DKE....
/otice that the innermost set o$ !arentheses, -DKE., is a !roblem that #e can solve #ithout a loo! or any s!ecial constructs= In $act, #e can use the $ollo#ing se3uence o$ sim!li$ications to com!ute a $inal sum=

totalP -2K-;K-BK-DKE....totalP -2K-;K-BK2C...totalP -2K-;K92..total P -2K9<.totalP 9B


1o# can #e ta,e this idea and turn it into a %ython !rogram" 6irst, let:s restate the sum !roblem in terms o$ %ython lists= e might say the the sum o$ the list num1ist is the sum o$ the $irst element o$ the list -num1ist-0/., and the sum o$ the numbers in the rest o$ the list -num1ist-1>/.= 'o state it in a $unctional $orm0

listSu"-nu"!ist.P(irst-nu"!ist.KlistSu"-rest-nu"!ist..
In this e3uation (irst-nu"!ist. returns the $irst element o$ the list and rest-nu"!ist. returns a list o$ everything but the $irst element= 'his is easily e*!ressed in %ython as sho#n in !isting 2=

1 2

2<9

4 ! 6 " # $ de: listsum(num1ist)> i: len(num1ist) ++ 1> return num1ist-0/ else> return num1ist-0/ % listsum(num1ist-1>/) print(listsum(-1. .!.".$/))

-lstOrecsum.

'here are a $e# ,ey ideas in this listing to loo, at= 6irst, on line 9 #e are chec,ing to see i$ the list is one element long= 'his chec, is crucial and is our esca!e clause $rom the $unction= 'he sum o$ a list o$ length 2 is trivialU it is just the number in the list= Second, on line B our $unction calls itsel$R 'his is the reason that #e call the listsum algorithm recursive= + recursive $unction is a $unction that calls itsel$= Figure 1 sho#s the series o$ recursive calls that are needed to sum the list S2,;,B,D,ET= >ou should thin, o$ this series o$ calls as a series o$ sim!li$ications= )ach time #e ma,e a recursive call #e are solving a smaller !roblem, until #e reach the !oint #here the !roblem cannot get any smaller=

Series o$ Recursive Calls +dding a List o$ /umbers hen #e reach the !oint #here the !roblem is as sim!le as it can get, #e begin to !iece together the solutions o$ each o$ the small !roblems until the initial !roblem is solved= Figure 2 sho#s the additions that are !er$ormed as listsum #or,s its #ay bac,#ard through the

2<;

series o$ calls= hen listsum returns $rom the to!most !roblem, #e have the solution to the #hole !roblem=

Series o$ Recursive Returns $rom +dding a List o$ /umbers

The Three /aws o% Recursion


Li,e the robots o$ +simov, all recursive algorithms must obey three im!ortant la#s0 2= + recursive algorithm must have a base case= 9= + recursive algorithm must change its state and move to#ard the base case= ;= + recursive algorithm must call itsel$, recursively= Let:s loo, at each one o$ these la#s in more detail and see ho# it #as used in the listsum algorithm= 6irst, a base case is the condition that allo#s the algorithm to sto! recursing= + base case is ty!ically a !roblem that is small enough to solve directly= In the listsum algorithm the base case is a list o$ length 2= 'o obey the second la#, #e must arrange $or a change o$ state that moves the algorithm to#ard the base case= + change o$ state means that some data that the algorithm is using is modi$ied= 5sually the data that re!resents our !roblem gets smaller in some #ay= In the listsum algorithm our !rimary data structure is a list, so #e must $ocus our state4changing e$$orts on the list= Since the base case is a list o$ length 2, a natural !rogression to#ard the base case is to shorten the list= 'his is e*actly #hat ha!!ens on line B o$ !isting 2 #hen #e call listsum #ith a shorter list= 'he $inal la# is that the algorithm must call itsel$= 'his is the very de$inition o$ recursion= Recursion is a con$using conce!t to many beginning !rogrammers= +s a novice !rogrammer, you have learned that $unctions are good because you can ta,e a large !roblem and brea, it 2<<

u! into smaller !roblems= 'he smaller !roblems can be solved by #riting a $unction to solve each !roblem= hen #e tal, about recursion it may seem that #e are tal,ing ourselves in circles= e have a !roblem to solve #ith a $unction, but that $unction solves the !roblem by calling itsel$R But the logic is not circular at allU the logic o$ recursion is an elegant e*!ression o$ solving a !roblem by brea,ing it do#n into a smaller and easier !roblems= In the remainder o$ this cha!ter #e #ill loo, at more e*am!les o$ recursion= In each case #e #ill $ocus on designing a solution to a !roblem by using the three la#s o$ recursion= Sel$ Chec, =recsim!=20 1o# many recursive calls are made #hen com!uting the sum o$ the list S9,<,C,F,2GT" a. C b. B c. < d. ; =recsim!=90 Su!!ose you are going to #rite a recusive $unction to calculate the $actorial o$ a number= $act-n. returns n L n42 L n49 L === here the $actorial o$ 8ero is de$inded to be 2= hat #ould be the most a!!ro!riate base case" a. n PP G b. n PP 2 c. n JP G d. n QP 2

#onverting an Integer to a String in Any Base


Su!!ose you #ant to convert an integer to a string in some base bet#een binary and he*adecimal= 6or e*am!le, convert the integer 2G to its string re!resentation in decimal as "10", or to its string re!resentation in binary as "1010"= hile there are many algorithms to solve this !roblem, including the algorithm discussed in the stac, section, the recursive $ormulation o$ the !roblem is very elegant= Let:s loo, at a concrete e*am!le using base 2G and the number DCE= Su!!ose #e have a se3uence o$ characters corres!onding to the $irst 2G digits, li,e con2String + "012 4!6"#$"= It is easy to convert a number less than 2G to its string e3uivalent by loo,ing it u! in the se3uence= 6or e*am!le, i$ the number is E, then the string is con2String-$/ or "$"= I$ #e can arrange to brea, u! the number DCE into three single4digit numbers, D, C, and E, then converting it to a string is sim!le= + number less than 2G sounds li,e a good base case= &no#ing #hat our base is suggests that the overall algorithm #ill involve three com!onents0

2<B

2= Reduce the original number to a series o$ single4digit numbers= 9= Convert the single digit4number to a string using a loo,u!= ;= Concatenate the single4digit strings together to $orm the $inal result= 'he ne*t ste! is to $igure out ho# to change state and ma,e !rogress to#ard the base case= Since #e are #or,ing #ith an integer, let:s consider #hat mathematical o!erations might reduce a number= 'he most li,ely candidates are division and subtraction= hile subtraction might #or,, it is unclear #hat #e should subtract $rom #hat= Integer division #ith remainders gives us a clear direction= Let:s loo, at #hat ha!!ens i$ #e divide a number by the base #e are trying to convert to= 5sing integer division to divide DCE by 2G, #e get DC #ith a remainder o$ E= 'his gives us t#o good results= 6irst, the remainder is a number less than our base that can be converted to a string immediately by loo,u!= Second, #e get a number that is smaller than our original and moves us to#ard the base case o$ having a single number less than our base= /o# our job is to convert DC to its string re!resentation= +gain #e #ill use integer division !lus remainder to get results o$ D and C res!ectively= 6inally, #e have reduced the !roblem to converting D, #hich #e can do easily since it satis$ies the base case condition o$ nQbase, #here

baseP2G= 'he series o$ o!erations #e have just !er$ormed is illustrated in Figure 3= /otice
that the numbers #e #ant to remember are in the remainder bo*es along the right side o$ the diagram=

image Converting an Integer to a String in Base 2G !isting 3 sho#s the %ython code that im!lements the algorithm outlined above $or any base bet#een 9 and 2C=

2<C

2 4 ! 6 " # $ 10 de: toStr(n.<ase)> con2ertString + "012 4!6"#$APJD@*" i: n , <ase> return con2ertString-n/ else> return toStr(n''<ase.<ase) % con2ertString-n(<ase/ print(toStr(14! .16))

-lstOrectostr.

/otice that in line ; #e chec, $or the base case #here n is less than the base #e are converting to= hen #e detect the base case, #e sto! recursing and sim!ly return the string $rom the con2ertString se3uence= In line C #e satis$y both the second and third la#sAby ma,ing the recursive call and by reducing the !roblem si8eAusing division= Let:s trace the algorithm againU this time #e #ill convert the number 2G to its base 9 string re!resentation -"1010".=

2<D

Converting the /umber 2G to its Base 9 String Re!resentation Figure 4 sho#s that #e get the results #e are loo,ing $or, but it loo,s li,e the digits are in the #rong order= 'he algorithm #or,s correctly because #e ma,e the recursive call $irst on line C, then #e add the string re!resentation o$ the remainder= I$ #e reversed returning the con2ertString loo,u! and returning the toStr call, the resulting string #ould be bac,#ardR But by delaying the concatenation o!eration until a$ter the recursive call has returned, #e get the result in the !ro!er order= 'his should remind you o$ our discussion o$ stac,s bac, in the !revious cha!ter= Sel$ Chec, rite a $unction that ta,es a string as a !arameter and returns a ne# string that is the reverse o$ the old string=

rite a $unction that ta,es a string as a !arameter and returns 'rue i$ the string is a !alindrome, 6alse other#ise= Remember that a string is a !alindrome i$ it is s!elled the same both $or#ard and bac,#ard= $or e*am!le0 radar is a !alindrome= $or bonus !oints !alindromes can also be !hrases, but you need to remove the s!aces and !unctuation be$ore chec,ing= $or e*am!le0 madam i:m adam is a !alindrome= Other $un !alindromes include0

,aya, aiboh!hobia Live not on evil Reviled did I live, said I, as evil I did deliver Go hang a salamiU I:m a lasagna hog= +ble #as I ere I sa# )lba &ana,ana, A a to#n in +las,a assamassa# A a to#n in South Da,ota

Stac ,rames. Implementing Recursion


Su!!ose that instead o$ concatenating the result o$ the recursive call to toStr #ith the string $rom con2ertString, #e modi$ied our algorithm to !ush the strings onto a stac, !rior to ma,ing the recursive call= 'he code $or this modi$ied algorithm is sho#n in !isting 4=

1 2 4 !

2<F

6 " # $ 10 11 12 1 rStac= + Stac=() de: toStr(n.<ase)> con2ertString + "012 4!6"#$APJD@*" i: n , <ase> rStac=.push(con2ertString-n/) else> rStac=.push(con2ertString-n ( <ase/) toStr(n '' <ase. <ase) print(toStr(14! .16))

-lstOrecstac,.

)ach time #e ma,e a call to toStr, #e !ush a character on the stac,= Returning to the !revious e*am!le #e can see that a$ter the $ourth call to toStr the stac, #ould loo, li,e Figure 5= /otice that no# #e can sim!ly !o! the characters o$$ the stac, and concatenate them into the $inal result, "1010"=

Strings %laced on the Stac, During Conversion 'he !revious e*am!le gives us some insight into ho# %ython im!lements a recursive $unction call= hen a $unction is called in %ython, a stac %rame is allocated to handle the local variables o$ the $unction= hen the $unction returns, the return value is le$t on to! o$ the stac, $or the calling $unction to access= Figure 6 illustrates the call stac, a$ter the return statement on line <=

2<E

Call Stac, Generated $rom toStr(10.2) /otice that the call to toStr(2''2.2) leaves a return value o$ "1" on the stac,= 'his return value is then used in !lace o$ the $unction call -toStr(1.2). in the e*!ression "1" % con2ertString-2(2/, #hich #ill leave the string "10" on the to! o$ the stac,= In this #ay, the %ython call stac, ta,es the !lace o$ the stac, #e used e*!licitly in !isting 4= In our list summing e*am!le, you can thin, o$ the return value on the stac, ta,ing the !lace o$ an accumulator variable= 'he stac, $rames also !rovide a sco!e $or the variables used by the $unction= )ven though #e are calling the same $unction over and over, each call creates a ne# sco!e $or the variables that are local to the $unction= I$ you ,ee! this idea o$ the stac, in your head, you #ill $ind it much easier to #rite a !ro!er recursive $unction=

2BG

Sorting and Searching


!b"ectives

'o be able to e*!lain and im!lement se3uential search and binary search= 'o be able to e*!lain and im!lement selection sort, bubble sort, merge sort, 3uic, sort, insertion sort, and shell sort= 'o understand the idea o$ hashing as a search techni3ue= 'o introduce the ma! abstract data ty!e= 'o im!lement the ma! abstract data ty!e using hashing=

Searching
e #ill no# turn our attention to some o$ the most common !roblems that arise in com!uting, those o$ searching and sorting= In this section #e #ill study searching= e #ill return to sorting later in the cha!ter= Searching is the algorithmic !rocess o$ $inding a !articular item in a collection o$ items= + search ty!ically ans#ers either )rue or *alse as to #hether the item is !resent= On occasion it may be modi$ied to return #here the item is $ound= 6or our !ur!oses here, #e #ill sim!ly concern ourselves #ith the 3uestion o$ membershi!= In %ython, there is a very easy #ay to as, #hether an item is in a list o$ items= o!erator=
>>> 1! in - .!.2.4.1/ *alse >>> in - .!.2.4.1/ )rue >>>

e use the in

)ven though this is easy to #rite, an underlying !rocess must be carried out to ans#er the 3uestion= It turns out that there are many di$$erent #ays to search $or the item= hat #e are interested in here is ho# these algorithms #or, and ho# they com!are to one another=

The Se-uential Search


hen data items are stored in a collection such as a list, #e say that they have a linear or se3uential relationshi!= )ach data item is stored in a !osition relative to the others= In %ython lists, these relative !ositions are the inde* values o$ the individual items= Since these inde* values are ordered, it is !ossible $or us to visit them in se3uence= 'his !rocess gives rise to our $irst searching techni3ue, the se-uential search= Figure 1 sho#s ho# this search #or,s= Starting at the $irst item in the list, #e sim!ly move $rom item to item, $ollo#ing the underlying se3uential ordering until #e either $ind #hat #e are loo,ing $or or run out o$ items= I$ #e run out o$ items, #e have discovered that the item #e #ere searching $or #as not !resent=

2B2

Se3uential Search o$ a List o$ Integers 'he %ython im!lementation $or this algorithm is sho#n in !isting 1= 'he $unction needs the list and the item #e are loo,ing $or and returns a boolean value as to #hether it is !resent= 'he boolean variable :ound is initiali8ed to *alse and is assigned the value )rue i$ #e discover the item in the list= 2 de$ se3uentialSearch-alist, item.0 9 !os P G ; $ound P 6alse < B #hile !os Q len-alist. and not $ound0 C i$ alistS!osT PP item0 D $ound P 'rue F else0 E !os P !osK2 2G 22 return $ound 29 2; testlist P S2, 9, ;9, F, 2D, 2E, <9, 2;, GT 2< !rint-se3uentialSearch-testlist, ;.. 2B !rint-se3uentialSearch-testlist, 2;.. Ste! 2 o$ CB line that has just e*ecuted ne*t line to e*ecute 6rames Objects Se3uential Search o$ an 5nordered List -search2.

Analysis o% Se-uential Search


'o analy8e searching algorithms, #e need to decide on a basic unit o$ com!utation= Recall that this is ty!ically the common ste! that must be re!eated in order to solve the !roblem= 6or searching, it ma,es sense to count the number o$ com!arisons !er$ormed= )ach com!arison may or may not discover the item #e are loo,ing $or= In addition, #e ma,e another assum!tion here= 'he list o$ items is not ordered in any #ay= 'he items have been !laced randomly into the list= In other #ords, the !robability that the item #e are loo,ing $or is in any !articular !osition is e*actly the same $or each !osition o$ the list=

2B9

I$ the item is not in the list, the only #ay to ,no# it is to com!are it against every item !resent= I$ there are n items, then the se3uential search re3uires n com!arisons to discover that the item is not there= In the case #here the item is in the list, the analysis is not so straight$or#ard= 'here are actually three di$$erent scenarios that can occur= In the best case #e #ill $ind the item in the $irst !lace #e loo,, at the beginning o$ the list= e #ill need only one com!arison= In the #orst case, #e #ill not discover the item until the very last com!arison, the nth com!arison= hat about the average case" On average, #e #ill $ind the item about hal$#ay into the listU that is, #e #ill com!are against n9 items= Recall, ho#ever, that as n gets large, the coe$$icients, no matter #hat they are, become insigni$icant in our a!!ro*imation, so the com!le*ity o$ the se3uential search, is '-n.= Table 1 summari8es these results= #ase item is !resent item is not !resent Best #ase Worst #ase Average #ase

2 n

n n

n9

Com!arisons 5sed in a Se3uential Search o$ an 5nordered List e assumed earlier that the items in our collection had been randomly !laced so that there is no relative order bet#een the items= hat #ould ha!!en to the se3uential search i$ the items #ere ordered in some #ay" ould #e be able to gain any e$$iciency in our search techni3ue" +ssume that the list o$ items #as constructed so that the items #ere in ascending order, $rom lo# to high= I$ the item #e are loo,ing $or is !resent in the list, the chance o$ it being in any one o$ the n !ositions is still the same as be$ore= e #ill still have the same number o$ com!arisons to $ind the item= 1o#ever, i$ the item is not !resent there is a slight advantage= Figure 2 sho#s this !rocess as the algorithm loo,s $or the item BG= /otice that items are still com!ared in se3uence until B<= +t this !oint, ho#ever, #e ,no# something e*tra= /ot only is B< not the item #e are loo,ing $or, but no other elements beyond B< can #or, either since the list is sorted= In this case, the algorithm does not have to continue loo,ing through all o$ the items to re!ort that the item #as not $ound= It can sto! immediately= !isting 2 sho#s this variation o$ the se3uential search $unction=

Se3uential Search o$ an Ordered List o$ Integers 2 de$ orderedSe3uentialSearch-alist, item.0 9 !os P G ; $ound P 6alse < sto! P 6alse B #hile !os Q len-alist. and not $ound and not sto!0 C i$ alistS!osT PP item0 2B;

D $ound P 'rue F else0 E i$ alistS!osT J item0 2G sto! P 'rue 22 else0 29 !os P !osK2 2; 2< return $ound 2B 2C testlist P SG, 2, 9, F, 2;, 2D, 2E, ;9, <9,T 2D !rint-orderedSe3uentialSearch-testlist, ;.. 2F !rint-orderedSe3uentialSearch-testlist, 2;.. Ste! 2 o$ B2 line that has just e*ecuted ne*t line to e*ecute 6rames Objects Se3uential Search o$ an Ordered List -search9. Table 2 summari8es these results= /ote that in the best case #e might discover that the item is not in the list by loo,ing at only one item= On average, #e #ill ,no# a$ter loo,ing through only n9 items= 1o#ever, this techni3ue is still '-n.= In summary, a se3uential search is im!roved by ordering the list only in the case #here #e do not $ind the item=

item is !resent item not !resent

2 n n9 2 n n9

Com!arisons 5sed in Se3uential Search o$ an Ordered List Sel$ Chec, =SRC1=20 Su!!ose you are doing a se3uential search o$ the list S2B, 2F, 9, 2E, 2F, G, F, 2<, 2E, 2<T= 1o# many com!arisons #ould you need to do in order to $ind the ,ey 2F" a. B b. 2G c. < d. 9

2B<

=SRC1=90 Su!!ose you are doing a se3uential search o$ the ordered list S;, B, C, F, 22, 29, 2<, 2B, 2D, 2FT= 1o# many com!arisons #ould you need to do in order to $ind the ,ey 2;" a. 2G b. B c. D d. C

The (inary Search


It is !ossible to ta,e greater advantage o$ the ordered list i$ #e are clever #ith our com!arisons= In the se3uential search, #hen #e com!are against the $irst item, there are at most n[2 more items to loo, through i$ the $irst item is not #hat #e are loo,ing $or= Instead o$ searching the list in se3uence, a binary search #ill start by e*amining the middle item= I$ that item is the one #e are searching $or, #e are done= I$ it is not the correct item, #e can use the ordered nature o$ the list to eliminate hal$ o$ the remaining items= I$ the item #e are searching $or is greater than the middle item, #e ,no# that the entire lo#er hal$ o$ the list as #ell as the middle item can be eliminated $rom $urther consideration= 'he item, i$ it is in the list, must be in the u!!er hal$= e can then re!eat the !rocess #ith the u!!er hal$= Start at the middle item and com!are it against #hat #e are loo,ing $or= +gain, #e either $ind it or s!lit the list in hal$, there$ore eliminating another large !art o$ our !ossible search s!ace= Figure 3 sho#s ho# this algorithm can 3uic,ly $ind the value B<= 'he com!lete $unction is sho#n in !isting 3=

Binary Search o$ an Ordered List o$ Integers 2 de$ binarySearch-alist, item.0 9 $irst P G ; last P len-alist.42 < $ound P 6alse B C #hile $irstQPlast and not $ound0 D mid!oint P -$irst K last.MM9 F i$ alistSmid!ointT PP item0 E $ound P 'rue 2G else0 22 i$ item Q alistSmid!ointT0

2BB

29 last P mid!oint42 2; else0 2< $irst P mid!ointK2 2B 2C return $ound 2D 2F testlist P SG, 2, 9, F, 2;, 2D, 2E, ;9, <9,T 2E !rint-binarySearch-testlist, ;.. 9G !rint-binarySearch-testlist, 2;.. Ste! 2 o$ <G line that has just e*ecuted ne*t line to e*ecute 6rames Objects Binary Search o$ an Ordered List -search;. Be$ore #e move on to the analysis, #e should note that this algorithm is a great e*am!le o$ a divide and con3uer strategy= Divide and con3uer means that #e divide the !roblem into smaller !ieces, solve the smaller !ieces in some #ay, and then reassemble the #hole !roblem to get the result= hen #e !er$orm a binary search o$ a list, #e $irst chec, the middle item= I$ the item #e are searching $or is less than the middle item, #e can sim!ly !er$orm a binary search o$ the le$t hal$ o$ the original list= Li,e#ise, i$ the item is greater, #e can !er$orm a binary search o$ the right hal$= )ither #ay, this is a recursive call to the binary search $unction !assing a smaller list= !isting 4 sho#s this recursive version= 2 de$ binarySearch-alist, item.0 9 i$ len-alist. PP G0 ; return 6alse < else0 B mid!oint P len-alist.MM9 C i$ alistSmid!ointTPPitem0 D return 'rue F else0 E i$ itemQalistSmid!ointT0 2G return binarySearch-alistS0mid!ointT,item. 22 else0 29 return binarySearch-alistSmid!ointK20T,item. 2; 2< testlist P SG, 2, 9, F, 2;, 2D, 2E, ;9, <9,T 2B !rint-binarySearch-testlist, ;.. 2C !rint-binarySearch-testlist, 2;.. Ste! 2 o$ ;G line that has just e*ecuted

2BC

ne*t line to e*ecute 6rames Objects + Binary Search44Recursive 7ersion -search<.

Analysis o% Binary Search


'o analy8e the binary search algorithm, #e need to recall that each com!arison eliminates about hal$ o$ the remaining items $rom consideration= hat is the ma*imum number o$ com!arisons this algorithm #ill re3uire to chec, the entire list" I$ #e start #ith n items, about n9 items #ill be le$t a$ter the $irst com!arison= +$ter the second com!arison, there #ill be about n<= 'hen nF, n2C, and so on= 1o# many times can #e s!lit the list" Table 3 hel!s us to see the ans#er= #omparisons Appro)imate 'umber o% Items /e%t 2 9 ; ===
n9i i 'abular +nalysis $or a Binary Search n9 n< nF

hen #e s!lit the list enough times, #e end u! #ith a list that has just one item= )ither that is the item #e are loo,ing $or or it is not= )ither #ay, #e are done= 'he number o$ com!arisons necessary to get to this !oint is i #here n9iP2= Solving $or i gives us iPlogn= 'he ma*imum number o$ com!arisons is logarithmic #ith res!ect to the number o$ items in the list= 'here$ore, the binary search is '-logn.= One additional analysis issue needs to be addressed= In the recursive solution sho#n above, the recursive call,
<inar0Search(alist->midpoint/.item)

uses the slice o!erator to create the le$t hal$ o$ the list that is then !assed to the ne*t invocation -similarly $or the right hal$ as #ell.= 'he analysis that #e did above assumed that the slice o!erator ta,es constant time= 1o#ever, #e ,no# that the slice o!erator in %ython is actually O-,.= 'his means that the binary search using slice #ill not !er$orm in strict logarithmic time= Luc,ily this can be remedied by !assing the list along #ith the starting and ending indices= 'he indices can be calculated as #e did in !isting 3= e leave this im!lementation as an e*ercise= )ven though a binary search is generally better than a se3uential search, it is im!ortant to note that $or small values o$ n, the additional cost o$ sorting is !robably not #orth it= In $act, #e should al#ays consider #hether it is cost e$$ective to ta,e on the e*tra #or, o$ sorting to gain searching bene$its= I$ #e can sort once and then search many times, the cost o$ the sort is

2BD

not so signi$icant= 1o#ever, $or large lists, sorting even once can be so e*!ensive that sim!ly !er$orming a se3uential search $rom the start may be the best choice= Sel$ Chec, 0 Su!!ose you have the $ollo#ing sorted list S;, B, C, F, 22, 29, 2<, 2B, 2D, 2FT and are using the recursive binary search algorithm= hich grou! o$ numbers correctly sho#s the se3uence o$ como!arisons used to $ind the ,ey F= a. 22, B, C, F b. 29, C, 22, F c. ;, B, C, F d. 2F, 29, C, F 0 Su!!ose you have the $ollo#ing sorted list S;, B, C, F, 22, 29, 2<, 2B, 2D, 2FT and are using the recursive binary search algorithm= hich grou! o$ numbers correctly sho#s the se3uence o$ como!arisons used to search $or the ,ey 2C" a. 22, 2<, 2D b. 2F, 2D, 2B c. 2<, 2D, 2B d. 29, 2D, 2B

"ashing
In !revious sections #e #ere able to ma,e im!rovements in our search algorithms by ta,ing advantage o$ in$ormation about #here items are stored in the collection #ith res!ect to one another= 6or e*am!le, by ,no#ing that a list #as ordered, #e could search in logarithmic time using a binary search= In this section #e #ill attem!t to go one ste! $urther by building a data structure that can be searched in '-2. time= 'his conce!t is re$erred to as hashing= In order to do this, #e #ill need to ,no# even more about #here the items might be #hen #e go to loo, $or them in the collection= I$ every item is #here it should be, then the search can use a single com!arison to discover the !resence o$ an item= e #ill see, ho#ever, that this is ty!ically not the case= + hash table is a collection o$ items #hich are stored in such a #ay as to ma,e it easy to $ind them later= )ach !osition o$ the hash table, o$ten called a slot, can hold an item and is named by an integer value starting at G= 6or e*am!le, #e #ill have a slot named G, a slot named 2, a slot named 9, and so on= Initially, the hash table contains no items so every slot is em!ty= e can im!lement a hash table by using a list #ith each element initiali8ed to the s!ecial %ython value 7one= Figure 4 sho#s a hash table o$ si8e "P22= In other #ords, there are " slots in the table, named G through 2G=

2BF

1ash 'able #ith 22 )m!ty Slots 'he ma!!ing bet#een an item and the slot #here that item belongs in the hash table is called the hash %unction= 'he hash $unction #ill ta,e any item in the collection and return an integer in the range o$ slot names, bet#een G and "42= +ssume that #e have the set o$ integer items B<, 9C, E;, 2D, DD, and ;2= Our $irst hash $unction, sometimes re$erred to as the ?remainder method,@ sim!ly ta,es an item and divides it by the table si8e, returning the remainder as its hash value -h-ite".Pite"N22.= Table 4 gives all o$ the hash values $or our e*am!le items= /ote that this remainder method -modulo arithmetic. #ill ty!ically be !resent in some $orm in all hash $unctions, since the result must be in the range o$ slot names= Item 0ash 9alue B< 9C E; 2D DD 2G < B C G

;2 E Sim!le 1ash 6unction 5sing Remainders Once the hash values have been com!uted, #e can insert each item into the hash table at the designated !osition as sho#n in Figure 5= /ote that C o$ the 22 slots are no# occu!ied= 'his is re$erred to as the load %actor, and is commonly denoted by .Pnu"bero(ite"stablesi/e= 6or this e*am!le, .PC22=

1ash 'able #ith Si* Items /o# #hen #e #ant to search $or an item, #e sim!ly use the hash $unction to com!ute the slot name $or the item and then chec, the hash table to see i$ it is !resent= 'his searching o!eration is '-2., since a constant amount o$ time is re3uired to com!ute the hash value and then inde* the hash table at that location= I$ everything is #here it should be, #e have $ound a constant time search algorithm= >ou can !robably already see that this techni3ue is going to #or, only i$ each item ma!s to a uni3ue location in the hash table= 6or e*am!le, i$ the item << had been the ne*t item in our 2BE

collection, it #ould have a hash value o$ G -<<N22PPG.= Since DD also had a hash value o$ G, #e #ould have a !roblem= +ccording to the hash $unction, t#o or more items #ould need to be in the same slot= 'his is re$erred to as a collision -it may also be called a ?clash@.= Clearly, collisions create a !roblem $or the hashing techni3ue= e #ill discuss them in detail later=

0ash ,unctions
Given a collection o$ items, a hash $unction that ma!s each item into a uni3ue slot is re$erred to as a per%ect hash %unction= I$ #e ,no# the items and the collection #ill never change, then it is !ossible to construct a !er$ect hash $unction -re$er to the e*ercises $or more about !er$ect hash $unctions.= 5n$ortunately, given an arbitrary collection o$ items, there is no systematic #ay to construct a !er$ect hash $unction= Luc,ily, #e do not need the hash $unction to be !er$ect to still gain !er$ormance e$$iciency= One #ay to al#ays have a !er$ect hash $unction is to increase the si8e o$ the hash table so that each !ossible value in the item range can be accommodated= 'his guarantees that each item #ill have a uni3ue slot= +lthough this is !ractical $or small numbers o$ items, it is not $easible #hen the number o$ !ossible items is large= 6or e*am!le, i$ the items #ere nine4digit Social Security numbers, this method #ould re3uire almost one billion slots= I$ #e only #ant to store data $or a class o$ 9B students, #e #ill be #asting an enormous amount o$ memory= Our goal is to create a hash $unction that minimi8es the number o$ collisions, is easy to com!ute, and evenly distributes the items in the hash table= 'here are a number o$ common #ays to e*tend the sim!le remainder method= e #ill consider a $e# o$ them here= 'he %olding method $or constructing hash $unctions begins by dividing the item into e3ual4 si8e !ieces -the last !iece may not be o$ e3ual si8e.= 'hese !ieces are then added together to give the resulting hash value= 6or e*am!le, i$ our item #as the !hone number <;C4BBB4<CG2, #e #ould ta,e the digits and divide them into grou!s o$ 9 -<;,CB,BB,<C,G2.= +$ter the addition, <;KCBKBBK<CKG2, #e get 92G= I$ #e assume our hash table has 22 slots, then #e need to !er$orm the e*tra ste! o$ dividing by 22 and ,ee!ing the remainder= In this case 92G N 22 is 2, so the !hone number <;C4BBB4<CG2 hashes to slot 2= Some $olding methods go one ste! $urther and reverse every other !iece be$ore the addition= 6or the above e*am!le, #e get <;KBCKBBKC<KG2P92E #hich gives 92E N 22P2G= +nother numerical techni3ue $or constructing a hash $unction is called the mid&s-uare method= e $irst s3uare the item, and then e*tract some !ortion o$ the resulting digits= 6or e*am!le, i$ the item #ere <<, #e #ould $irst com!ute <<9P2,E;C= By e*tracting the middle t#o digits, E;, and !er$orming the remainder ste!, #e get B -E; N 22.= Table 5 sho#s items under both the remainder method and the mid4s3uare method= >ou should veri$y that you understand ho# these values #ere com!uted= Item Remainder *id&S-uare B< 9C 2G < ; D

2CG

Item Remainder *id&S-uare E; 2D DD B C G E F <

;2 E C HCom!arison o$ Remainder and Mid4S3uare MethodsI e can also create hash $unctions $or character4based items such as strings= 'he #ord ?cat@ can be thought o$ as a se3uence o$ ordinal values=
>>> ord(6c6) $$ >>> ord(6a6) $" >>> ord(6t6) 116

e can then ta,e these three ordinal values, add them u!, and use the remainder method to get a hash value -see Figure 6.= !isting 5 sho#s a $unction called hash that ta,es a string and a table si8e and returns the hash value in the range $rom G to ta<lesiRe42=

1ashing a String 5sing Ordinal 7alues


de: hash(astring. ta<lesiRe)> sum + 0 :or pos in range(len(astring))> sum + sum % ord(astring-pos/) return sum(ta<lesiRe

Sim!le 1ash 6unction $or Strings It is interesting to note that #hen using this hash $unction, anagrams #ill al#ays be given the same hash value= 'o remedy this, #e could use the !osition o$ the character as a #eight= Figure 7 sho#s one !ossible #ay to use the !ositional value as a #eighting $actor= 'he modi$ication to the hash $unction is le$t as an e*ercise=

2C2

1ashing a String 5sing Ordinal 7alues #ith

eighting

>ou may be able to thin, o$ a number o$ additional #ays to com!ute hash values $or items in a collection= 'he im!ortant thing to remember is that the hash $unction has to be e$$icient so that it does not become the dominant !art o$ the storage and search !rocess= I$ the hash $unction is too com!le*, then it becomes more #or, to com!ute the slot name than it #ould be to sim!ly do a basic se3uential or binary search as described earlier= 'his #ould 3uic,ly de$eat the !ur!ose o$ hashing=

#ollision Resolution
e no# return to the !roblem o$ collisions= hen t#o items hash to the same slot, #e must have a systematic method $or !lacing the second item in the hash table= 'his !rocess is called collision resolution= +s #e stated earlier, i$ the hash $unction is !er$ect, collisions #ill never occur= 1o#ever, since this is o$ten not !ossible, collision resolution becomes a very im!ortant !art o$ hashing= One method $or resolving collisions loo,s into the hash table and tries to $ind another o!en slot to hold the item that caused the collision= + sim!le #ay to do this is to start at the original hash value !osition and then move in a se3uential manner through the slots until #e encounter the $irst slot that is em!ty= /ote that #e may need to go bac, to the $irst slot -circularly. to cover the entire hash table= 'his collision resolution !rocess is re$erred to as open addressing in that it tries to $ind the ne*t o!en slot or address in the hash table= By systematically visiting each slot one at a time, #e are !er$orming an o!en addressing techni3ue called linear probing= Figure 8 sho#s an e*tended set o$ integer items under the sim!le remainder method hash $unction -B<,9C,E;,2D,DD,;2,<<,BB,9G.= Table 4 above sho#s the hash values $or the original items= Figure 5 sho#s the original contents= hen #e attem!t to !lace << into slot G, a collision occurs= 5nder linear !robing, #e loo, se3uentially, slot by slot, until #e $ind an o!en !osition= In this case, #e $ind slot 2= +gain, BB should go in slot G but must be !laced in slot 9 since it is the ne*t o!en !osition= 'he $inal value o$ 9G hashes to slot E= Since slot E is $ull, #e begin to do linear !robing= e visit slots 2G, G, 2, and 9, and $inally $ind an em!ty slot at !osition ;=

2C9

Collision Resolution #ith Linear %robing Once #e have built a hash table using o!en addressing and linear !robing, it is essential that #e utili8e the same methods to search $or items= +ssume #e #ant to loo, u! the item E;= hen #e com!ute the hash value, #e get B= Loo,ing in slot B reveals E;, and #e can return )rue= hat i$ #e are loo,ing $or 9G" /o# the hash value is E, and slot E is currently holding ;2= e cannot sim!ly return *alse since #e ,no# that there could have been collisions= e are no# $orced to do a se3uential search, starting at !osition 2G, loo,ing until either #e $ind the item 9G or #e $ind an em!ty slot= + disadvantage to linear !robing is the tendency $or clusteringU items become clustered in the table= 'his means that i$ many collisions occur at the same hash value, a number o$ surrounding slots #ill be $illed by the linear !robing resolution= 'his #ill have an im!act on other items that are being inserted, as #e sa# #hen #e tried to add the item 9G above= + cluster o$ values hashing to G had to be s,i!!ed to $inally $ind an o!en !osition= 'his cluster is sho#n in Figure #=

+ Cluster o$ Items $or Slot G One #ay to deal #ith clustering is to e*tend the linear !robing techni3ue so that instead o$ loo,ing se3uentially $or the ne*t o!en slot, #e s,i! slots, thereby more evenly distributing the items that have caused collisions= 'his #ill !otentially reduce the clustering that occurs= Figure 1$ sho#s the items #hen collision resolution is done #ith a ?!lus ;@ !robe= 'his means that once a collision occurs, #e #ill loo, at every third slot until #e $ind one that is em!ty=

Collision Resolution 5sing ?%lus ;@ 'he general name $or this !rocess o$ loo,ing $or another slot a$ter a collision is rehashing= ith sim!le linear !robing, the rehash $unction is ne hash*aluePrehash-oldhash*alue. #here

rehash-0os.P-0osK2.Nsi/eo(table= 'he ?!lus ;@ rehash can be de$ined as rehash-0os.P-0osK;.Nsi/eo(table= In general, rehash-0os.P-0osKs)i0. Nsi/eo(table= It is im!ortant to note that the si8e o$ the ?s,i!@ must be such that all the
slots in the table #ill eventually be visited= Other#ise, !art o$ the table #ill be unused= 'o

2C;

ensure this, it is o$ten suggested that the table si8e be a !rime number= 'his is the reason #e have been using 22 in our e*am!les= + variation o$ the linear !robing idea is called -uadratic probing= Instead o$ using a constant ?s,i!@ value, #e use a rehash $unction that increments the hash value by 2, ;, B, D, E, and so on= 'his means that i$ the $irst hash value is h, the successive values are hK2, hK<,

hKE, hK2C, and so on= In other #ords, 3uadratic !robing uses a s,i! consisting o$
successive !er$ect s3uares= Figure 11 sho#s our e*am!le values a$ter they are !laced using this techni3ue=

Collision Resolution #ith (uadratic %robing +n alternative method $or handling the collision !roblem is to allo# each slot to hold a re$erence to a collection -or chain. o$ items= #haining allo#s many items to e*ist at the same location in the hash table= hen collisions ha!!en, the item is still !laced in the !ro!er slot o$ the hash table= +s more and more items hash to the same location, the di$$iculty o$ searching $or the item in the collection increases= Figure 12 sho#s the items as they are added to a hash table that uses chaining to resolve collisions=

Collision Resolution #ith Chaining hen #e #ant to search $or an item, #e use the hash $unction to generate the slot #here it should reside= Since each slot holds a collection, #e use a searching techni3ue to decide #hether the item is !resent= 'he advantage is that on the average there are li,ely to be many $e#er items in each slot, so the search is !erha!s more e$$icient= e #ill loo, at the analysis $or hashing at the end o$ this section= Sel$ Chec,

2C<

0 In a hash table o$ si8e 2; #hich inde* !ositions #ould the $ollo#ing t#o ,eys ma! to" 9D, 2;G a. 2, 2G b. 2;, G c. 2, G d. 9, ; 0 Su!!ose you are given the $ollo#ing set o$ ,eys to insert into a hash table that holds e*actly 22 values0 22; , 22D , ED , 2GG , 22< , 2GF , 22C , 2GB , EE hich o$ the $ollo#ing best demonstrates the contents o$ the has table a$ter all the ,eys have been inserted using linear !robing" a. 2GG, OO, OO, 22;, 22<, 2GB, 22C, 22D, ED, 2GF, EE b. EE, 2GG, OO, 22;, 22<, OO, 22C, 22D, 2GB, ED, 2GF c. 2GG, 22;, 22D, ED, 2<, 2GF, 22C, 2GB, EE, OO, OO d. 22D, 22<, 2GF, 22C, 2GB, EE, OO, OO, ED, 2GG, 22;

Implementing the Map Abstract Data Type


One o$ the most use$ul %ython collections is the dictionary= Recall that a dictionary is an associative data ty!e #here you can store ,eyAdata !airs= 'he ,ey is used to loo, u! the associated data value= e o$ten re$er to this idea as a map= 'he ma! abstract data ty!e is de$ined as $ollo#s= 'he structure is an unordered collection o$ associations bet#een a ,ey and a data value= 'he ,eys in a ma! are all uni3ue so that there is a one4to4one relationshi! bet#een a ,ey and a value= 'he o!erations are given belo#=
Gap() Create a ne#, em!ty ma!= It returns an em!ty ma! collection= put(=e0.2al) +dd a ne# ,ey4value !air to the ma!= I$ the ,ey is already

in the ma!

then re!lace the old value #ith the ne# value= get(=e0) Given a ,ey, return the value stored in the ma! or 7one other#ise= del Delete the ,ey4value !air $rom the ma! using a statement o$ the $orm del map-=e0/= len() Return the number o$ ,ey4value !airs stored in the ma!= in Return )rue $or a statement o$ the $orm =e0 in map, i$ the given ,ey is in the ma!, *alse other#ise=

One o$ the great bene$its o$ a dictionary is the $act that given a ,ey, #e can loo, u! the associated data value very 3uic,ly= In order to !rovide this $ast loo, u! ca!ability, #e need an im!lementation that su!!orts an e$$icient search= e could use a list #ith se3uential or binary search but it #ould be even better to use a hash table as described above since loo,ing u! an item in a hash table can a!!roach '-2. !er$ormance=

2CB

In !isting x #e use t#o lists to create a Oash)a<le class that im!lements the Ma! abstract data ty!e= One list, called slots, #ill hold the ,ey items and a !arallel list, called data, #ill hold the data values= hen #e loo, u! a ,ey, the corres!onding !osition in the data list #ill hold the associated data value= e #ill treat the ,ey list as a hash table using the ideas !resented earlier= /ote that the initial si8e $or the hash table has been chosen to be 22= +lthough this is arbitrary, it is im!ortant that the si8e be a !rime number so that the collision resolution algorithm can be as e$$icient as !ossible=
class Oash)a<le> de: 44init44(sel:)> sel:.siRe + 11 sel:.slots + -7one/ & sel:.siRe sel:.data + -7one/ & sel:.siRe

Ma! +D' Im!lementationAConstructor im!lements the sim!le remainder method= 'he collision resolution techni3ue is linear !robing #ith a ?!lus 2@ rehash $unction= 'he put $unction -see !isting x. assumes that there #ill eventually be an em!ty slot unless the ,ey is already !resent in the sel:.slots= It com!utes the original hash value and i$ that slot is not em!ty, iterates the rehash $unction until an em!ty slot occurs= I$ a nonem!ty slot already contains the ,ey, the old data value is re!laced #ith the ne# data value=
hash:unction de: put(sel:.=e0.data)> hash2alue + sel:.hash:unction(=e0.len(sel:.slots)) i: sel:.slots-hash2alue/ ++ 7one> sel:.slots-hash2alue/ + =e0 sel:.data-hash2alue/ + data else> i: sel:.slots-hash2alue/ ++ =e0> sel:.data-hash2alue/ + data ?replace else> ne3tslot + sel:.rehash(hash2alue.len(sel:.slots)) Fhile sel:.slots-ne3tslot/ Q+ 7one and S sel:.slots-ne3tslot/ Q+ =e0> ne3tslot + sel:.rehash(ne3tslot.len(sel:.slots)) i: sel:.slots-ne3tslot/ ++ 7one> sel:.slots-ne3tslot/+=e0 sel:.data-ne3tslot/+data else> sel:.data-ne3tslot/ + data ?replace de: hash:unction(sel:.=e0.siRe)> return =e0(siRe de: rehash(sel:.oldhash.siRe)> return (oldhash%1)(siRe

Ma! +D' Im!lementationA%ut Method Li,e#ise, the get $unction -see !isting x. begins by com!uting the initial hash value= I$ the value is not in the initial slot, rehash is used to locate the ne*t !ossible !osition= /otice that line 2B guarantees that the search #ill terminate by chec,ing to ma,e sure that #e have not

2CC

returned to the initial slot= I$ that ha!!ens, #e have e*hausted all !ossible slots and the item must not be !resent= 'he $inal methods o$ the Oash)a<le class !rovide additional dictionary $unctionality= e overload the HOOgetitemOOI and HOOsetitemOOI methods to allo# access usingZZSTZZ= 'his means that once a Oash)a<le has been created, the $amiliar inde* o!erator #ill be available= e leave the remaining methods as e*ercises=
de: get(sel:.=e0)> startslot + sel:.hash:unction(=e0.len(sel:.slots)) data + 7one stop + *alse :ound + *alse position + startslot Fhile sel:.slots-position/ Q+ 7one and S not :ound and not stop> i: sel:.slots-position/ ++ =e0> :ound + )rue data + sel:.data-position/ else> position+sel:.rehash(position.len(sel:.slots)) i: position ++ startslot> stop + )rue return data de: 44getitem44(sel:.=e0)> return sel:.get(=e0) de: 44setitem44(sel:.=e0.data)> sel:.put(=e0.data)

Ma! +D' Im!lementation A Search Method 'he $ollo#ing session sho#s the Oash)a<le class in action= 6irst #e #ill create a hash table and store some items #ith integer ,eys and string data values=
>>> O+Oash)a<le() >>> O-!4/+"cat" >>> O-26/+"dog" >>> O-$ /+"lion" >>> O-1"/+"tiger" >>> O-""/+"<ird" >>> O- 1/+"coF" >>> O-44/+"goat" >>> O-!!/+"pig" >>> O-20/+"chic=en" >>> O.slots -"". 44. !!. 20. 26. $ . 1". 7one. 7one. 1. !4/ >>> O.data -6<ird6. 6goat6. 6pig6. 6chic=en6. 6dog6. 6lion6. 6tiger6. 7one. 7one. 6coF6. 6cat6/

/e*t #e #ill access and modi$y some items in the hash table= /ote that the value $or the ,ey 9G is being re!laced=
>>> O-20/

2CD

6chic=en6 >>> O-1"/ 6tiger6 >>> O-20/+6duc=6 >>> O-20/ 6duc=6 >>> O.data -6<ird6. 6goat6. 6pig6. 6duc=6. 6dog6. 6lion6. 6tiger6. 7one. 7one. 6coF6. 6cat6/ >> print(O-$$/) 7one

Analysis o% 0ashing
e stated earlier that in the best case hashing #ould !rovide a '-2., constant time search techni3ue= 1o#ever, due to collisions, the number o$ com!arisons is ty!ically not so sim!le= )ven though a com!lete analysis o$ hashing is beyond the sco!e o$ this te*t, #e can state some #ell4,no#n results that a!!ro*imate the number o$ com!arisons necessary to search $or an item= 'he most im!ortant !iece o$ in$ormation #e need to analy8e the use o$ a hash table is the load $actor, .= Conce!tually, i$ . is small, then there is a lo#er chance o$ collisions, meaning that items are more li,ely to be in the slots #here they belong= I$ . is large, meaning that the table is $illing u!, then there are more and more collisions= 'his means that collision resolution is more di$$icult, re3uiring more com!arisons to $ind an em!ty slot= ith chaining, increased collisions means an increased number o$ items on each chain= +s be$ore, #e #ill have a result $or both a success$ul and an unsuccess$ul search= 6or a success$ul search using o!en addressing #ith linear !robing, the average number o$ com!arisons is a!!ro*imately 29-2K22[.. and an unsuccess$ul search gives 29-2K-22[..9. I$ #e are using chaining, the average number o$ com!arisons is 2K.9 $or the success$ul case, and sim!ly . com!arisons i$ the search is unsuccess$ul=

2CF

Trees
!b"ectives

'o understand #hat a tree data structure is and ho# it is used= 'o see ho# trees can be used to im!lement a ma! data structure= 'o im!lement trees using a list= 'o im!lement trees using classes and re$erences= 'o im!lement trees as a recursive data structure= 'o im!lement a !riority 3ueue using a hea!=

()amples o% Trees
Hsec0treee*am!I /o# that #e have studied linear data structures li,e stac,s and 3ueues and have some e*!erience #ith recursion, #e #ill loo, at a common data structure called the tree= 'rees are used in many areas o$ com!uter science, including o!erating systems, gra!hics, database systems, and com!uter net#or,ing= 'ree data structures have many things in common #ith their botanical cousins= + tree data structure has a root, branches, and leaves= 'he di$$erence bet#een a tree in nature and a tree in com!uter science is that a tree data structure has its root at the to! and its leaves on the bottom= Be$ore #e begin our study o$ tree data structures, let:s loo, at a $e# common e*am!les= Our $irst e*am!le o$ a tree is a classi$ication tree $rom biology= 6igure H$ig0biotreeI sho#s an e*am!le o$ the biological classi$ication o$ some animals= 6rom this sim!le e*am!le, #e can learn about several !ro!erties o$ trees= 'he $irst !ro!erty this e*am!le demonstrates is that trees are hierarchical= By hierarchical, #e mean that trees are structured in layers #ith the more general things near the to! and the more s!eci$ic things near the bottom= 'he to! o$ the hierarchy is the &ingdom, the ne*t layer o$ the tree -the ?children@ o$ the layer above. is the %hylum, then the Class, and so on= 1o#ever, no matter ho# dee! #e go in the classi$ication tree, all the organisms are still animals=

2CE

'a*onomy o$ Some Common +nimals Sho#n as a 'ree /otice that you can start at the to! o$ the tree and $ollo# a !ath made o$ circles and arro#s all the #ay to the bottom= +t each level o$ the tree #e might as, ourselves a 3uestion and then $ollo# the !ath that agrees #ith our ans#er= 6or e*am!le #e might as,, ?Is this animal a Chordate or an +rthro!od"@ I$ the ans#er is ?Chordate@ then #e $ollo# that !ath and as,, ?Is this Chordate a Mammal"@ I$ not, #e are stuc, -but only in this sim!li$ied e*am!le.= hen #e are at the Mammal level #e as,, ?Is this Mammal a %rimate or a Carnivore"@ e can ,ee! $ollo#ing !aths until #e get to the very bottom o$ the tree #here #e have the common name= + second !ro!erty o$ trees is that all o$ the children o$ one node are inde!endent o$ the children o$ another node= 6or e*am!le, the Genus 6elis has the children Domestica and Leo= 'he Genus Musca also has a child named Domestica, but it is a di$$erent node and is inde!endent o$ the Domestica child o$ 6elis= 'his means that #e can change the node that is the child o$ Musca #ithout a$$ecting the child o$ 6elis= + third !ro!erty is that each lea$ node is uni3ue= e can s!eci$y a !ath $rom the root o$ the tree to a lea$ that uni3uely identi$ies each s!ecies in the animal ,ingdomU $or e*am!le, +nimalia e Chordate e Mammal e Carnivora e 6elidae

eZFelis0"ath0rightarro#Z Domestica=
2DG

+nother e*am!le o$ a tree structure that you !robably use every day is a $ile system= In a $ile system, directories, or $olders, are structured as a tree= 6igure H$ig0$iletreeI illustrates a small !art o$ a 5ni* $ile system hierarchy=

+ Small %art o$ the 5ni* 6ile System 1ierarchy 'he $ile system tree has much in common #ith the biological classi$ication tree= >ou can $ollo# a !ath $rom the root to any directory= 'hat !ath #ill uni3uely identi$y that subdirectory -and all the $iles in it.= +nother im!ortant !ro!erty o$ trees, derived $rom their hierarchical nature, is that you can move entire sections o$ a tree -called a subtree. to a di$$erent !osition in the tree #ithout a$$ecting the lo#er levels o$ the hierarchy= 6or e*am!le, #e could ta,e the entire subtree staring #ith MetcM, detach etcM $rom the root and reattach it under usrM= 'his #ould change the uni3ue !athname to htt!d $rom MetcMhtt!d to MusrMetcMhtt!d, but #ould not a$$ect the contents or any children o$ the htt!d directory= + $inal e*am!le o$ a tree is a #eb !age= 'he $ollo#ing is an e*am!le o$ a sim!le #eb !age #ritten using 1'ML= 6igure H$ig0htmlI sho#s the tree that corres!onds to each o$ the 1'ML tags used to create the !age=
,html 3mlns+"http>''FFF.F .org'1$$$'3html" 3ml>lang+"en" lang+"en"> ,head> ,meta http5equi2+"Jontent5)0pe" content+"te3t'htmlZ charset+ut:5#" '> ,title>simple,'title> ,'head> ,<od0> ,h1>A simple Fe< page,'h1> ,ul> ,li>1ist item one,'li> ,li>1ist item tFo,'li> ,'ul> ,h2>,a hre:+"http>''FFF.cs.luther.edu">1uther JS ,'a>,h2> ,'<od0> ,'html>

2D2

+ 'ree Corres!onding to the Mar,u! )lements o$ a

eb %age

'he 1'ML source code and the tree accom!anying the source illustrate another hierarchy= /otice that each level o$ the tree corres!onds to a level o$ nesting inside the 1'ML tags= 'he $irst tag in the source is ,html> and the last is ,'html> +ll the rest o$ the tags in the !age are inside the !air= I$ you chec,, you #ill see that this nesting !ro!erty is true at all levels o$ the tree=

9ocabulary and De%initions


/o# that #e have loo,ed at e*am!les o$ trees, #e #ill $ormally de$ine a tree and its com!onents= /ode + node is a $undamental !art o$ a tree= It can have a name, #hich #e call the ?,ey=@ + node may also have additional in$ormation= e call this additional in$ormation the ?!ayload=@ hile the !ayload in$ormation is not central to many tree algorithms, it is o$ten critical in a!!lications that ma,e use o$ trees= )dge +n edge is another $undamental !art o$ a tree= +n edge connects t#o nodes to sho# that there is a relationshi! bet#een them= )very node -e*ce!t the root. is connected by e*actly one incoming edge $rom another node= )ach node may have several outgoing edges= Root 'he root o$ the tree is the only node in the tree that has no incoming edges= In 6igure H$ig0$iletreeI, M is the root o$ the tree= %ath + !ath is an ordered list o$ nodes that are connected by edges= 6or e*am!le, Mammal e Carnivora e 6elidae e 6elis e Domestica is a !ath= Children 'he set o$ nodes c that have incoming edges $rom the same node to are said to be the children o$ that node= In 6igure H$ig0$iletreeI, nodes logM, s!oolM, and y!M are the children o$ node varM= %arent + node is the !arent o$ all the nodes it connects to #ith outgoing edges= In 6igure H$ig0$iletreeI the node varM is the !arent o$ nodes logM, s!oolM, and y!M= Sibling 2D9

/odes in the tree that are children o$ the same !arent are said to be siblings= 'he nodes etcM and usrM are siblings in the $ilesystem tree= Subtree + subtree is a set o$ nodes and edges com!rised o$ a !arent and all the descendants o$ that !arent= Lea$ /ode + lea$ node is a node that has no children= 6or e*am!le, 1uman and Chim!an8ee are lea$ nodes in 6igure H$ig0biotreeI= Level 'he level o$ a node n is the number o$ edges on the !ath $rom the root node to n= 6or e*am!le, the level o$ the 6elis node in 6igure H$ig0biotreeI is $ive= By de$inition, the level o$ the root node is 8ero= 1eight 'he height o$ a tree is e3ual to the ma*imum level o$ any node in the tree= 'he height o$ the tree in 6igure H$ig0$iletreeI is t#o= ith the basic vocabulary no# de$ined, #e can move on to a $ormal de$inition o$ a tree= In $act, #e #ill !rovide t#o de$initions o$ a tree= One de$inition involves nodes and edges= 'he second de$inition, #hich #ill !rove to be very use$ul, is a recursive de$inition= 1e(inition 'ne2 + tree consists o$ a set o$ nodes and a set o$ edges that connect !airs o$ nodes= + tree has the $ollo#ing !ro!erties0

One node o$ the tree is designated as the root node= )very node n, e*ce!t the root node, is connected by an edge $rom e*actly one other node 0, #here 0 is the !arent o$ n= + uni3ue !ath traverses $rom the root to each node= I$ each node in the tree has a ma*imum o$ t#o children, #e say that the tree is a binary tree=

6igure H$ig0nodeedgetreeI illustrates a tree that $its de$inition one= 'he arro#heads on the edges indicate the direction o$ the connection=

2D;

+ 'ree Consisting o$ a Set o$ /odes and )dges 1e(inition T o2 + tree is either em!ty or consists o$ a root and 8ero or more subtrees, each o$ #hich is also a tree= 'he root o$ each subtree is connected to the root o$ the !arent tree by an edge= 6igure H$ig0rectreeI illustrates this recursive de$inition o$ a tree= 5sing the recursive de$inition o$ a tree, #e ,no# that the tree in 6igure H$ig0rectreeI has at least $our nodes, since each o$ the triangles re!resenting a subtree must have a root= It may have many more nodes than that, but #e do not ,no# unless #e loo, dee!er into the tree=

+ recursive De$inition o$ a tree

Implementation
&ee!ing in mind the de$initions $rom the !revious section, #e can use the $ollo#ing $unctions to create and mani!ulate a binary tree0
Pinar0)ree() creates a ne# instance o$ a binary tree= get1e:tJhild() returns the binary tree corres!onding

to the le$t child o$ the current

node=
getLightJhild()

returns the binary tree corres!onding to the right child o$ the

current node=
setLoot8al(2al) stores the object in !arameter 2al in the current node= getLoot8al() returns the object stored in the current node= insert1e:t(2al) creates a ne# binary tree and installs it as the le$t child

o$ the

current node=
insertLight(2al)

creates a ne# binary tree and installs it as the right child o$ the

current node= 'he ,ey decision in im!lementing a tree is choosing a good internal storage techni3ue= %ython allo#s us t#o very interesting !ossibilities, so #e #ill e*amine both be$ore choosing

2D<

one= 'he $irst techni3ue #e #ill call ?list o$ lists,@ the second techni3ue #e #ill call ?nodes and re$erences=@

/ist o% /ists Representation


In a tree re!resented by a list o$ lists, #e #ill begin #ith %ython:s list data structure and #rite the $unctions de$ined above= +lthough #riting the inter$ace as a set o$ o!erations on a list is a bit di$$erent $rom the other abstract data ty!es #e have im!lemented, it is interesting to do so because it !rovides us #ith a sim!le recursive data structure that #e can loo, at and e*amine directly= In a list o$ lists tree, #e #ill store the value o$ the root node as the $irst element o$ the list= 'he second element o$ the list #ill itsel$ be a list that re!resents the le$t subtree= 'he third element o$ the list #ill be another list that re!resents the right subtree= 'o illustrate this storage techni3ue, let:s loo, at an e*am!le= 6igure H$ig0smalltreeI sho#s a sim!le tree and the corres!onding list im!lementation=

+ small tree
m0)ree + -6a6. ?root -6<6. ?le:t su<tree -6d6 -/. -//. -6e6 -/. -// /. -6c6. ?right su<tree -6:6 -/. -//. -/ / / )he list representation o: the treeC

/otice that #e can access subtrees o$ the list using standard list slices= 'he root o$ the tree is m0)ree-0/, the le$t subtree o$ the root is m0)ree-1/, and the right subtree is m0)ree-2/= 'he $ollo#ing %ython session illustrates creating a sim!le tree using a list= Once the tree is constructed, #e can access the root and the le$t and right subtrees= One very nice !ro!erty o$ this list o$ lists a!!roach is that the structure o$ a list re!resenting a subtree adheres to the structure de$ined $or a treeU the structure itsel$ is recursiveR + subtree that has a root value and t#o em!ty lists is a lea$ node= +nother nice $eature o$ the list o$ lists a!!roach is that it generali8es to a tree that has many subtrees= In the case #here the tree is more than a binary tree, another subtree is just another list= 2DB

1 2 4 ! 6 " m0)ree + -6a6. -6<6. -6d6.-/.-//. -6e6.-/.-// /. -6c6. -6:6.-/.-//. -// / print(m0)ree) print 6le:t su<tree + 6. m0)ree-1/ print 6root + 6. m0)ree-0/ print 6right su<tree + 6. m0)ree-2/

-treeOlist2.

Let:s $ormali8e this de$inition o$ the tree data structure by !roviding some $unctions that ma,e it easy $or us to use lists as trees= /ote that #e are not going to de$ine a binary tree class= 'he $unctions #e #ill #rite #ill just hel! us mani!ulate a standard list as though #e are #or,ing #ith a tree=
de: Pinar0)ree(r)> return -r. -/. -//

'he Pinar0)ree $unction sim!ly constructs a list #ith a root node and t#o em!ty sublists $or the children= 'o add a le$t subtree to the root o$ a tree, #e need to insert a ne# list into the second !osition o$ the root list= e must be care$ul= I$ the list already has something in the second !osition, #e need to ,ee! trac, o$ it and !ush it do#n the tree as the le$t child o$ the list #e are adding= Listing Hlst0linsle$tI sho#s the %ython code $or inserting a le$t child=
de: insert1e:t(root.neFPranch)> t + root.pop(1) i: len(t) > 1> root.insert(1.-neFPranch.t.-//) else> root.insert(1.-neFPranch. -/. -//) return root

/otice that to insert a le$t child, #e $irst obtain the -!ossibly em!ty. list that corres!onds to the current le$t child= e then add the ne# le$t child, installing the old le$t child as the le$t child o$ the ne# one= 'his allo#s us to s!lice a ne# node into the tree at any !osition= 'he code $or insertLight is similar to insert1e:t and is sho#n in Listing Hlst0linsrightI=
de: insertLight(root.neFPranch)> t + root.pop(2)

2DC

i: len(t) > 1> root.insert(2.-neFPranch.-/.t/) else> root.insert(2.-neFPranch.-/.-//) return root

'o round out this set o$ tree4ma,ing $unctions, let:s #rite a cou!le o$ access $unctions $or getting and setting the root value, as #ell as getting the le$t or right subtrees=
de: getLoot8al(root)> return root-0/ de: setLoot8al(root.neF8al)> root-0/ + neF8al de: get1e:tJhild(root)> return root-1/ de: getLightJhild(root)> return root-2/

'he %ython session in 6igure H$ig0ma,e'reessI e*ercises the tree $unctions #e have just #ritten= >ou should ty!e in this code and try it out $or yoursel$= One o$ the e*ercises as,s you to dra# the tree structure resulting $rom this set o$ calls=

1 2 4 ! 6 " # $ 10 11 12 1 14 1! 16 1" 1# 1$ 20 21 22 2 24 2! 26 2" 2# 2$

2DD

0 1 2 4 ! 6 " # $ 40 41 42 4 44 4! 46 de: Pinar0)ree(r)> return -r. -/. -// de: insert1e:t(root.neFPranch)> t + root.pop(1) i: len(t) > 1> root.insert(1.-neFPranch.t.-//) else> root.insert(1.-neFPranch. -/. -//) return root de: insertLight(root.neFPranch)> t + root.pop(2) i: len(t) > 1> root.insert(2.-neFPranch.-/.t/) else> root.insert(2.-neFPranch.-/.-//) return root de: getLoot8al(root)> return root-0/ de: setLoot8al(root.neF8al)> root-0/ + neF8al de: get1e:tJhild(root)> return root-1/ de: getLightJhild(root)> return root-2/ r + Pinar0)ree( ) insert1e:t(r.4) insert1e:t(r.!) insertLight(r.6) insertLight(r.") l + get1e:tJhild(r) print l setLoot8al(l.$) print r insert1e:t(l.11) print r print getLightJhild(getLightJhild(r))

2DF

+ %ython Session to Illustrate Basic 'ree 6unctions -binOtree.

Sel$ Chec, 0
Ti2en the :olloFing statments> 3 + Pinar0)ree(6a6) insert1e:t(3.6<6) insertLight(3.6c6) insertLight(getLightJhild(3).6d6) insert1e:t(getLightJhild(getLightJhild(3)).6e6) Hhich o: the ansFers is the correct representation o: the treeV

a. SXaX, SXbX, ST, STT, SXcX, ST, SXdX, ST, STTTT b. SXaX, SXcX, ST, SXdX, SXeX, ST, STT, STTT, SXbX, ST, STTT c. SXaX, SXbX, ST, STT, SXcX, ST, SXdX, SXeX, ST, STT, STTTT d. SXaX, SXbX, ST, SXdX, SXeX, ST, STT, STTT, SXcX, ST, STTT rite a $unction <uild)ree that returns a tree using the list o$ lists $unctions that loo,s li,e this0

'odes and Re%erences


Our second method to re!resent a tree uses nodes and re$erences= In this case #e #ill de$ine a class that has attributes $or the root value, as #ell as the le$t and right subtrees= Since this re!resentation more closely $ollo#s the object4oriented !rogramming !aradigm, #e #ill continue to use this re!resentation $or the remainder o$ the cha!ter= 2DE

5sing nodes and re$erences, #e might thin, o$ the tree as being structured li,e the one sho#n in 6igure H$ig0treerecI=

+ Sim!le 'ree 5sing a /odes and Re$erences +!!roach e #ill start out #ith a sim!le class de$inition $or the nodes and re$erences a!!roach as sho#n in Listing Hlst0narI= 'he im!ortant thing to remember about this re!resentation is that the attributes le:t and right #ill become re$erences to other instances o$ the Pinar0)ree class= 6or e*am!le, #hen #e insert a ne# le$t child into the tree #e create another instance o$ Pinar0)ree and modi$y sel:.le:tJhild in the root to re$erence the ne# tree=
class Pinar0)ree> de: 44init44(sel:.rootK<A)> sel:.=e0 + rootK<A sel:.le:tJhild + 7one sel:.rightJhild + 7one

/otice that in Listing Hlst0narI, the constructor $unction e*!ects to get some ,ind o$ object to store in the root= dust li,e you can store any object you li,e in a list, the root object o$ a tree can be a re$erence to any object= 6or our early e*am!les, #e #ill store the name o$ the node as the root value= 5sing nodes and re$erences to re!resent the tree in 6igure H$ig0treerecI, #e #ould create si* instances o$ the Binary'ree class= /e*t let:s loo, at the $unctions #e need to build the tree beyond the root node= 'o add a le$t child to the tree, #e #ill create a ne# binary tree object and set the le:t attribute o$ the root to re$er to this ne# object= 'he code $or insert1e:t is sho#n in Listing Hlst0inle$tI=
de: insert1e:t(sel:.neF7ode)> i: sel:.le:tJhild ++ 7one> sel:.le:tJhild + Pinar0)ree(neF7ode) else> t + Pinar0)ree(neF7ode) t.le:tJhild + sel:.le:tJhild sel:.le:tJhild + t

2FG

e must consider t#o cases $or insertion= 'he $irst case is characteri8ed by a node #ith no e*isting le$t child= hen there is no le$t child, sim!ly add a node to the tree= 'he second case is characteri8ed by a node #ith an e*isting right child= In the second case, #e insert a node and !ush the e*isting child do#n one level in the tree= 'he second case is handled by the else statement on line Hlst0inilinsrtI o$ Listing Hlst0inle$tI= 'he code $or insertLight must consider a symmetric set o$ cases= 'here #ill either be no right child, or #e must insert the node bet#een the root and an e*isting right child= 'he insertion code is sho#n in Listing Hlst0insrtI=
de: insertLight(sel:.neF7ode)> i: sel:.rightJhild ++ 7one> sel:.rightJhild + Pinar0)ree(neF7ode) else> t + Pinar0)ree(neF7ode) t.rightJhild + sel:.rightJhild sel:.rightJhild + t

'o round out the de$inition $or a sim!le binary tree data structure, #e #ill #rite access $unctions $or the le$t and right children, as #ell as the root values=
de: getLightJhild(sel:)> return sel:.rightJhild de: get1e:tJhild(sel:)> return sel:.le:tJhild de: setLoot8al(sel:.o<A)> sel:.=e0 + o<A de: getLoot8al(sel:)> return sel:.=e0

/o# that #e have all the !ieces to create and mani!ulate a binary tree, let:s use them to chec, on the structure a bit more= Let:s ma,e a sim!le tree #ith node a as the root, and add nodes b and c as children= 'he $ollo#ing %ython session creates the tree and loo,s at the some o$ the values stored in =e0, le:t, and right= /otice that both the le$t and right children o$ the root are themselves distinct instances o$ the Pinar0)ree class= +s #e said in our original recursive de$inition $or a tree, this allo#s us to treat any child o$ a binary tree as a binary tree itsel$= H

1 2 4 ! 6 " # $

2F2

10 11 12 1 14 :rom p0thonds.trees.<inar0)ree import Pinar0)ree r + Pinar0)ree(6a6) r.getLoot8al() print(r.get1e:tJhild()) r.insert1e:t(6<6) print(r.get1e:tJhild()) print(r.get1e:tJhild().getLoot8al()) r.insertLight(6c6) print(r.getLightJhild()) print(r.getLightJhild().getLoot8al()) r.getLightJhild().setLoot8al(6hello6) print(r.getLightJhild().getLoot8al())

-bintree.

Sel$ Chec, rite a $unction <uild)ree that returns a tree using the nodes and re$erences im!lementation that loo,s li,e this0

Binary Tree Applications


Parse Tree
ith the im!lementation o$ our tree data structure com!lete, #e no# loo, at an e*am!le o$ ho# a tree can be used to solve some real !roblems= In this section #e #ill loo, at !arse

2F9

trees= %arse trees can be used to re!resent real4#orld constructions li,e sentences -see Figure x., or mathematical e*!ressions=

+ %arse 'ree $or a Sim!le Sentence Figure x sho#s the hierarchical structure o$ a sim!le sentence= Re!resenting a sentence as a tree structure allo#s us to #or, #ith the individual !arts o$ the sentence by using subtrees=

%arse 'ree $or --DK;.-B[9.. e can also re!resent a mathematical e*!ression such as --DK;.-B[9.. as a !arse tree, as sho#n in Figure x= e have already loo,ed at $ully !arenthesi8ed e*!ressions, so #hat do #e ,no# about this e*!ression" e ,no# that multi!lication has a higher !recedence than either addition or subtraction= Because o$ the !arentheses, #e ,no# that be$ore #e can do the multi!lication #e must evaluate the !arenthesi8ed addition and subtraction e*!ressions= 'he hierarchy o$ the tree hel!s us understand the order o$ evaluation $or the #hole e*!ression= Be$ore #e can evaluate the to!4level multi!lication, #e must evaluate the addition and the subtraction in the subtrees= 'he addition, #hich is the le$t subtree, evaluates to 2G= 'he 2F;

subtraction, #hich is the right subtree, evaluates to ;= 5sing the hierarchical structure o$ trees, #e can sim!ly re!lace an entire subtree #ith one node once #e have evaluated the e*!ressions in the children= +!!lying this re!lacement !rocedure gives us the sim!li$ied tree sho#n in Figure x=

+ Sim!li$ied %arse 'ree $or --DK;.-B[9.. In the rest o$ this section #e are going to e*amine !arse trees in more detail= In !articular #e #ill loo, at

1o# to build a !arse tree $rom a $ully !arenthesi8ed mathematical e*!ression= 1o# to evaluate the e*!ression stored in a !arse tree= 1o# to recover the original mathematical e*!ression $rom a !arse tree=

'he $irst ste! in building a !arse tree is to brea, u! the e*!ression string into a list o$ to,ens= 'here are $our di$$erent ,inds o$ to,ens to consider0 le$t !arentheses, right !arentheses, o!erators, and o!erands= e ,no# that #henever #e read a le$t !arenthesis #e are starting a ne# e*!ression, and hence #e should create a ne# tree to corres!ond to that e*!ression= Conversely, #henever #e read a right !arenthesis, #e have $inished an e*!ression= e also ,no# that o!erands are going to be lea$ nodes and children o$ their o!erators= 6inally, #e ,no# that every o!erator is going to have both a le$t and a right child= 5sing the in$ormation $rom above #e can de$ine $our rules as $ollo#s0 2= I$ the current to,en is a 6(6, add a ne# node as the le$t child o$ the current node, and descend to the le$t child= 9= I$ the current to,en is in the list -6%6.656.6'6.6&6/, set the root value o$ the current node to the o!erator re!resented by the current to,en= +dd a ne# node as the right child o$ the current node and descend to the right child= ;= I$ the current to,en is a number, set the root value o$ the current node to the number and return to the !arent= <= I$ the current to,en is a 6)6, go to the !arent o$ the current node= Be$ore #riting the %ython code, let:s loo, at an e*am!le o$ the rules outlined above in action= e #ill use the e*!ression -;K-<B..= e #ill !arse this e*!ression into the $ollo#ing list o$ character to,ens -6(6. 6 6. 6%6. 6(6. 646. 6&6. 6!6 .6)6.6)6/= Initially #e #ill start out #ith a !arse tree that consists o$ an em!ty root node= Figure x illustrates the structure and contents o$ the !arse tree, as each ne# to,en is !rocessed=

2F<

2FB

'racing %arse 'ree Construction 5sing Figure x, let:s #al, through the e*am!le ste! by ste!0 2= Create an em!ty tree= 2FC

9= Read - as the $irst to,en= By rule 2, create a ne# node as the le$t child o$ the root= Ma,e the current node this ne# child= ;= Read ; as the ne*t to,en= By rule ;, set the root value o$ the current node to ; and go bac, u! the tree to the !arent= <= Read K as the ne*t to,en= By rule 9, set the root value o$ the current node to K and add a ne# node as the right child= 'he ne# right child becomes the current node= B= Read a - as the ne*t to,en= By rule 2, create a ne# node as the le$t child o$ the current node= 'he ne# le$t child becomes the current node= C= Read a < as the ne*t to,en= By rule ;, set the value o$ the current node to <= Ma,e the !arent o$ < the current node= D= Read L as the ne*t to,en= By rule 9, set the root value o$ the current node to L and create a ne# right child= 'he ne# right child becomes the current node= F= Read B as the ne*t to,en= By rule ;, set the root value o$ the current node to B= Ma,e the !arent o$ B the current node= E= Read . as the ne*t to,en= By rule < #e ma,e the !arent o$ L the current node= 2G= Read . as the ne*t to,en= By rule < #e ma,e the !arent o$ K the current node= +t this !oint there is no !arent $or K so #e are done= 6rom the e*am!le above, it is clear that #e need to ,ee! trac, o$ the current node as #ell as the !arent o$ the current node= 'he tree inter$ace !rovides us #ith a #ay to get children o$ a node, through the get1e:tJhild and getLightJhild methods, but ho# can #e ,ee! trac, o$ the !arent" + sim!le solution to ,ee!ing trac, o$ !arents as #e traverse the tree is to use a stac,= henever #e #ant to descend to a child o$ the current node, #e $irst !ush the current node on the stac,= hen #e #ant to return to the !arent o$ the current node, #e !o! the !arent o$$ the stac,= 5sing the rules described above, along #ith the Stac= and Pinar0)ree o!erations, #e are no# ready to #rite a %ython $unction to create a !arse tree= 'he code $or our !arse tree builder is !resented in Listing Hlst0builde*!I=

1 2 4 ! 6 " # $ 10 11 12 1 14 1! 16 1" 1# 1$

2FD

20 21 22 2 24 2! 26 2" 2# 2$ 0 1 2 :rom p0thonds.<asic.stac= import Stac= :rom p0thonds.trees.<inar0)ree import Pinar0)ree de: <uildNarse)ree(:pe3p)> :plist + :pe3p.split() pStac= + Stac=() e)ree + Pinar0)ree(66) pStac=.push(e)ree) current)ree + e)ree :or i in :plist> i: i ++ 6(6> current)ree.insert1e:t(66) pStac=.push(current)ree) current)ree + current)ree.get1e:tJhild() eli: i not in -6%6. 656. 6&6. 6'6. 6)6/> current)ree.setLoot8al(int(i)) parent + pStac=.pop() current)ree + parent eli: i in -6%6. 656. 6&6. 6'6/> current)ree.setLoot8al(i) current)ree.insertLight(66) pStac=.push(current)ree) current)ree + current)ree.getLightJhild() eli: i ++ 6)6> current)ree + pStac=.pop() else> raise 8alue@rror return e)ree pt + <uildNarse)ree("( ( 10 % ! ) & pt.postorder() )")

Building a %arse 'ree -!arsebuild.

'he $our rules $or building a !arse tree are coded as the $irst $our clauses o$ the i: statement on lines Hlst0!tl!I, Hlst0!to!erI, Hlst0!to!ndI, and Hlst0!tr!I o$ Listing Hlst0builde*!I= In each case you can see that the code im!lements the rule, as described above, #ith a $e# calls to the Pinar0)ree or Stac= methods= 'he only error chec,ing #e do in this $unction is in the else

2FF

clause, #here #e raise a 8alue@rror e*ce!tion i$ #e get a to,en $rom the list that #e do not recogni8e= /o# that #e have built a !arse tree, #hat can #e do #ith it" +s a $irst e*am!le, #e #ill #rite a $unction to evaluate the !arse tree, returning the numerical result= 'o #rite this $unction, #e #ill ma,e use o$ the hierarchical nature o$ the tree= Loo, bac, at Figure x= Recall that #e can re!lace the original tree #ith the sim!li$ied tree sho#n in Figure x= 'his suggests that #e can #rite an algorithm that evaluates a !arse tree by recursively evaluating each subtree= +s #e have done #ith !ast recursive algorithms, #e #ill begin the design $or the recursive evaluation $unction by identi$ying the base case= + natural base case $or recursive algorithms that o!erate on trees is to chec, $or a lea$ node= In a !arse tree, the lea$ nodes #ill al#ays be o!erands= Since numerical objects li,e integers and $loating !oints re3uire no $urther inter!retation, the e2aluate $unction can sim!ly return the value stored in the lea$ node= 'he recursive ste! that moves the $unction to#ard the base case is to call e2aluate on both the le$t and the right children o$ the current node= 'he recursive call e$$ectively moves us do#n the tree, to#ard a lea$ node= 'o !ut the results o$ the t#o recursive calls together, #e can sim!ly a!!ly the o!erator stored in the !arent node to the results returned $rom evaluating both children= In the e*am!le $rom Figure x #e see that the t#o children o$ the root evaluate to themselves, namely 2G and ;= +!!lying the multi!lication o!erator gives us a $inal result o$ ;G= 'he code $or a recursive e2aluate $unction is sho#n in Listing Hlst0etevalI= 6irst, #e obtain re$erences to the le$t and the right children o$ the current node= I$ both the le$t and right children evaluate to 7one, then #e ,no# that the current node is really a lea$ node= 'his chec, is on line Hlst0etbcI= I$ the current node is not a lea$ node, loo, u! the o!erator in the current node and a!!ly it to the results $rom recursively evaluating the le$t and right children= 'o im!lement, #e use a dictionary #ith the ,eys 6%6. 656. 6&6, and 6'6= 'he values stored in the dictionary are $unctions $rom %ython:s o!erator module= 'he o!erator module !rovides us #ith the $unctional versions o$ many commonly used o!erators= hen #e loo, u! an o!erator in the dictionary, the corres!onding $unction object is retrieved= Since the retrieved object is a $unction, #e can call it in the usual #ay :unction(param1.param2)= So the loo,u! opers-6%6/(2.2) is e3uivalent to operator.add(2.2)=
de: e2aluate(parse)ree)> opers + B6%6>operator.add. 656>operator.su<. 6&6>operator.mul. 6'6>operator.truedi2C le:tJ + parse)ree.get1e:tJhild() rightJ + parse)ree.getLightJhild() i: le:tJ and rightJ> ?'' Sla<elBlst>et<cC :n + opers-parse)ree.getLoot8al()/ return :n(e2aluate(le:tJ).e2aluate(rightJ)) ?''Sla<elBlst>e2ale3precC else> return parse)ree.getLoot8al()

6inally, #e #ill trace the e2aluate $unction on the !arse tree #e created in Figure x= hen #e $irst call e2aluate, #e !ass the root o$ the entire tree as the !arameter parse)ree= 'hen #e obtain re$erences to the le$t and right children to ma,e sure they e*ist= 'he recursive call 2FE

ta,es !lace on line Hlst0evale*!recI= e begin by loo,ing u! the o!erator in the root o$ the tree, #hich is 6%6= 'he 6%6 o!erator ma!s to the operator.add $unction call, #hich ta,es t#o !arameters= +s usual $or a %ython $unction call, the $irst thing %ython does is to evaluate the !arameters that are !assed to the $unction= In this case both !arameters are recursive $unction calls to our e2aluate $unction= 5sing le$t4to4right evaluation, the $irst recursive call goes to the le$t= In the $irst recursive call the e2aluate $unction is given the le$t subtree= e $ind that the node has no le$t or right children, so #e are in a lea$ node= hen #e are in a lea$ node #e just return the value stored in the lea$ node as the result o$ the evaluation= In this case #e return the integer ;= +t this !oint #e have one !arameter evaluated $or our to!4level call to operator.add= But #e are not done yet= Continuing the le$t4to4right evaluation o$ the !arameters, #e no# ma,e a recursive call to evaluate the right child o$ the root= e $ind that the node has both a le$t and a right child so #e loo, u! the o!erator stored in this node, 6&6, and call this $unction using the le$t and right children as the !arameters= +t this !oint you can see that both recursive calls #ill be to lea$ nodes, #hich #ill evaluate to the integers $our and $ive res!ectively= ith the t#o !arameters evaluated, #e return the result o$ operator.mul(4.!)= +t this !oint #e have evaluated the o!erands $or the to! level 6%6 o!erator and all that is le$t to do is $inish the call to operator.add( .20)= 'he result o$ the evaluation o$ the entire e*!ression tree $or

-;K-<B.. is 9;=

Tree Traversals
/o# that #e have e*amined the basic $unctionality o$ our tree data structure, it is time to loo, at some additional usage !atterns $or trees= 'hese usage !atterns can be divided into the three #ays that #e access the nodes o$ the tree= 'here are three commonly used !atterns to visit all the nodes in a tree= 'he di$$erence bet#een these !atterns is the order in #hich each node is visited= e call this visitation o$ the nodes a ?traversal=@ 'he three traversals #e #ill loo, at are called preorder, inorder, and postorder= Let:s start out by de$ining these three traversals more care$ully, then loo, at some e*am!les #here these !atterns are use$ul= !reorder In a !reorder traversal, #e visit the root node $irst, then recursively do a !reorder traversal o$ the le$t subtree, $ollo#ed by a recursive !reorder traversal o$ the right subtree= inorder In an inorder traversal, #e recursively do an inorder traversal on the le$t subtree, visit the root node, and $inally do a recursive inorder traversal o$ the right subtree= !ostorder In a !ostorder traversal, #e recursively do a !ostorder traversal o$ the le$t subtree and the right subtree $ollo#ed by a visit to the root node= Let:s loo, at some e*am!les that illustrate each o$ these three ,inds o$ traversals= 6irst let:s loo, at the !reorder traversal= +s an e*am!le o$ a tree to traverse, #e #ill re!resent this boo, as a tree= 'he boo, is the root o$ the tree, and each cha!ter is a child o$ the root= )ach section #ithin a cha!ter is a child o$ the cha!ter, and each subsection is a child o$ its section, and so on= Figure x sho#s a limited version o$ a boo, #ith only t#o cha!ters= /ote that the traversal algorithm #or,s $or trees #ith any number o$ children, but #e #ill stic, #ith binary trees $or no#= 2EG

Re!resenting a Boo, as a 'ree Su!!ose that you #anted to read this boo, $rom $ront to bac,= 'he !reorder traversal gives you e*actly that ordering= Starting at the root o$ the tree -the Boo, node. #e #ill $ollo# the !reorder traversal instructions= e recursively call preorder on the le$t child, in this case Cha!ter2= e again recursively call preorder on the le$t child to get to Section 2=2= Since Section 2=2 has no children, #e do not ma,e any additional recursive calls= hen #e are $inished #ith Section 2=2, #e move u! the tree to Cha!ter 2= +t this !oint #e still need to visit the right subtree o$ Cha!ter 2, #hich is Section 2=9= +s be$ore #e visit the le$t subtree, #hich brings us to Section 2=9=2, then #e visit the node $or Section 2=9=9= ith Section 2=9 $inished, #e return to Cha!ter 2= 'hen #e return to the Boo, node and $ollo# the same !rocedure $or Cha!ter 9= 'he code $or #riting tree traversals is sur!risingly elegant, largely because the traversals are #ritten recursively= Listing Hlst0!reorderI sho#s the %ython code $or a !reorder traversal o$ a binary tree= >ou may #onder, #hat is the best #ay to #rite an algorithm li,e !reorder traversal" Should it be a $unction that sim!ly uses a tree as a data structure, or should it be a method o$ the tree data structure itsel$" Listing Hlst0!reorde*tI sho#s a version o$ the !reorder traversal #ritten as an e*ternal $unction that ta,es a binary tree as a !arameter= 'he e*ternal $unction is !articularly elegant because our base case is sim!ly to chec, i$ the tree e*ists= I$ the tree !arameter is 7one, then the $unction returns #ithout ta,ing any action=
de: preorder(tree)> i: tree> print(tree.getLoot8al()) preorder(tree.get1e:tJhild()) preorder(tree.getLightJhild())

2E2

e can also im!lement preorder as a method o$ the Pinar0)ree class= 'he code $or im!lementing preorder as an internal method is sho#n in Listing Hlst0!reorderI= /otice #hat ha!!ens #hen #e move the code $rom internal to e*ternal= In general, #e just re!lace tree #ith sel:= 1o#ever, #e also need to modi$y the base case= 'he internal method must chec, $or the e*istence o$ the le$t and the right children be(ore ma,ing the recursive call to preorder=
de: preorder(sel:)> print(sel:.=e0) i: sel:.le:tJhild> sel:.le:t.preorder() i: sel:.rightJhild> sel:.right.preorder()

hich o$ these t#o #ays to im!lement preorder is best" 'he ans#er is that im!lementing preorder as an e*ternal $unction is !robably better in this case= 'he reason is that you very rarely #ant to just traverse the tree= In most cases you are going to #ant to accom!lish something else #hile using one o$ the basic traversal !atterns= In $act, #e #ill see in the ne*t e*am!le that the postorder traversal !attern $ollo#s very closely #ith the code #e #rote earlier to evaluate a !arse tree= 'here$ore #e #ill #rite the rest o$ the traversals as e*ternal $unctions= 'he algorithm $or the postorder traversal, in Listing Hlst0!ostorderI is nearly identical to preorder, e*ce!t that #e move the call to !rint to the end o$ the $unction=
de: postorder(tree)> i: tree Q+ 7one> postorder(tree.get1e:tJhild()) postorder(tree.getLightJhild()) print(tree.getLoot8al())

e have already seen a common use $or the !ostorder traversal, namely evaluating a !arse tree= Loo, bac, at Listing Hlst0etevalI again= hat #e are doing is evaluating the le$t subtree, evaluating the right subtree, and combining them in the root through the $unction call to an o!erator= +ssume that our binary tree is going to store only e*!ression tree data= Let:s re#rite the evaluation $unction, but model it even more closely on the postorder code in Listing Hlst0!ostorderI=
de: postordere2al(tree)> opers + B6%6>operator.add. 656>operator.su<. 6&6>operator.mul. 6'6>operator.truedi2C res1 + 7one res2 + 7one i: tree> res1 + postordere2al(tree.get1e:tJhild()) ?'' Sla<elBpele:tC res2 + postordere2al(tree.getLightJhild()) ?'' Sla<elBperightC i: res1 and res2> return opers-tree.getLoot8al()/(res1.res2) ?'' Sla<elBpee2alC else> return tree.getLoot8al()

/otice that the $orm in Listing Hlst0!ostevalI is the same as the $orm in Listing Hlst0!ostorderI, e*ce!t that instead o$ !rinting the ,ey at the end o$ the $unction, #e

2E9

return it= 'his allo#s us to save the values returned $rom the recursive calls in lines H!ele$tI and H!erightI= e then use these saved values along #ith the o!erator on line H!eevalI= 'he $inal traversal #e #ill loo, at in this section is the inorder traversal= In the inorder traversal #e visit the le$t subtree, $ollo#ed by the root, and $inally the right subtree= Listing Hlst0inorderI sho#s our code $or the inorder traversal= /otice that in all three o$ the traversal $unctions #e are sim!ly changing the !osition o$ the print statement #ith res!ect to the t#o recursive $unction calls=
de: inorder(tree)> i: tree Q+ 7one> inorder(tree.get1e:tJhild()) print(tree.getLoot8al()) inorder(tree.getLightJhild())

I$ #e !er$orm a sim!le inorder traversal o$ a !arse tree #e get our original e*!ression bac,, #ithout any !arentheses= Let:s modi$y the basic inorder algorithm to allo# us to recover the $ully !arenthesi8ed version o$ the e*!ression= 'he only modi$ications #e #ill ma,e to the basic tem!late are as $ollo#s0 !rint a le$t !arenthesis be(ore the recursive call to the le$t subtree, and !rint a right !arenthesis a(ter the recursive call to the right subtree= 'he modi$ied code is sho#n in Listing Hlst0!rt$!eI=
de: printe3p(tree)> s8al + "" i: tree> s8al + 6(6 % printe3p(tree.get1e:tJhild()) s8al + s8al % str(tree.getLoot8al()) s8al + s8al % printe3p(tree.getLightJhild())%6)6 return s8al

'he $ollo#ing %ython session sho#s the printe3p and postordere2al methods in action=
>>> :rom p0thonds.trees import Pinar0)ree >>> 3 + Pinar0)ree(6&6) >>> 3.insert1e:t(6%6) >>> l + 3.get1e:tJhild() >>> l.insert1e:t(4) >>> l.insertLight(!) >>> 3.insertLight(") >>> >>> print(printe3p(3)) (((4) % (!)) & (")) >>> >>> print(postordere2al(3)) 6 >>>

/otice that the printe3p $unction as #e have im!lemented it !uts !arentheses around each number= hile not incorrect, the !arentheses are clearly not needed= In the e*ercises at the end o$ this cha!ter you are as,ed to modi$y the printe3p $unction to remove this set o$ !arentheses=

Priority 2ueues with Binary 0eaps


2E;

In Cha!ter Hcha!0basicdsI you learned about the $irst in $irst out data structure called a 3ueue= One im!ortant variation o$ a 3ueue is called a priority -ueue= + !riority 3ueue acts li,e a 3ueue in that you de3ueue an item by removing it $rom the $ront= 1o#ever, in a !riority 3ueue the logical order o$ items inside a 3ueue is determined by their !riority= 'he highest !riority items are at the $ront o$ the 3ueue and the lo#est !riority items are at the bac,= 'hus #hen you en3ueue an item on a !riority 3ueue, the ne# item may move all the #ay to the $ront= e #ill see that the !riority 3ueue is a use$ul data structure $or some o$ the gra!h algorithms #e #ill study in the ne*t cha!ter= >ou can !robably thin, o$ a cou!le o$ easy #ays to im!lement a !riority 3ueue using sorting $unctions and lists= 1o#ever, inserting into a list is '-n. and sorting a list is '-nlogn.= e can do better= 'he classic #ay to im!lement a !riority 3ueue is using a data structure called a binary heap= + binary hea! #ill allo# us both en3ueue and de3ueue items in '-logn.= 'he binary hea! is interesting to study because #hen #e diagram the hea! it loo,s a lot li,e a tree, but #hen #e im!lement it #e use only a single list as an internal re!resentation= 'he binary hea! has t#o common variations0 the min heap, in #hich the smallest ,ey is al#ays at the $ront, and the ma) heap, in #hich the largest ,ey value is al#ays at the $ront= In this section #e #ill im!lement the min hea!= e leave a ma* hea! im!lementation as an e*ercise=

Binary 0eap !perations


'he basic o!erations #e #ill im!lement $or our binary hea! are as $ollo#s0
Pinar0Oeap() creates a ne#, em!ty, binary hea!= insert(=) adds a ne# item to the hea!= :indGin() returns the item #ith the minimum ,ey value, leaving item in the hea!= delGin() returns the item #ith the minimum ,ey value, removing the item $rom the

hea!=
is@mpt0() returns true i$ the hea! is em!ty, $alse other#ise= siRe() returns the number o$ items in the hea!= <uildOeap(list) builds a ne# hea! $rom a list o$ ,eys=

'he $ollo#ing %ython session demonstrates the use o$ some o$ the binary hea! methods=

1 2 4 ! 6 " # $

2E<

10 11 12 1 14 1! :rom p0thonds.trees.<inheap import PinOeap <h + PinOeap() <h.insert(!) <h.insert(") <h.insert( ) <h.insert(11) print(<h.delGin()) print(<h.delGin()) print(<h.delGin()) print(<h.delGin())

-hea!2.

Binary 0eap Implementation


The Structure Property
In order to ma,e our hea! #or, e$$iciently, #e #ill ta,e advantage o$ the logarithmic nature o$ the tree to re!resent our hea!= >ou #ill learn in section Hsec0stanalI that in order to guarantee logarithmic !er$ormance, #e must ,ee! our tree balanced= + balanced binary tree has roughly the same number o$ nodes in the le$t and right subtrees o$ the root= In our hea! im!lementation #e ,ee! the tree balanced by creating a complete binary tree= + com!lete binary tree is a tree in #hich each level has all o$ its nodes= 'he e*ce!tion to this is the bottom level o$ the tree, #hich #e $ill in $rom le$t to right= Figure x sho#s an e*am!le o$ a com!lete binary tree=

+ Com!lete Binary 'ree

2EB

+nother interesting !ro!erty o$ a com!lete tree is that #e can re!resent it using a single list= e do not need to use nodes and re$erences or even lists o$ lists= Because the tree is com!lete, the le$t child o$ a !arent -at !osition 0. is the node that is $ound in !osition 90 in the list= Similarly, the right child o$ the !arent is at !osition 90K2 in the list= 'o $ind the !arent o$ any node in the tree, #e can sim!ly use %ython:s integer division= Given that a node is at !osition n in the list, the !arent is at !osition nM9= Figure x illustrates a com!lete binary tree and also gives the list re!resentation o$ the tree= 'he list re!resentation o$ the tree, along #ith the $ull structure !ro!erty, allo#s us to e$$iciently traverse a com!lete binary tree using only a $e# sim!le mathematical o!erations= e #ill see that this also leads to an e$$icient im!lementation o$ our binary hea!=

The "eap Order Property


'he method that #e #ill use to store items in a hea! relies on maintaining the hea! order !ro!erty= 'he heap order property is as $ollo#s0 In a hea!, $or every node x #ith !arent 0, the ,ey in 0 is smaller than or e3ual to the ,ey in x= Figure x also illustrates a com!lete binary tree that has the hea! order !ro!erty=

+ Com!lete Binary 'ree, along #ith its List Re!resentation

"eap Operations
e #ill begin our im!lementation o$ a binary hea! #ith the constructor= Since the entire binary hea! can be re!resented by a single list, all the constructor #ill do is initiali8e the list and an attribute currentSiRe to ,ee! trac, o$ the current si8e o$ the hea!= Listing Hlst0bh0initI sho#s the %ython code $or the constructor= >ou #ill notice that an em!ty

2EC

binary hea! has a single 8ero as the $irst element o$ heap1ist and that this 8ero is not used, but is there so that sim!le integer division can be used in later methods=
de: 44init44(sel:)> sel:.heap1ist + -0/ sel:.currentSiRe + 0

'he ne*t method #e #ill im!lement is insert= 'he easiest, and most e$$icient, #ay to add an item to a list is to sim!ly a!!end the item to the end o$ the list= 'he good ne#s about a!!ending is that it guarantees that #e #ill maintain the com!lete tree !ro!erty= 'he bad ne#s about a!!ending is that #e #ill very li,ely violate the hea! structure !ro!erty= 1o#ever, it is !ossible to #rite a method that #ill allo# us to regain the hea! structure !ro!erty by com!aring the ne#ly added item #ith its !arent= I$ the ne#ly added item is less than its !arent, then #e can s#a! the item #ith its !arent= Figure x sho#s the series o$ s#a!s needed to !ercolate the ne#ly added item u! to its !ro!er !osition in the tree=

2ED

%ercolate the /e# /ode u! to Its %ro!er %osition 2EF

/otice that #hen #e !ercolate an item u!, #e are restoring the hea! !ro!erty bet#een the ne#ly added item and the !arent= e are also !reserving the hea! !ro!erty $or any siblings= O$ course, i$ the ne#ly added item is very small, #e may still need to s#a! it u! another level= In $act, #e may need to ,ee! s#a!!ing until #e get to the to! o$ the tree= Listing Hlst0bh0hel!ersI sho#s the percIp method, #hich !ercolates a ne# item as $ar u! in the tree as it needs to go to maintain the hea! !ro!erty= 1ere is #here our #asted element in heap1ist is im!ortant= /otice that #e can com!ute the !arent o$ any node by using sim!le integer division= 'he !arent o$ the current node can be com!uted by dividing the inde* o$ the current node by 9= e are no# ready to #rite the insert method= 'he %ython code $or insert is sho#n in Listing Hlst0bh0addI= Most o$ the #or, in the insert method is really done by percIp= Once a ne# item is a!!ended to the tree, percIp ta,es over and !ositions the ne# item !ro!erly=
de: percIp(sel:.i)> Fhile i '' 2 > 0> i: sel:.heap1ist-i/ , sel:.heap1ist-i '' 2/> tmp + sel:.heap1ist-i '' 2/ sel:.heap1ist-i '' 2/ + sel:.heap1ist-i/ sel:.heap1ist-i/ + tmp i + i '' 2 de: insert(sel:.=)> sel:.heap1ist.append(=) sel:.currentSiRe + sel:.currentSiRe % 1 sel:.percIp(sel:.currentSiRe)

ith the insert method !ro!erly de$ined, #e can no# loo, at the delGin method= Since the hea! !ro!erty re3uires that the root o$ the tree be the smallest item in the tree, $inding the minimum item is easy= 'he hard !art o$ delGin is restoring $ull com!liance #ith the hea! structure and hea! order !ro!erties a$ter the root has been removed= e can restore our hea! in t#o ste!s= 6irst, #e #ill restore the root item by ta,ing the last item in the list and moving it to the root !osition= Moving the last item maintains our hea! structure !ro!erty= 1o#ever, #e have !robably destroyed the hea! order !ro!erty o$ our binary hea!= Second, #e #ill restore the hea! order !ro!erty by !ushing the ne# root node do#n the tree to its !ro!er !osition= Figure x sho#s the series o$ s#a!s needed to move the ne# root node to its !ro!er !osition in the hea!=

2EE

9GG

%ercolating the Root /ode do#n the 'ree In order to maintain the hea! order !ro!erty, all #e need to do is s#a! the root #ith its smallest child less than the root= +$ter the initial s#a!, #e may re!eat the s#a!!ing !rocess #ith a node and its children until the node is s#a!!ed into a !osition on the tree #here it is already less than both children= 'he code $or !ercolating a node do#n the tree is $ound in the percDoFn and minJhild methods in Listing Hlst0bh0!do#nI=
de: percDoFn(sel:.i)> Fhile (i & 2) ,+ sel:.currentSiRe> mc + sel:.minJhild(i) i: sel:.heap1ist-i/ > sel:.heap1ist-mc/> tmp + sel:.heap1ist-i/ sel:.heap1ist-i/ + sel:.heap1ist-mc/ sel:.heap1ist-mc/ + tmp i + mc de: minJhild(sel:.i)> i: i & 2 % 1 > sel:.currentSiRe> return i & 2 else> i: sel:.heap1ist-i&2/ , sel:.heap1ist-i&2%1/> return i & 2 else> return i & 2 % 1

'he code $or the delmin o!eration is in Listing Hlst0bh0delI= /ote that once again the hard #or, is handled by a hel!er $unction, in this case percDoFn=
de: delGin(sel:)> ret2al + sel:.heap1ist-1/ sel:.heap1ist-1/ + sel:.heap1ist-sel:.currentSiRe/ sel:.currentSiRe + sel:.currentSiRe 5 1 sel:.heap1ist.pop() sel:.percDoFn(1) return ret2al

'o $inish our discussion o$ binary hea!s, #e #ill loo, at a method to build an entire hea! $rom a list o$ ,eys= 'he $irst method you might thin, o$ may be li,e the $ollo#ing= Given a list o$ ,eys, you could easily build a hea! by inserting each ,ey one at a time= Since you are starting #ith a list o$ one item, the list is sorted and you could use binary search to $ind the right !osition to insert the ne*t ,ey at a cost o$ a!!ro*imately '-logn. o!erations= 1o#ever, remember that inserting an item in the middle o$ the list may re3uire '-n. o!erations to shi$t the rest o$ the list over to ma,e room $or the ne# ,ey= 'here$ore, to insert n ,eys into the hea! #ould re3uire a total o$ '-nlogn. o!erations= 1o#ever, i$ #e start #ith an entire list then #e can build the #hole hea! in '-n. o!erations= Listing Hlst0bh0buildI sho#s the code to build the entire hea!=
de: <uildOeap(sel:.alist)> i + len(alist) '' 2 sel:.currentSiRe + len(alist) sel:.heap1ist + -0/ % alist->/ Fhile (i > 0)> ?'' Sla<elBlst><h>loopC sel:.percDoFn(i)

9G2

i + i 5 1

Building a 1ea! $rom the List SE, C, B, 9, ;T Figure x sho#s the s#a!s that the <uildOeap method ma,es as it moves the nodes in an initial tree o$ HSE, C, B, 9, ;TI into their !ro!er !ositions= +lthough #e start out in the middle o$ the tree and #or, our #ay bac, to#ard the root, the percDoFn method ensures that the largest child is al#ays moved do#n the tree= Because it is a com!lete binary tree, any nodes !ast the hal$#ay !oint #ill be leaves and there$ore have no children= /otice that #hen i+1, #e are !ercolating do#n $rom the root o$ the tree, so this may re3uire multi!le s#a!s= +s you can see in the rightmost t#o subtrees o$ Figure x, $irst the E is moved out o$ the root !osition, but a$ter E is moved do#n one level in the tree, percDoFn ensures that #e chec, the ne*t set o$ children $arther do#n in the tree to ensure that it is !ushed as lo# as it can go= In this case it results in a second s#a! #ith ;= /o# that E has been moved to the lo#est level o$ the tree, no $urther s#a!!ing can be done= It is use$ul to com!are the list re!resentation o$ this series o$ s#a!s as sho#n in Figure x #ith the tree re!resentation=
i + 2 i + 1 i + 0 -0. $. !. 6. 2. / -0. $. 2. 6. !. / -0. 2. . 6. !. $/

HBuilding a 1ea! $rom the List SE, B, C, 9, ;TI H$ig0bldhea!I 'he assertion that #e can build the hea! in '-n. may seem a bit mysterious at $irst, and a !roo$ is beyond the sco!e o$ this boo,= 1o#ever, the ,ey to understanding that you can build the hea! in '-n. is to remember that the logn $actor is derived $rom the height o$ the tree= 6or most o$ the #or, in <uildOeap, the tree is shorter than logn= 5sing the $act that you can build a hea! $rom a list in '-n. time, you #ill construct a sorting algorithm that uses a hea! and sorts a list in '-nlogn.. as an e*ercise at the end o$ this cha!ter=

Binary Search Trees


9G9

e have already seen t#o di$$erent #ays to get ,ey4value !airs in a collection= Recall that these collections im!lement the map abstract data ty!e= 'he t#o im!lementations o$ a ma! +D' #e discussed #ere binary search on a list and hash tables= In this section #e #ill study binary search trees as yet another #ay to ma! $rom a ,ey to a value= In this case #e are not interested in the e*act !lacement o$ items in the tree, but #e are interested in using the binary tree structure to !rovide $or e$$icient searching=

Search Tree !perations


Be$ore #e loo, at the im!lementation, let:s revie# the inter$ace !rovided by the ma! +D'= >ou #ill notice that this inter$ace is very similar to the %ython dictionary=

Ma!-. Create a ne#, em!ty ma!= !ut-,ey,val. +dd a ne# ,ey4value !air to the ma!= I$ the ,ey is already in the ma! then re!lace the old value #ith the ne# value= get-,ey. Given a ,ey, return the value stored in the ma! or /one other#ise= del Delete the ,ey4value !air $rom the ma! using a statement o$ the $orm del ma!S,eyT= len-. Return the number o$ ,ey4value !airs stored in the ma!= in Return 'rue $or a statement o$ the $orm ,ey in ma!, i$ the given ,ey is in the ma!=

Search Tree Implementation


+ binary search tree relies on the !ro!erty that ,eys that are less than the !arent are $ound in the le$t subtree, and ,eys that are greater than the !arent are $ound in the right subtree= e #ill call this the bst property= +s #e im!lement the Ma! inter$ace as described above, the bst !ro!erty #ill guide our im!lementation= Figure 1 illustrates this !ro!erty o$ a binary search tree, sho#ing the ,eys #ithout any associated values= /otice that the !ro!erty holds $or each !arent and child= +ll o$ the ,eys in the le$t subtree are less than the ,ey in the root= +ll o$ the ,eys in the right subtree are greater than the root=

+ Sim!le Binary Search 'ree

9G;

/o# that you ,no# #hat a binary search tree is, #e #ill loo, at ho# a binary search tree is constructed= 'he search tree in Figure 1 re!resents the nodes that e*ist a$ter #e have inserted the $ollo#ing ,eys in the order sho#n0 DG,;2,E;,E<,2<,9;,D;= Since DG #as the $irst ,ey inserted into the tree, it is the root= /e*t, ;2 is less than DG, so it becomes the le$t child o$ DG= /e*t, E; is greater than DG, so it becomes the right child o$ DG= /o# #e have t#o levels o$ the tree $illed, so the ne*t ,ey is going to be the le$t or right child o$ either ;2 or E;= Since E< is greater than DG and E;, it becomes the right child o$ E;= Similarly 2< is less than DG and ;2, so it becomes the le$t child o$ ;2= 9; is also less than ;2, so it must be in the le$t subtree o$ ;2= 1o#ever, it is greater than 2<, so it becomes the right child o$ 2<= 'o im!lement the binary search tree, #e #ill use the nodes and re$erences a!!roach similar to the one #e used to im!lement the lin,ed list, and the e*!ression tree= 1o#ever, because #e must be able create and #or, #ith a binary search tree that is em!ty, our im!lementation #ill use t#o classes= 'he $irst class #e #ill call BinarySearch'ree, and the second class #e #ill call 'ree/ode= 'he BinarySearch'ree class has a re$erence to the 'ree/ode that is the root o$ the binary search tree= In most cases the e*ternal methods de$ined in the outer class sim!ly chec, to see i$ the tree is em!ty= I$ there are nodes in the tree, the re3uest is just !assed on to a !rivate method de$ined in the BinarySearch tree class that ta,es the root as a !arameter= In the case #here the tree is em!ty or #e #ant to delete the ,ey at the root o$ the tree, #e must ta,e s!ecial action= 'he code $or the BinarySearch'ree class constructor along #ith a $e# other miscellaneous $unctions is sho#n belo#=
class Pinar0Search)ree> de: 44init44(sel:)> sel:.root + 7one sel:.siRe + 0 de: length(sel:)> return sel:.siRe de: 44len44(sel:)> return sel:.siRe de: 44iter44(sel:)> return sel:.root.44iter44()

'he 'ree/ode class !rovides many hel!er $unctions that ma,e the #or, done in the BinarySearch'ree class methods much easier= 'he constructor $or a 'ree/ode, along #ith these hel!er $unctions, is sho#n in Listing Hlst0bstInitI= +s you can see in the listing many o$ these hel!er $unctions hel! to classi$y a node according to its o#n !osition as a child, -le$t or right. and the ,ind o$ children the node has= One big di$$erence bet#een the 'ree/ode class and the Binary'ree class $rom Section Hsec0bintreeI is that #e #ill e*!licitly ,ee! trac, o$ the !arent as an attribute o$ each node= >ou #ill see #hy this is im!ortant #hen #e discuss the im!lementation $or the del o!erator= +nother interesting as!ect o$ the im!lementation o$ 'ree/ode in Listing Hlst0bstInitI is that #e use %ython:s o!tional !arameters= O!tional !arameters ma,e it easy $or us to create a 'ree/ode under several di$$erent circumstances= Sometimes #e #ill #ant to construct a ne# 'ree/ode that already has both a !arent and a child= ith an e*isting !arent and child, #e

9G<

can !ass !arent and child as !arameters= +t other times #e #ill just create a 'ree/ode #ith the ,ey value !air, and #e #ill not !ass any !arameters $or !arent or child= In this case, the de$ault values o$ the o!tional !arameters are used=
class )ree7ode> de: 44init44(sel:.=e0.2al.le:t+7one.right+7one. parent+7one)> sel:.=e0 + =e0 sel:.pa0load + 2al sel:.le:tJhild + le:t sel:.rightJhild + right sel:.parent + parent de: has1e:tJhild(sel:)> return sel:.le:tJhild de: hasLightJhild(sel:)> return sel:.rightJhild de: is1e:tJhild(sel:)> return sel:.parent and sel:.parent.le:tJhild ++ sel: de: isLightJhild(sel:)> return sel:.parent and sel:.parent.rightJhild ++ sel: de: isLoot(sel:)> return not sel:.parent de: is1ea:(sel:)> return not (sel:.rightJhild or sel:.le:tJhild) de: hasAn0Jhildren(sel:)> return sel:.rightJhild or sel:.le:tJhild de: hasPothJhildren(sel:)> return sel:.rightJhild and sel:.le:tJhild de: replace7odeData(sel:.=e0.2alue.lc.rc)> sel:.=e0 + =e0 sel:.pa0load + 2alue sel:.le:tJhild + lc sel:.rightJhild + rc i: sel:.has1e:tJhild()> sel:.le:tJhild.parent + sel: i: sel:.hasLightJhild()> sel:.rightJhild.parent + sel:

/o# that #e have the BinarySearch'ree shell and the 'ree/ode it is time to #rite the !ut method that #ill allo# us to build our binary search tree= 'he !ut method is a method o$ the BinarySearch'ree class= 'his method #ill chec, to see i$ the tree already has a root= I$ there is not a root then !ut #ill create a ne# 'ree/ode and install it as the root o$ the tree= I$ a root node is already in !lace then !ut calls the !rivate, recursive, hel!er $unction O!ut to search the tree according to the $ollo#ing algorithm0

Starting at the root o$ the tree, search the binary tree com!aring the ne# ,ey to the ,ey in the current node= I$ the ne# ,ey is less than the current node, search the le$t subtree= I$ the ne# ,ey is greater than the current node, search the right subtree=

9GB

hen there is no le$t -or right. child to search, #e have $ound the !osition in the tree #here the ne# node should be installed= 'o add a node to the tree, create a ne# 'ree/ode object and insert the object at the !oint discovered in the !revious ste!=

'he listing belo# sho#s the %ython code $or inserting a ne# node in the tree= 'he O!ut $unction is #ritten recursively $ollo#ing the ste!s outlined above= /otice that #hen a ne# child is inserted into the tree, the current/ode is !assed to the ne# tree as the !arent= One im!ortant !roblem #ith our im!lementation o$ insert is that du!licate ,eys are not handled !ro!erly= +s our tree is im!lemented a du!licate ,ey #ill create a ne# node #ith the same ,ey value in the right subtree o$ the node having the original ,ey= 'he result o$ this is that the node #ith the ne# ,ey #ill never be $ound during a search= + better #ay to handle the insertion o$ a du!licate ,ey is $or the value associated #ith the ne# ,ey to re!lace the old value= e leave $i*ing this bug as an e*ercise $or you=
de: put(sel:.=e0.2al)> i: sel:.root> sel:.4put(=e0.2al.sel:.root) else> sel:.root + )ree7ode(=e0.2al) sel:.siRe + sel:.siRe % 1 de: 4put(sel:.=e0.2al.current7ode)> i: =e0 , current7ode.=e0> i: current7ode.has1e:tJhild()> sel:.4put(=e0.2al.current7ode.le:tJhild) else> current7ode.le:tJhild + )ree7ode(=e0.2al.parent+current7ode) else> i: current7ode.hasLightJhild()> sel:.4put(=e0.2al.current7ode.rightJhild) else> current7ode.rightJhild + )ree7ode(=e0.2al.parent+current7ode)

ith the !ut method de$ined, #e can easily overload the ST o!erator $or assignment by having the OOsetitemOO method call the !ut method= 'his allo#s us to #rite %ython statements li,e myfi!'reeSX%lymouthXT P BB<<C, just li,e a %ython dictionary=
de: 44setitem44(sel:.=.2)> sel:.put(=.2)

Figure 2 illustrates the !rocess $or inserting a ne# node into a binary search tree= 'he lightly shaded nodes indicate the nodes that #ere visited during the insertion !rocess=

9GC

Inserting a /ode #ith &ey P 2E Once the tree is constructed, the ne*t tas, is to im!lement the retrieval o$ a value $or a given ,ey= 'he get method is even easier than the !ut method because it sim!ly searches the tree recursively until it gets to a non4matching lea$ node or $inds a matching ,ey= hen a matching ,ey is $ound, the value stored in the !ayload o$ the node is returned= 'he $ollo#ing listing sho#s the code $or get, Oget and OOgetitemOO= 'he search code in the Oget method uses the same logic $or choosing the le$t or right child as the O!ut method= /otice that the Oget method returns a 'ree/ode to get, this allo#s Oget to be used as a $le*ible hel!er method $or other BinarySearch'ree methods that may need to ma,e use o$ other data $rom the 'ree/ode besides the !ayload= By im!lementing the OOgetitemOO method #e can #rite a %ython statement that loo,s just li,e #e are accessing a dictionary, #hen in $act #e are using a binary search tree, $or e*am!le 8 P myfi!'reeSX6argoXTI= +s you can see, all the ZZOOgetitemOO method does is call get=
de: get(sel:.=e0)> i: sel:.root> res + sel:.4get(=e0.sel:.root) i: res> return res.pa0load else> return 7one else> return 7one de: 4get(sel:.=e0.current7ode)> i: not current7ode> return 7one eli: current7ode.=e0 ++ =e0> return current7ode eli: =e0 , current7ode.=e0> return sel:.4get(=e0.current7ode.le:tJhild) else> return sel:.4get(=e0.current7ode.rightJhild)

9GD

de: 44getitem44(sel:.=e0)> return sel:.get(=e0)

5sing get, #e can im!lement the in o!eration by #riting a OOcontainsOO method $or the BinarySearch'ree= 'he OOcontainsOO method #ill sim!ly call get and return 'rue i$ get returns a value, or 6alse i$ it returns /one= 'he code $or OOcontainsOO is sho#n belo#=
de: 44contains44(sel:.=e0)> i: sel:.4get(=e0.sel:.root)> return )rue else> return *alse

Recall that OOcontainsOO overloads the in o!erator and allo#s us to #rite statements such as0
i: 67orth:ield6 in m0Yip)ree> print("oom 0a 0a")

6inally, #e turn our attention to the most challenging method in the binary search tree, the deletion o$ a ,ey= 'he $irst tas, is to $ind the node to delete by searching the tree= I$ the tree has more than one node #e search using the Oget method to $ind the 'ree/ode that needs to be removed= I$ the tree only has a single node, that means #e are removing the root o$ the tree, but #e still must chec, to ma,e sure the ,ey o$ the root matches the ,ey that is to be deleted= In either case i$ the ,ey is not $ound the del o!erator raises an error=
de: delete(sel:.=e0)> i: sel:.siRe > 1> node)oLemo2e + sel:.4get(=e0.sel:.root) i: node)oLemo2e> sel:.remo2e(node)oLemo2e) sel:.siRe + sel:.siRe51 else> raise Ue0@rror(6@rror. =e0 not in tree6) eli: sel:.siRe ++ 1 and sel:.root.=e0 ++ =e0> sel:.root + 7one sel:.siRe + sel:.siRe 5 1 else> raise Ue0@rror(6@rror. =e0 not in tree6) de: 44delitem44(sel:.=e0)> sel:.delete(=e0)

Once #e:ve $ound the node containing the ,ey #e #ant to delete, there are three cases that #e must consider0 2= 'he node to be deleted has no children -see Figure 3.= 9= 'he node to be deleted has only one child -see Figure 4.= ;= 'he node to be deleted has t#o children -see Figure 5.= 'he $irst case is straight$or#ard= I$ the current node has no children all #e need to do is delete the node and remove the re$erence to this node in the !arent= 'he code $or this case is sho#n in here=
i: current7ode.is1ea:()> i: current7ode ++ current7ode.parent.le:tJhild>

9GF

current7ode.parent.le:tJhild + 7one else> current7ode.parent.rightJhild + 7one

Deleting /ode 2C, a /ode #ithout Children 'he second case is only slightly more com!licated= I$ a node has only a single child, then #e can sim!ly !romote the child to ta,e the !lace o$ its !arent= 'he code $or this case is sho#n in the ne*t listing= +s you loo, at this code you #ill see that there are si* cases to consider= Since the cases are symmetric #ith res!ect to either having a le$t or right child #e #ill just discuss the case #here the current node has a le$t child= 'he decision !roceeds as $ollo#s0 2= I$ the current node is a le$t child then #e only need to u!date the !arent re$erence o$ the le$t child to !oint to the !arent o$ the current node, and then u!date the le$t child re$erence o$ the !arent to !oint to the current node:s le$t child= 9= I$ the current node is a right child then #e only need to u!date the !arent re$erence o$ the right child to !oint to the !arent o$ the current node, and then u!date the right child re$erence o$ the !arent to !oint to the current node:s right child= ;= I$ the current node has no !arent, it must be the root= In this case #e #ill just re!lace the ,ey, !ayload, le$tChild, and rightChild data by calling the re!lace/odeData method on the root=
else> ? this node has one child i: current7ode.has1e:tJhild()> i: current7ode.is1e:tJhild()> current7ode.le:tJhild.parent + current7ode.parent current7ode.parent.le:tJhild + current7ode.le:tJhild eli: current7ode.isLightJhild()> current7ode.le:tJhild.parent + current7ode.parent current7ode.parent.rightJhild + current7ode.le:tJhild else> current7ode.replace7odeData(current7ode.le:tJhild.=e0. current7ode.le:tJhild.pa0load. current7ode.le:tJhild.le:tJhild.

9GE

current7ode.le:tJhild.rightJhild) else> i: current7ode.is1e:tJhild()> current7ode.rightJhild.parent + current7ode.parent current7ode.parent.le:tJhild + current7ode.rightJhild eli: current7ode.isLightJhild()> current7ode.rightJhild.parent + current7ode.parent current7ode.parent.rightJhild + current7ode.rightJhild else> current7ode.replace7odeData(current7ode.rightJhild.=e0. current7ode.rightJhild.pa0load. current7ode.rightJhild.le:tJhild. current7ode.rightJhild.rightJhild)

Deleting /ode 9B, a /ode 'hat 1as a Single Child 'he third case is the most di$$icult case to handle= I$ a node has t#o children, then it is unli,ely that #e can sim!ly !romote one o$ them to ta,e the node:s !lace= e can, ho#ever, search the tree $or a node that can be used to re!lace the one scheduled $or deletion= hat #e need is a node that #ill !reserve the binary search tree relationshi!s $or both o$ the e*isting le$t and right subtrees= 'he node that #ill do this is the node that has the ne*t4largest ,ey in the tree= e call this node the successor, and #e #ill loo, at a #ay to $ind the successor shortly= 'he successor is guaranteed to have no more than one child, so #e ,no# ho# to remove it using the t#o cases $or deletion that #e have already im!lemented= Once the successor has been removed, #e sim!ly !ut it in the tree in !lace o$ the node to be deleted=

92G

Deleting /ode B, a /ode #ith '#o Children 'he code to handle the third case is sho#n in the ne*t listing= /otice that #e ma,e use o$ the hel!er methods $indSuccessor and $indMin to $ind the successor= 'o remove the successor, #e ma,e use o$ the method s!liceOut= 'he reason #e use s!liceOut is that it goes directly to the node #e #ant to s!lice out and ma,es the right changes= e could call delete recursively, but then #e #ould #aste time re4searching $or the ,ey node=
eli: current7ode.hasPothJhildren()> ?interior succ + current7ode.:indSuccessor() succ.spliceKut() current7ode.=e0 + succ.=e0 current7ode.pa0load + succ.pa0load

'he code to $ind the successor is sho#n belo# and as you can see is a method o$ the 'ree/ode class= 'his code ma,es use o$ the same !ro!erties o$ binary search trees that cause an inorder traversal to !rint out the nodes in the tree $rom smallest to largest= 'here are three cases to consider #hen loo,ing $or the successor0 2= I$ the node has a right child, then the successor is the smallest ,ey in the right subtree= 9= I$ the node has no right child and is the le$t child o$ its !arent, then the !arent is the successor= ;= I$ the node is the right child o$ its !arent, and itsel$ has no right child, then the successor to this node is the successor o$ its !arent, e*cluding this node=

922

'he $irst condition is the only one that matters $or us #hen deleting a node $rom a binary search tree= 1o#ever, the $indSuccessor method has other uses that #e #ill e*!lore in the e*ercises at the end o$ this cha!ter= 'he $indMin method is called to $ind the minimum ,ey in a subtree= >ou should convince yoursel$ that the minimum valued ,ey in any binary search tree is the le$tmost child o$ the tree= 'here$ore the $indMin method sim!ly $ollo#s the le$tChild re$erences in each node o$ the subtree until it reaches a node that does not have a le$t child=
de: :indSuccessor(sel:)> succ + 7one i: sel:.hasLightJhild()> succ + sel:.rightJhild.:indGin() else> i: sel:.parent> i: sel:.is1e:tJhild()> succ + sel:.parent else> sel:.parent.rightJhild + 7one succ + sel:.parent.:indSuccessor() sel:.parent.rightJhild + sel: return succ de: :indGin(sel:)> current + sel: Fhile current.has1e:tJhild()> current + current.le:tJhild return current de: spliceKut(sel:)> i: sel:.is1ea:()> i: sel:.is1e:tJhild()> sel:.parent.le:tJhild + 7one else> sel:.parent.rightJhild + 7one eli: sel:.hasAn0Jhildren()> i: sel:.has1e:tJhild()> i: sel:.is1e:tJhild()> sel:.parent.le:tJhild + sel:.le:tJhild else> sel:.parent.rightJhild + sel:.le:tJhild sel:.le:tJhild.parent + sel:.parent else> i: sel:.is1e:tJhild()> sel:.parent.le:tJhild + sel:.rightJhild else> sel:.parent.rightJhild + sel:.rightJhild sel:.rightJhild.parent + sel:.parent

'he com!lete listing $or delete is given here $or additional clarity=
de: remo2e(sel:.current7ode)> i: current7ode.is1ea:()> ?lea: i: current7ode ++ current7ode.parent.le:tJhild> current7ode.parent.le:tJhild + 7one else> current7ode.parent.rightJhild + 7one eli: current7ode.hasPothJhildren()> ?interior succ + current7ode.:indSuccessor()

929

succ.spliceKut() current7ode.=e0 + succ.=e0 current7ode.pa0load + succ.pa0load else> ? this node has one child i: current7ode.has1e:tJhild()> i: current7ode.is1e:tJhild()> current7ode.le:tJhild.parent + current7ode.parent current7ode.parent.le:tJhild + current7ode.le:tJhild eli: current7ode.isLightJhild()> current7ode.le:tJhild.parent + current7ode.parent current7ode.parent.rightJhild + current7ode.le:tJhild else> current7ode.replace7odeData(current7ode.le:tJhild.=e0. current7ode.le:tJhild.pa0load. current7ode.le:tJhild.le:tJhild. current7ode.le:tJhild.rightJhild) else> i: current7ode.is1e:tJhild()> current7ode.rightJhild.parent + current7ode.parent current7ode.parent.le:tJhild + current7ode.rightJhild eli: current7ode.isLightJhild()> current7ode.rightJhild.parent + current7ode.parent current7ode.parent.rightJhild + current7ode.rightJhild else> current7ode.replace7odeData(current7ode.rightJhild.=e0. current7ode.rightJhild.pa0load. current7ode.rightJhild.le:tJhild. current7ode.rightJhild.rightJhild)

e need to loo, at one last inter$ace method $or the binary search tree= Su!!ose that #e #ould li,e to sim!ly iterate over all the ,eys in the tree in order= 'his is de$initely something #e have done #ith dictionaries, so #hy not trees" >ou already ,no# ho# to traverse a binary tree in order, using the inorder traversal algorithm= 1o#ever, #riting an iterator re3uires a bit more #or,, since an iterator should return only one node each time the iterator is called= %ython !rovides us #ith a very !o#er$ul $unction to use #hen creating an iterator= 'he $unction is called yield= yield is similar to return in that it returns a value to the caller= 1o#ever, yield also ta,es the additional ste! o$ $ree8ing the state o$ the $unction so that the ne*t time the $unction is called it continues e*ecuting $rom the e*act !oint it le$t o$$ earlier= 6unctions that create objects that can be iterated are called generator $unctions= 'he code $or an inorder iterator o$ a binary tree is sho#n in the ne*t listing= Loo, at this code care$ullyU at $irst glance you might thin, that the code is not recursive= 1o#ever, remember that OOiterOO overrides the $or * in o!eration $or iteration, so it really is recursiveR Because it is recursive over 'ree/ode instances the OOiterOO method is de$ined in the 'ree/ode class=
de: 44iter44(sel:)> i: sel:> i: sel:.has1e:tJhild()> :or elem in sel:.le:tJhi1d> 0ield elem 0ield sel:.=e0 i: sel:.hasLightJhild()> :or elem in sel:.rightJhild> 0ield elem

92;

+t this !oint you may #ant to do#nload the entire $ile containing the $ull version o$ the BinarySearch'ree and 'ree/ode classes= >ou can $ind this $ile -bst=!y. on the su!!ort #eb site $or this boo, at ###=!ython#or,s=org=

Search Tree Analysis


ith the im!lementation o$ a binary search tree no# com!lete, #e #ill do a 3uic, analysis o$ the methods #e have im!lemented= Let:s $irst loo, at the !ut method= 'he limiting $actor on its !er$ormance is the height o$ the binary tree= Recall $rom the vocabulary section that the height o$ a tree is the number o$ edges bet#een the root and the dee!est lea$ node= 'he height is the limiting $actor because #hen #e are searching $or the a!!ro!riate !lace to insert a node into the tree, #e #ill need to do at most one com!arison at each level o$ the tree= hat is the height o$ a binary tree li,ely to be" 'he ans#er to this 3uestion de!ends on ho# the ,eys are added to the tree= I$ the ,eys are added in a random order, the height o$ the tree is going to be around log9n #here n is the number o$ nodes in the tree= 'his is because i$ the ,eys are randomly distributed, about hal$ o$ them #ill be less than the root and hal$ #ill be greater than the root= Remember that in a binary tree there is one node at the root, t#o nodes in the ne*t level, and $our at the ne*t= 'he number o$ nodes at any !articular level is 9d #here d is the de!th o$ the level= 'he total number o$ nodes in a !er$ectly balanced binary tree is 9hK2[2, #here h re!resents the height o$ the tree= + !er$ectly balanced tree has the same number o$ nodes in the le$t subtree as the right subtree= In a balanced binary tree, the #orst4case !er$ormance o$ !ut is '-log9n., #here n is the number o$ nodes in the tree= /otice that this is the inverse relationshi! to the calculation in the !revious !aragra!h= So log9n gives us the height o$ the tree, and re!resents the ma*imum number o$ com!arisons that !ut #ill need to do as it searches $or the !ro!er !lace to insert a ne# node= 5n$ortunately it is !ossible to construct a search tree that has height n sim!ly by inserting the ,eys in sorted orderR +n e*am!le o$ such a tree is sho#n in Figure 6= In this case the !er$ormance o$ the !ut method is '-n.=

92<

+ s,e#ed binary search tree #ould give !oor !er$ormance /o# that you understand that the !er$ormance o$ the !ut method is limited by the height o$ the tree, you can !robably guess that other methods, get, in, and del, are limited as #ell= Since get searches the tree to $ind the ,ey, in the #orst case the tree is searched all the #ay to the bottom and no ,ey is $ound= +t $irst glance del might seem more com!licated, since it may need to search $or the successor be$ore the deletion o!eration can com!lete= But remember that the #orst4case scenario to $ind the successor is also just the height o$ the tree #hich means that you #ould sim!ly double the #or,= Since doubling is a constant $actor it does not change #orst case analysis o$ '-n. $or an unbalanced tree=

Balanced Binary Search Trees


In the !revious section #e loo,ed at building a binary search tree= +s #e learned, the !er$ormance o$ the binary search tree can degrade to '-n. $or o!erations li,e get and put #hen the tree becomes unbalanced= In this section #e #ill loo, at a s!ecial ,ind o$ binary search tree that automatically ma,es sure that the tree remains balanced at all times= 'his tree is called an A9/ tree and is named $or its inventors0 G=M= +delson47els,ii and )=M= Landis= +n +7L tree im!lements the Ma! abstract data ty!e just li,e a regular binary search tree, the only di$$erence is in ho# the tree !er$orms= 'o im!lement our +7L tree #e need to ,ee! trac, o$ a balance %actor $or each node in the tree= e do this by loo,ing at the heights o$ the le$t and right subtrees $or each node= More $ormally, #e de$ine the balance $actor $or a node as the di$$erence bet#een the height o$ the le$t subtree and the height o$ the right subtree=

balanceFactorPheight-le(tSubTree.[height-rightSubTree.
5sing the de$inition $or balance $actor given above #e say that a subtree is le$t4heavy i$ the balance $actor is greater than 8ero= I$ the balance $actor is less than 8ero then the subtree is right heavy= I$ the balance $actor is 8ero then the tree is !er$ectly in balance= 6or !ur!oses o$ im!lementing an +7L tree, and gaining the bene$it o$ having a balanced tree #e #ill de$ine a tree to be in balance i$ the balance $actor is 42, G, or 2= Once the balance $actor o$ a node in a 92B

tree is outside this range #e #ill need to have a !rocedure to bring the tree bac, into balance= 6igure H$ig0unbalI sho#s an e*am!le o$ an unbalanced, right4heavy tree and the balance $actors o$ each node=

H+n 5nbalanced Right41eavy 'ree #ith Balance 6actorsI H$ig0unbalI

A9/ Tree Per%ormance


Hsec0avl4tree4!er$ormanceI Be$ore #e !roceed any $urther lets loo, at the result o$ en$orcing this ne# balance $actor re3uirement= Our claim is that by ensuring that a tree al#ays has a balance $actor o$ 42, G, or 2 #e can get better Big4O !er$ormance o$ ,ey o!erations= Let us start by thin,ing about ho# this balance condition changes the #orst4case tree= 'here are t#o !ossibilities to consider, a le$t4heavy tree and a right heavy tree= I$ #e consider trees o$ heights G, 2, 9, and ;, 6igure H$ig0#orst+7LI illustrates the most unbalanced le$t4heavy tree !ossible under the ne# rules=

92C

H or st4Case Le$t41eavy +7L 'reesI H$ig0#orst+7LI Loo,ing at the total number o$ nodes in the tree #e see that $or a tree o$ height G there is 2 node, $or a tree o$ height 2 there is 2K2P9 nodes, $or a tree o$ height 9 there are

2K2K9P< and $or a tree o$ height ; there are 2K9K<PD= More generally the !attern #e see $or the number o$ nodes in a tree o$ height h -3h. is0 3hP2K3h[2K3h[9
'his recurrence may loo, $amiliar to you because it is very similar to the 6ibonacci se3uence= e can use this $act to derive a $ormula $or the height o$ an +7L tree given the number o$ nodes in the tree= Recall that $or the 6ibonacci se3uence the ith 6ibonacci number is given by0

FGPGF2P2FiPFi[2KFi[9 $or all ig9


+n im!ortant mathematical result is that as the numbers o$ the 6ibonacci se3uence get larger and larger the ratio o$ FiMFi[2 becomes closer and closer to a!!ro*imating the golden ratio

h #hich is de$ined as hP2KBi9= >ou can consult a math te*t i$ you #ant to see a derivation o$ the !revious e3uation= e #ill sim!ly use this e3uation to a!!ro*imate Fi as FiPhiMBi= I$ #e ma,e use o$ this a!!ro*imation #e can re#rite the e3uation $or 3h as0 3hPFhK9[2,hg2
By re!lacing the 6ibonacci re$erence #ith its golden ratio a!!ro*imation #e get0

3hPhhK9Bi[2
I$ #e rearrange the terms, and ta,e the base 9 log o$ both sides and then solve $or h #e get the $ollo#ing derivation0 == math0

92D

SlogB74h%1C + (O%2)SlogBSNhiC 5 S:racB1CB2C SlogB!C SS h + S:racBSlogB74h%1C 5 2 SlogBSNhiC % S:racB1CB2C SlogB!CCBSlogBSNhiCC SS h + 1.44 SlogB74hC

'his derivation sho#s us that at any time the height o$ our +7L tree is e3ual to a constant-2=<<. times the log o$ the height o$ the tree= 'his is great ne#s $or searching our +7L tree because it limits the search to '-log3.=

A9/ Tree Implementation


Hsec0avl4tree4im!lI /o# that #e have demonstrated that ,ee!ing an +7L tree in balance is going to be a big !er$ormance im!rovement, let us loo, at ho# #e #ill augment the !rocedure to insert a ne# ,ey into the tree= Since all ne# ,eys are inserted into the tree as lea$ nodes and #e ,no# that the balance $actor $or a ne# lea$ is 8ero, there are no ne# re3uirements $or the node that #as just inserted= But once the ne# lea$ is added #e must u!date the balance $actor o$ its !arent= 1o# this ne# lea$ a$$ects the !arent:s balance $actor de!ends on #hether the lea$ node is a le$t child or a right child= I$ the ne# node is a right child the balance $actor o$ the !arent #ill be reduced by one= I$ the ne# node is a le$t child then the balance $actor o$ the !arent #ill be increased by one= 'his relation can be a!!lied recursively to the grand!arent o$ the ne# node, and !ossibly to every ancestor all the #ay u! to the root o$ the tree= Since this is a recursive !rocedure let us e*amine the t#o base cases $or u!dating balance $actors0

'he recursive call has reached the root o$ the tree= 'he balance $actor o$ the !arent has been adjusted to 8ero= >ou should convince yoursel$ that once a subtree has a balance $actor o$ 8ero, then the balance o$ its ancestor nodes does not change=

e #ill im!lement the +7L tree as a subclass o$ Pinar0Search)ree= 'o begin, #e #ill override the HO!utI method and #rite a ne# updatePalance hel!er method= 'hese methods are sho#n in Listing Hlst0u!dbalI= >ou #ill notice that the de$inition $or HO!utI is e*actly the same as in Listing Hlst0bst!utI e*ce!t $or the additions o$ the calls to updatePalance on lines Hbal!ut0u!2I and Hbal!ut0u!9I=
-:loat+ht<.caption+Ipdating Palance *actors.la<el+lst>upd<al/ de: 4put(sel:.=e0.2al.current7ode)> i: =e0 , current7ode.=e0> i: current7ode.has1e:tJhild()> sel:.4put(=e0.2al.current7ode.le:tJhild) else> current7ode.le:tJhild + )ree7ode(=e0.2al. parent+current7ode) sel:.updatePalance(current7ode.le:tJhild) ?'' Sla<elB<alput>up1C else> i: current7ode.hasLightJhild()> sel:.4put(=e0.2al.current7ode.rightJhild) else> current7ode.rightJhild + )ree7ode(=e0.2al. parent+current7ode) sel:.updatePalance(current7ode.rightJhild) ?'' Sla<elB<alput>up2C

92F

de: updatePalance(sel:.node)> i: node.<alance*actor > 1 or node.<alance*actor , 51> Sla<elBupd<al>chec=C sel:.re<alance(node) ?'' Sla<elBupd<al>re<alC return i: node.parent Q+ 7one> i: node.is1e:tJhild()> node.parent.<alance*actor %+ 1 eli: node.isLightJhild()> node.parent.<alance*actor 5+ 1 i: node.parent.<alance*actor Q+ 0> sel:.updatePalance(node.parent)

?''

'he ne# updatePalance method is #here most o$ the #or, is done= 'his im!lements the recursive !rocedure #e just described= 'he updatePalance method $irst chec,s to see i$ the current node is out o$ balance enough to re3uire rebalancing -line Hu!dbal0chec,I.= I$ that is the case then the rebalancing is done and no $urther u!dating to !arents is re3uired= I$ the current node does not re3uire rebalancing then the balance $actor o$ the !arent is adjusted= I$ the balance $actor o$ the !arent is non48ero then the algorithm continues to #or, its #ay u! the tree to#ard the root by recursively calling updatePalance on the !arent= hen a rebalancing o$ the tree is necessary, ho# do #e do it" )$$icient rebalancing is the ,ey to ma,ing the +7L 'ree #or, #ell #ithout sacri$icing !er$ormance= In order to bring an +7L 'ree bac, into balance #e #ill !er$orm one or more rotations on the tree= 'o understand #hat a rotation is let us loo, at a very sim!le e*am!le= Consider the tree in the le$t hal$ o$ 6igure H$ig0unbalsim!I= 'his tree is out o$ balance #ith a balance $actor o$ 49= 'o bring this tree into balance #e #ill use a le$t rotation around the subtree rooted at node +=

H'rans$orming an 5nbalanced 'ree into a Balanced 'ree 5sing a Le$t RotationI H$ig0unbalsim!I 'o !er$orm a le$t rotation #e essentially do the $ollo#ing0

%romote the right child -B. to be the root o$ the subtree= Move the old root -+. to be the le$t child o$ the ne# root= I$ ne# root -B. already had a le$t child then ma,e it the right child o$ the ne# le$t child -+.= /ote0 Since the ne# root -B. #as the right child o$ + the right child o$ + is guaranteed to be em!ty at this !oint= 'his allo#s us to add a ne# node as the right child #ithout any $urther consideration=

hile this !rocedure is $airly easy in conce!t, the details o$ the code are a bit tric,y since #e need to move things around in just the right order so that all !ro!erties o$ a Binary Search

92E

'ree are !reserved= 6urthermore #e need to ma,e sure to u!date all o$ the !arent !ointers a!!ro!riately= Lets loo, at a slightly more com!licated tree to illustrate the right rotation= 'he le$t side o$ 6igure H$ig0rightrot2I sho#s a tree that is le$t4heavy and #ith a balance $actor o$ 9 at the root= 'o !er$orm a right rotation #e essentially do the $ollo#ing0

%romote the le$t child -C. to be the root o$ the subtree= Move the old root -). to be the right child o$ the ne# root= I$ the ne# root-C. already had a right child -D. then ma,e it the le$t child o$ the ne# right child -).= /ote0 Since the ne# root -C. #as the le$t child o$ ), the le$t child o$ ) is guaranteed to be em!ty at this !oint= 'his allo#s us to add a ne# node as the le$t child #ithout any $urther consideration=

H'rans$orming an 5nbalanced 'ree into a Balanced 'ree 5sing a Right RotationI H$ig0rightrot2I /o# that you have seen the rotations and have the basic idea o$ ho# a rotation #or,s let us loo, at the code= Listing Hlst0rotsI sho#s the code $or both the right and the le$t rotations= In line Hrotle$t0tem!I #e create a tem!orary variable to ,ee! trac, o$ the ne# root o$ the subtree= +s #e said be$ore the ne# root is the right child o$ the !revious root= /o# that a re$erence to the right child has been stored in this tem!orary variable #e re!lace the right child o$ the old root #ith the le$t child o$ the ne#= 'he ne*t ste! is to adjust the !arent !ointers o$ the t#o nodes= I$ neFLoot has a le$t child then the ne# !arent o$ the le$t child becomes the old root= 'he !arent o$ the ne# root is set to the !arent o$ the old root= I$ the old root #as the root o$ the entire tree then #e must set the root o$ the tree to !oint to this ne# root= Other#ise, i$ the old root is a le$t child then #e change the !arent o$ the le$t child to !oint to the ne# rootU other#ise #e change the !arent o$ the right child to !oint to the ne# root= -lines Hrotle$t0!2IAHrotle$t0!9I.= 6inally #e set the !arent o$ the old root to be the ne# root= 'his is a lot o$ com!licated boo,,ee!ing, so #e encourage you to trace through this $unction #hile loo,ing at 6igure H$ig0unbalsim!I= 'he rotateLight method is symmetrical to rotate1e:t so #e #ill leave it to you to study the code $or rotateLight=
-la<el+lst>rots.:loat+ht<.caption+1e:t and Light Lotations/ de: rotate1e:t(sel:.rotLoot)> neFLoot + rotLoot.rightJhild ?'' Sla<elBrotle:t>tempC rotLoot.rightJhild + neFLoot.le:tJhild i: neFLoot.le:tJhild Q+ 7one> neFLoot.le:tJhild.parent + rotLoot

99G

neFLoot.parent + rotLoot.parent i: rotLoot.isLoot()> sel:.root + neFLoot else> i: rotLoot.is1e:tJhild()> ?'' Sla<elBrotle:t>p1C rotLoot.parent.le:tJhild + neFLoot else> rotLoot.parent.rightJhild + neFLoot ?'' Sla<elBrotle:t>p2C neFLoot.le:tJhild + rotLoot rotLoot.parent + neFLoot rotLoot.<alance*actor + rotLoot.<alance*actor % 1 S ?'' Sla<elBrotle:t><:1C 5 min(neFLoot.<alance*actor. 0) neFLoot.<alance*actor + neFLoot.<alance*actor % 1 S % ma3(rotLoot.<alance*actor. 0) ?'' Sla<elBrotle:t><:2C

6inally, lines Hrotle$t0b$2IAHrotle$t0b$9I re3uire some e*!lanation= In these t#o lines #e u!date the balance $actors o$ the old and the ne# root= Since all the other moves are moving entire subtrees around the balance $actors o$ all other nodes are una$$ected by the rotation= But ho# can #e u!date the balance $actors #ithout com!letely recalculating the heights o$ the ne# subtrees" 'he $ollo#ing derivation should convince you that these lines are correct=

H+ Le$t RotationI H$ig0b$deriveI 6igure H$ig0b$deriveI sho#s a le$t rotation= B and D are the !ivotal nodes and +, C, ) are their subtrees= Let hx denote the height o$ a !articular subtree rooted at node x= By de$inition #e ,no# the $ollo#ing0

ne 4al-4.Ph5[h6old4al-4.Ph5[h1
But #e ,no# that the old height o$ D can also be given by 2K"ax-h6,h-., that is, the height o$ D is one more than the ma*imum height o$ its t#o children= Remember that hc and

h- hav not changed= So, let us substitute that in to the second e3uation, #hich gives us
0math0Z oldBal-B. P hO+ 4 -2 K ma*-hOC,hO)..Z and then subtract the t#o e3uations= 'he $ollo#ing ste!s do the subtraction and use some algebra to sim!li$y the e3uation $or ne 4al-4.=

ne 4al-4.[old4al-4.Ph5[h6[-h5[-2K"ax-h6,h-...ne 4al-4. [old4al-4.Ph5[h6[h5K-2K"ax-h6,h-..ne 4al-4.


992

[old4al-4.Ph5[h5K2K"ax-h6,h-.[h6ne 4al-4. [old4al-4.P2K"ax-h6,h-.[h6


/e*t #e #ill move old4al-4. to the right hand side o$ the e3uation and ma,e use o$ the $act that "ax-a,b.[cP"ax-a[c,b[c.=

ne 4al-4.Pold4al-4.K2K"ax-h6[h6,h-[h6.
But, h-[h6 is the same as [old4al-1.= So #e can use another identity that says

"ax-[a,[b.P["in-a,b.= So #e can $inish our derivation o$ ne 4al-4. #ith the


$ollo#ing ste!s0

ne 4al-4.Pold4al-4.K2K"ax-G,[old4al-1..ne 4al-4.Pold4al-4. K2["in-G,old4al-1..


/o# #e have all o$ the !arts in terms that #e readily ,no#= I$ #e remember that B is rotLoot and D is neFLoot then #e can see this corres!onds e*actly to the statement on line Hrotle$t0b$2I, or0
rotLoot.<alance*actor + rotLoot.<alance*actor % 1 5 min(0.neFLoot.<alance*actor)

+ similar derivation gives us the e3uation $or the u!dated node D, as #ell as the balance $actors a$ter a right rotation= e leave these as e*ercises $or you= /o# you might thin, that #e are done= e ,no# ho# to do our le$t and right rotations, and #e ,no# #hen #e should do a le$t or right rotation, but ta,e a loo, at 6igure H$ig0hardrotateI= Since node + has a balance $actor o$ 49 #e should do a le$t rotation= But, #hat ha!!ens #hen #e do the le$t rotation around +"

H+n 5nbalanced 'ree 'hat is More Di$$icult to BalanceI H$ig0hardrotateI 6igure H$ig0badrotateI sho#s us that a$ter the le$t rotation #e are no# out o$ balance the other #ay= I$ #e do a right rotation to correct the situation #e are right bac, #here #e started=

999

H+$ter a Le$t Rotation the 'ree Is Out o$ Balance in the Other DirectionI H$ig0badrotateI 'o correct this !roblem #e must use the $ollo#ing set o$ rules0

I$ a subtree needs a le$t rotation to bring it into balance, $irst chec, the balance $actor o$ the right child= I$ the right child is le$t heavy then do a right rotation on right child, $ollo#ed by the original le$t rotation= I$ a subtree needs a right rotation to bring it into balance, $irst chec, the balance $actor o$ the le$t child= I$ the le$t child is right heavy then do a le$t rotation on the le$t child, $ollo#ed by the original right rotation=

6igure H$ig0rotatelrI sho#s ho# these rules solve the dilemma #e encountered in 6igures H$ig0hardrotateI and H$ig0badrotateI= Starting #ith a right rotation around node C !uts the tree in a !osition #here the le$t rotation around + brings the entire subtree bac, into balance=

H+ Right Rotation 6ollo#ed by a Le$t RotationI H$ig0rotatelrI 'he code that im!lements these rules can be $ound in our re<alance method, #hich is sho#n in Listing Hlst0rebalanceI= Rule number 2 $rom above is im!lemented by the i: statement starting on line Hrot0lrI= Rule number 9 is im!lemented by the eli: statement starting on line Hrot0rlI=
-la<el+lst>re<alance.:loat+ht<.caption+Le<alancing Lules 9mplemented/ de: re<alance(sel:.node)> i: node.<alance*actor , 0> ?'' Sla<elBrot>lrC

99;

i: node.rightJhild.<alance*actor > 0> sel:.rotateLight(node.rightJhild) sel:.rotate1e:t(node) else> sel:.rotate1e:t(node) eli: node.<alance*actor > 0> ?'' Sla<elBrot>rlC i: node.le:tJhild.<alance*actor , 0> sel:.rotate1e:t(node.le:tJhild) sel:.rotateLight(node) else> sel:.rotateLight(node)

'he discussion 3uestions !rovide you the o!!ortunity to rebalance a tree that re3uires a le$t rotation $ollo#ed by a right= In addition the discussion 3uestions !rovide you #ith the o!!ortunity to rebalance some trees that are a little more com!le* than the tree in 6igure H$ig0rotatelrI= By ,ee!ing the tree in balance at all times, #e can ensure that the get method #ill run in order '-log9-n.. time= But the 3uestion is at #hat cost to our put method" Let us brea, this do#n into the o!erations !er$ormed by put= Since a ne# node is inserted as a lea$, u!dating the balance $actors o$ all the !arents #ill re3uire a ma*imum o$ log9-n. o!erations, one $or each level o$ the tree= I$ a subtree is $ound to be out o$ balance a ma*imum o$ t#o rotations are re3uired to bring the tree bac, into balance= But, each o$ the rotations #or,s in '-2. time, so even our put o!eration remains '-log9-n..= +t this !oint #e have im!lemented a $unctional +7L4'ree, unless you need the ability to delete a node= e leave the deletion o$ the node and subse3uent u!dating and rebalancing as an e*ercise $or you=

Summary o% *ap ADT Implementations


Hsec0summary4ma!4adtI Over the !ast t#o cha!ters #e have loo,ed at several data structures that can be used to im!lement the ma! abstract data ty!e= + binary Search on a list, a hash table, a binary search tree, and a balanced binary search tree= 'o conclude this section, let:s summari8e the !er$ormance o$ each data structure $or the ,ey o!erations de$ined by the ma! +D'=

!ut get in del

'-n. '-2. '-n. '-log9n. '-log9n. '-2. '-n. '-log9n. '-log9n. '-2. '-n. '-log9n. '-n.. '-2. '-n. '-log9n.

HCom!aring the %er$ormance o$ Di$$erent Ma! Im!lementationsI Htab0ma!com!areI

99<

Summary
In this cha!ter #e have loo,ed at the tree data structure= 'he tree data structure enables us to #rite many interesting algorithms= In this cha!ter #e have loo,ed at algorithms that use trees to do the $ollo#ing0

+ binary tree $or !arsing and evaluating e*!ressions= + binary tree $or im!lementing the ma! +D'= + balanced binary tree -+7L tree. $or im!lementing the ma! +D'= + binary tree to im!lement a min hea!= + min hea! used to im!lement a !riority 3ueue=

1ey Terms
+7L tree binary hea! binary tree child M children edge
inorder

binary search tree com!lete binary tree level node


postorder

hea! order !ro!erty height lea$ node minMma* hea! !ath !riority 3ueue sibling tree

ma! !arent
preorder

root successor

rotation subtree

Discussion 2uestions
2= Dra# the tree structure resulting $rom the $ollo#ing set o$ tree $unction calls0
2. >>> r + Pinar0)ree( ) . >>> insert1e:t(r.4) 4. - . -4. -/. -//. -// !. >>> insert1e:t(r.!) 6. - . -!. -4. -/. -//. -//. -// ". >>> insertLight(r.6) #. - . -!. -4. -/. -//. -//. -6. -/. -/// $. >>> insertLight(r.") 10. - . -!. -4. -/. -//. -//. -". -/. -6. -/. -//// 11. >>> setLoot8al(r.$) 12. >>> insert1e:t(r.11) 1 . -$. -11. -!. -4. -/. -//. -//. -//. -". -/. -6. -/. -////

2<= 'race the algorithm $or creating an e*!ression tree $or the e*!ression -<F.MC[;= 2B= Consider the $ollo#ing list o$ integers0 S2,9,;,<,B,C,D,F,E,2GT= Sho# the binary search tree resulting $rom inserting the integers in the list=

99B

2C= Consider the $ollo#ing list o$ integers0 S2G,E,F,D,C,B,<,;,9,2T= Sho# the binary search tree resulting $rom inserting the integers in the list= 2D= Generate a random list o$ integers= Sho# the binary hea! tree resulting $rom inserting the integers on the list one at a time= 2F= 5sing the list $rom the !revious 3uestion, sho# the binary hea! tree resulting $rom using the list as a !arameter to the <uildOeap method= Sho# both the tree and list $orm= 2E= Dra# the binary search tree that results $rom inserting the $ollo#ing ,eys in the order given0 CF,FF,C2,FE,E<,BG,<,DC,CC, and F9= 9G= Generate a random list o$ integers= Dra# the binary search tree resulting $rom inserting the integers on the list= 92= Consider the $ollo#ing list o$ integers0 S2,9,;,<,B,C,D,F,E,2GT= Sho# the binary hea! resulting $rom inserting the integers one at a time= 99= Consider the $ollo#ing list o$ integers0 S2G,E,F,D,C,B,<,;,9,2T= Sho# the binary hea! resulting $rom inserting the integers one at a time= 9;= Consider the t#o di$$erent methods #e used $or im!lementing a binary tree= hy must #e chec, be$ore the call to preorder #hen im!lementing as a method, #hereas #e could chec, inside the call #hen im!lementing as a $unction" 9<= Sho# the $unction calls needed to build the $ollo#ing binary tree=

2= Given the $ollo#ing tree, !er$orm the a!!ro!riate rotations to bring it bac, into balance=

99C

2= 5sing the $ollo#ing as a starting !oint, derive the e3uation that gives the u!dated balance $actor $or node D=

Programming ()ercises
2= )*tend the <uildNarse)ree $unction to handle mathematical e*!ressions that do not have s!aces bet#een every character= 9= Modi$y the <uildNarse)ree and e2aluate $unctions to handle boolean statements -and, or, and not.= Remember that ?not@ is a unary o!erator, so this #ill com!licate your code some#hat= ;= 5sing the :indSuccessor method, #rite a non4recursive inorder traversal $or a binary search tree= <= Modi$y the code $or a binary search tree to ma,e it threaded= rite a non4recursive inorder traversal method $or the threaded binary search tree= + threaded binary tree maintains a re$erence $rom each node to its successor= B= Modi$y our im!lementation o$ the binary search tree so that it handles du!licate ,eys !ro!erly= 'hat is, i$ a ,ey is already in the tree then the ne# !ayload should re!lace the old rather than add another node #ith the same ,ey= C= Create a binary hea! #ith a limited hea! si8e= In other #ords, the hea! only ,ee!s trac, o$ the n most im!ortant items= I$ the hea! gro#s in si8e to more than n items the least im!ortant item is dro!!ed=

99D

D= Clean u! the printe3p $unction so that it does not include an ]e*tra: set o$ !arentheses around each number= F= 5sing the <uildOeap method, #rite a sorting $unction that can sort a list in

'-nlogn. time=
E= rite a $unction that ta,es a !arse tree $or a mathematical e*!ression and calculates the derivative o$ the e*!ression #ith res!ect to some variable= 2G= Im!lement a binary hea! as a ma* hea!= 22= 5sing the Pinar0Oeap class, im!lement a ne# class called Nriorit0Xueue= >our Nriorit0Xueue class should im!lement the constructor, !lus the enqueue and dequeue methods= 29= Im!lement the delete method $or an +7L tree=

99F

Graphs
!b"ectives

'o learn #hat a gra!h is and ho# it is used= 'o im!lement the graph abstract data ty!e using multi!le internal re!resentations= 'o see ho# gra!hs can be used to solve a #ide variety o$ !roblems

In this cha!ter #e #ill study gra!hs= Gra!hs are a more general structure than the trees #e studied in the last cha!terU in $act you can thin, o$ a tree as a s!ecial ,ind o$ gra!h= Gra!hs can be used to re!resent many interesting things about our #orld, including systems o$ roads, airline $lights $rom city to city, ho# the Internet is connected, or even the se3uence o$ classes you must ta,e to com!lete a major in com!uter science= e #ill see in this cha!ter that once #e have a good re!resentation $or a !roblem, #e can use some standard gra!h algorithms to solve #hat other#ise might seem to be a very di$$icult !roblem= hile it is relatively easy $or humans to loo, at a road ma! and understand the relationshi!s bet#een di$$erent !laces, a com!uter has no such ,no#ledge= 1o#ever, #e can also thin, o$ a road ma! as a gra!h= hen #e do so #e can have our com!uter do interesting things $or us= I$ you have ever used one o$ the Internet ma! sites, you ,no# that a com!uter can $ind the shortest, 3uic,est, or easiest !ath $rom one !lace to another= +s a student o$ com!uter science you may #onder about the courses you must ta,e in order to get a major= + gra!h is good #ay to re!resent the !rere3uisites and other interde!endencies among courses= Figure 1 sho#s another gra!h= 'his one re!resents the courses and the order in #hich they must be ta,en to com!lete a major in com!uter science at Luther College=

%rere3uisites $or a Com!uter Science Major 99E

9ocabulary and De%initions


/o# that #e have loo,ed at some e*am!les o$ gra!hs, #e #ill more $ormally de$ine a gra!h and its com!onents= e already ,no# some o$ these terms $rom our discussion o$ trees= 7erte* + verte* -also called a ?node@. is a $undamental !art o$ a gra!h= It can have a name, #hich #e #ill call the ?,ey=@ + verte* may also have additional in$ormation= e #ill call this additional in$ormation the ?!ayload=@ )dge +n edge -also called an ?arc@. is another $undamental !art o$ a gra!h= +n edge connects t#o vertices to sho# that there is a relationshi! bet#een them= )dges may be one4#ay or t#o4#ay= I$ the edges in a gra!h are all one4#ay, #e say that the gra!h is a directed graph, or a digraph= 'he class !rere3uisites gra!h sho#n above is clearly a digra!h since you must ta,e some classes be$ore others= eight )dges may be #eighted to sho# that there is a cost to go $rom one verte* to another= 6or e*am!le in a gra!h o$ roads that connect one city to another, the #eight on the edge might re!resent the distance bet#een the t#o cities= ith those de$initions in hand #e can $ormally de$ine a gra!h= + gra!h can be re!resented by 7 #here 7P-8,-.= 6or the gra!h 7, 8 is a set o$ vertices and - is a set o$ edges= )ach edge is a tu!le -*,

. #here ,*8= e can add a third com!onent to the edge tu!le to re!resent a #eight= + subgra!h s is a set o$ edges e and vertices * such that e- and *8=
Figure 2 sho#s another e*am!le o$ a sim!le #eighted digra!h= 6ormally #e can re!resent this gra!h as the set o$ si* vertices0

8PH8G,82,89,8;,8<,8BI
and the set o$ nine edges0

-PH-*G,*2,B.,-*2,*9,<.,-*9,*;,E.,-*;,*<,D.,-*<,*G,2.,-*G,*B,9., -*B,*<,F.,-*;,*B,;.,-*B,*9,2.I

9;G

+ Sim!le )*am!le o$ a Directed Gra!h 'he e*am!le gra!h in Figure 2 hel!s illustrate t#o other ,ey gra!h terms0 %ath + !ath in a gra!h is a se3uence o$ vertices that are connected by edges= 6ormally #e #ould de$ine a !ath as 2, 9,===, n such that - i, iK2.- $or all 2jijn[2= 'he un#eighted !ath length is the number o$ edges in the !ath, s!eci$ically n[2= 'he #eighted !ath length is the sum o$ the #eights o$ all the edges in the !ath= 6or e*am!le in Figure 2 the !ath $rom 8; to 82 is the se3uence o$ vertices

-8;,8<,8G,82.= 'he edges are H-*;,*<,D.,-*<,*G,2.,-*G,*2,B.I=


Cycle + cycle in a directed gra!h is a !ath that starts and ends at the same verte*= 6or e*am!le, in Figure 2 the !ath -8B,89,8;,8B. is a cycle= + gra!h #ith no cycles is called an acyclic graph= + directed gra!h #ith no cycles is called a directed acyclic graph or a DAG= e #ill see that #e can solve several im!ortant !roblems i$ the !roblem can be re!resented as a D+G=

The Graph Abstract Data Type


'he gra!h abstract data ty!e -+D'. is de$ined as $ollo#s0
Traph() creates a ne#, em!ty gra!h= add8erte3(2ert) adds an instance o$ 8erte3

to the gra!h=

9;2

add@dge(:rom8ert. to8ert)

+dds a ne#, directed edge to the gra!h that connects +dds a ne#, #eighted, directed edge to the

t#o vertices=
add@dge(:rom8ert. to8ert. Feight)

gra!h that connects t#o vertices= get8erte3(2ertUe0) $inds the verte* in the gra!h named 2ertUe0= get8ertices() returns the list o$ all vertices in the gra!h= in returns )rue $or a statement o$ the $orm 2erte3 in graph, i$ the given verte* is in the gra!h, *alse other#ise=

Beginning #ith the $ormal de$inition $or a gra!h there are several #ays #e can im!lement the gra!h +D' in %ython= e #ill see that there are trade4o$$s in using di$$erent re!resentations to im!lement the +D' described above= 'here are t#o #ell4,no#n im!lementations o$ a gra!h, the ad"acency matri) and the ad"acency list= e #ill e*!lain both o$ these o!tions, and then im!lement one as a %ython class=

An Ad%acency +atri!
One o$ the easiest #ays to im!lement a gra!h is to use a t#o4dimensional matri*= In this matri* im!lementation, each o$ the ro#s and columns re!resent a verte* in the gra!h= 'he value that is stored in the cell at the intersection o$ ro# * and column indicates i$ there is an edge $rom verte* * to verte* = hen t#o vertices are connected by an edge, #e say that they are ad"acent= Figure 3 illustrates the adjacency matri* $or the gra!h in Figure 2= + value in a cell re!resents the #eight o$ the edge $rom verte* * to verte* =

+n +djacency Matri* Re!resentation $or a Gra!h

9;9

'he advantage o$ the adjacency matri* is that it is sim!le, and $or small gra!hs it is easy to see #hich nodes are connected to other nodes= 1o#ever, notice that most o$ the cells in the matri* are em!ty= Because most o$ the cells are em!ty #e say that this matri* is ?s!arse=@ + matri* is not a very e$$icient #ay to store s!arse data= In $act, in %ython you must go out o$ your #ay to even create a matri* structure li,e the one in Figure 3= 'he adjacency matri* is a good im!lementation $or a gra!h #hen the number o$ edges is large= But #hat do #e mean by large" 1o# many edges #ould be needed to $ill the matri*" Since there is one ro# and one column $or every verte* in the gra!h, the number o$ edges re3uired to $ill the matri* is V8V9= + matri* is $ull #hen every verte* is connected to every other verte*= 'here are $e# real !roblems that a!!roach this sort o$ connectivity= 'he !roblems #e #ill loo, at in this cha!ter all involve gra!hs that are s!arsely connected=

An Ad%acency *ist
+ more s!ace4e$$icient #ay to im!lement a s!arsely connected gra!h is to use an adjacency list= In an adjacency list im!lementation #e ,ee! a master list o$ all the vertices in the Gra!h object and then each verte* object in the gra!h maintains a list o$ the other vertices that it is connected to= In our im!lementation o$ the 8erte3 class #e #ill use a dictionary rather than a list #here the dictionary ,eys are the vertices, and the values are the #eights= Figure 4 illustrates the adjacency list re!resentation $or the gra!h in Figure 2=

9;;

+n +djacency List Re!resentation o$ a Gra!h 'he advantage o$ the adjacency list im!lementation is that it allo#s us to com!actly re!resent a s!arse gra!h= 'he adjacency list also allo#s us to easily $ind all the lin,s that are directly connected to a !articular verte*=

Implementation
5sing dictionaries, it is easy to im!lement the adjacency list in %ython= In our im!lementation o$ the Gra!h abstract data ty!e #e #ill create t#o classes, Traph, #hich holds the master list o$ vertices, and 8erte3, #hich #ill re!resent each verte* in the gra!h= )ach 8erte3 uses a dictionary to ,ee! trac, o$ the vertices to #hich it is connected, and the #eight o$ each edge= 'his dictionary is called connected)o= 'he listing belo# sho#s the code $or the 8erte3 class= 'he constructor sim!ly initiali8es the id, #hich #ill ty!ically be a string, and the connected)o dictionary= 'he add7eigh<or method is used add a connection $rom this verte* to another= 'he getJonnections method returns all o$ the vertices in the adjacency list, as re!resented by the connected)o instance variable= 'he getHeight method returns the #eight o$ the edge $rom this verte* to the verte* !assed as a !arameter=

9;<

class 8erte3> de: 44init44(sel:.=e0)> sel:.id + =e0 sel:.connected)o + BC de: add7eigh<or(sel:.n<r.Feight+0)> sel:.connected)o-n<r/ + Feight de: 44str44(sel:)> return str(sel:.id) % 6 connected)o> 6 % str(-3.id :or 3 in sel:.connected)o/) de: getJonnections(sel:)> return sel:.connected)o.=e0s() de: get9d(sel:)> return sel:.id de: getHeight(sel:.n<r)> return sel:.connected)o-n<r/

'he Traph class, sho#n in the ne*t listing, contains a dictionary that ma!s verte* names to verte* objects= In Figure 4 this dictionary object is re!resented by the shaded gray bo*= Traph also !rovides methods $or adding vertices to a gra!h and connecting one verte* to another= 'he get8ertices method returns the names o$ all o$ the vertices in the gra!h= In addition, #e have im!lemented the HOOiterOOI method to ma,e it easy to iterate over all the verte* objects in a !articular gra!h= 'ogether, the t#o methods allo# you to iterate over the vertices in a gra!h by name, or by the objects themselves=
class Traph> de: 44init44(sel:)> sel:.2ert1ist + BC sel:.num8ertices + 0 de: add8erte3(sel:.=e0)> sel:.num8ertices + sel:.num8ertices % 1 neF8erte3 + 8erte3(=e0) sel:.2ert1ist-=e0/ + neF8erte3 return neF8erte3 de: get8erte3(sel:.n)> i: n in sel:.2ert1ist> return sel:.2ert1ist-n/ else> return 7one de: 44contains44(sel:.n)> return n in sel:.2ert1ist de: add@dge(sel:.:.t.cost+0)> i: : not in sel:.2ert1ist> n2 + sel:.add8erte3(:) i: t not in sel:.2ert1ist> n2 + sel:.add8erte3(t) sel:.2ert1ist-:/.add7eigh<or(sel:.2ert1ist-t/. cost) de: get8ertices(sel:)> return sel:.2ert1ist.=e0s()

9;B

de: 44iter44(sel:)> return iter(sel:.2ert1ist.2alues())

5sing the Traph and 8erte3 classes just de$ined, the $ollo#ing %ython session creates the gra!h in Figure 2= 6irst #e create si* vertices numbered G through B= 'hen #e dis!lay the verte* dictionary= /otice that $or each ,ey G through B #e have created an instance o$ a 8erte3= /e*t, #e add the edges that connect the vertices together= 6inally, a nested loo! veri$ies that each edge in the gra!h is !ro!erly stored= >ou should chec, the out!ut o$ the edge list at the end o$ this session against Figure 2=
>>> >>> ... >>> B0> 1> 2> > 4> !> >>> >>> >>> >>> >>> >>> >>> >>> >>> >>> ... ... ... ( 0 ( 0 ( 1 ( 2 ( ( ( 4 ( ! ( ! g + Traph() :or i in range(6)> g.add8erte3(i) g.2ert1ist ,adATraph.8erte3 instance at 0341e1#>. ,adATraph.8erte3 instance at 03":2<0>. ,adATraph.8erte3 instance at 03":2##>. ,adATraph.8erte3 instance at 03": !0>. ,adATraph.8erte3 instance at 03": 2#>. ,adATraph.8erte3 instance at 03": 00>C g.add@dge(0.1.!) g.add@dge(0.!.2) g.add@dge(1.2.4) g.add@dge(2. .$) g.add@dge( .4.") g.add@dge( .!. ) g.add@dge(4.0.1) g.add@dge(!.4.#) g.add@dge(!.2.1) :or 2 in g> :or F in 2.getJonnections()> print("( (s . (s )" ( (2.get9d(). F.get9d())) . . . . . . . . . ! ) 1 ) 2 ) ) 4 ) ! ) 0 ) 4 ) 2 )

Breadth ,irst Search


The Word /adder Problem
'o begin our study o$ gra!h algorithms let:s consider the $ollo#ing !u88le called a #ord ladder= 'rans$orm the #ord ?6OOL@ into the #ord ?S+G)@= In a #ord ladder !u88le you must ma,e the change occur gradually by changing one letter at a time= +t each ste! you must trans$orm one #ord into another #ord, you are not allo#ed to trans$orm a #ord into a non4#ord= 'he #ord ladder !u88le #as invented in 2FDF by Le#is Carroll, the author o$ 5lice in 9onderland= 'he $ollo#ing se3uence o$ #ords sho#s one !ossible solution to the !roblem !osed above=

9;C

*KK1 NKK1 NK11 NK1@ NA1@ SA1@ SAT@

'here are many variations o$ the #ord ladder !u88le= 6or e*am!le you might be given a !articular number o$ ste!s in #hich to accom!lish the trans$ormation, or you might need to use a !articular #ord= In this section #e are interested in $iguring out the smallest number o$ trans$ormations needed to turn the starting #ord into the ending #ord= /ot sur!risingly, since this cha!ter is on gra!hs, #e can solve this !roblem using a gra!h algorithm= 1ere is an outline o$ #here #e are going0

Re!resent the relationshi!s bet#een the #ords as a gra!h= 5se the gra!h algorithm ,no#n as breadth $irst search to $ind an e$$icient !ath $rom the starting #ord to the ending #ord=

Building the Word /adder Graph


Our $irst !roblem is to $igure out ho# to turn a large collection o$ #ords into a gra!h= hat #e #ould li,e is to have an edge $rom one #ord to another i$ the t#o #ords are only di$$erent by a single letter= I$ #e can create such a gra!h, then any !ath $rom one #ord to another is a solution to the #ord ladder !u88le= Figure 1 sho#s a small gra!h o$ some #ords that solve the 6OOL to S+G) #ord ladder !roblem= /otice that the gra!h is an undirected gra!h and that the edges are un#eighted=

+ Small

ord Ladder Gra!h

9;D

e could use several di$$erent a!!roaches to create the gra!h #e need to solve this !roblem= Let:s start #ith the assum!tion that #e have a list o$ #ords that are all the same length= +s a starting !oint, #e can create a verte* in the gra!h $or every #ord in the list= 'o $igure out ho# to connect the #ords, #e could com!are each #ord in the list #ith every other= hen #e com!are #e are loo,ing to see ho# many letters are di$$erent= I$ the t#o #ords in 3uestion are di$$erent by only one letter, #e can create an edge bet#een them in the gra!h= 6or a small set o$ #ords that a!!roach #ould #or, $ineU ho#ever let:s su!!ose #e have a list o$ B,22G #ords= Roughly s!ea,ing, com!aring one #ord to every other #ord on the list is an '-n9. algorithm= 6or B,22G #ords, n9 is more than 9C million com!arisons= e can do much better by using the $ollo#ing a!!roach= Su!!ose that #e have a huge number o$ buc,ets, each o$ them #ith a $our4letter #ord on the outside, e*ce!t that one o$ the letters in the label has been re!laced by an underscore= 6or e*am!le, consider Figure 2, #e might have a buc,et labeled ?!o!O=@ +s #e !rocess each #ord in our list #e com!are the #ord #ith each buc,et, using the ]O: as a #ildcard, so both ?!o!e@ and ?!o!s@ #ould match ?!o!O=@ )very time #e $ind a matching buc,et, #e !ut our #ord in that buc,et= Once #e have all the #ords in the a!!ro!riate buc,ets #e ,no# that all the #ords in the buc,et must be connected=

ord Buc,ets $or

ords 'hat are Di$$erent by One Letter

In %ython, #e can im!lement the scheme #e have just described by using a dictionary= 'he labels on the buc,ets #e have just described are the ,eys in our dictionary= 'he value stored $or that ,ey is a list o$ #ords= Once #e have the dictionary built #e can create the gra!h= e start our gra!h by creating a verte* $or each #ord in the gra!h= 'hen #e create edges bet#een all the vertices #e $ind $or #ords $ound under the same ,ey in the dictionary= 'he $ollo#ing listing sho#s the %ython code re3uired to build the gra!h=
:rom p0thonds.graphs import Traph de: <uildTraph(Ford*ile)> d + BC g + Traph() F:ile + open(Ford*ile.6r6) ? create <uc=ets o: Fords that di::er <0 one letter :or line in F:ile> Ford + line->51/ :or i in range(len(Ford))> <uc=et + Ford->i/ % 646 % Ford-i%1>/ i: <uc=et in d>

9;F

d-<uc=et/.append(Ford) else> d-<uc=et/ + -Ford/ ? add 2ertices and edges :or Fords in the same <uc=et :or <uc=et in d.=e0s()> :or Ford1 in d-<uc=et/> :or Ford2 in d-<uc=et/> i: Ford1 Q+ Ford2> g.add@dge(Ford1.Ford2) return g

Since this is our $irst real4#orld gra!h !roblem, you might be #ondering ho# s!arse is the gra!h" 'he list o$ $our4letter #ords #e have $or this !roblem is B,22G #ords long= I$ #e #ere to use an adjacency matri*, the matri* #ould have B,22G L B,22G P 9C,229,2GG cells= 'he gra!h constructed by the <uildTraph $unction has e*actly B;,9FC edges, so the matri* #ould have only G=9GN o$ the cells $illedR 'hat is a very s!arse matri* indeed=

Implementing Breadth ,irst Search


ith the gra!h constructed #e can no# turn our attention to the algorithm #e #ill use to $ind the shortest solution to the #ord ladder !roblem= 'he gra!h algorithm #e are going to use is called the ?breadth $irst search@ algorithm= Breadth %irst search -B,S. is one o$ the easiest algorithms $or searching a gra!h= It also serves as a !rototy!e $or several other im!ortant gra!h algorithms that #e #ill study later= Given a gra!h 7 and a starting verte* s, a breadth $irst search !roceeds by e*!loring edges in the gra!h to $ind all the vertices in 7 $or #hich there is a !ath $rom s= 'he remar,able thing about a breadth $irst search is that it $inds all the vertices that are a distance ) $rom s be$ore it $inds an+ vertices that are a distance )K2= One good #ay to visuali8e #hat the breadth $irst search algorithm does is to imagine that it is building a tree, one level o$ the tree at a time= + breadth $irst search adds all children o$ the starting verte* be$ore it begins to discover any o$ the grandchildren= 'o ,ee! trac, o$ its !rogress, B6S colors each o$ the vertices #hite, gray, or blac,= +ll the vertices are initiali8ed to #hite #hen they are constructed= + #hite verte* is an undiscovered verte*= hen a verte* is initially discovered it is colored gray, and #hen B6S has com!letely e*!lored a verte* it is colored blac,= 'his means that once a verte* is colored blac,, it has no #hite vertices adjacent to it= + gray node, on the other hand, may have some #hite vertices adjacent to it, indicating that there are still additional vertices to e*!lore= 'he breadth $irst search algorithm sho#n in the listing belo# uses the adjacency list gra!h re!resentation #e develo!ed earlier= In addition it uses a Xueue, a crucial !oint as #e #ill see, to decide #hich verte* to e*!lore ne*t= In addition the B6S algorithm uses an e*tended version o$ the 8erte3 class= 'his ne# verte* class adds three ne# instance variables0 distance, !redecessor, and color= )ach o$ these instance variables also has the a!!ro!riate getter and setter methods= 'he code $or this e*!anded 7erte* class is included in the p0thonds !ac,age, but #e #ill not sho# it to you here as there is nothing ne# to learn by seeing the additional instance variables=

9;E

B6S begins at the starting verte* s and colors start gray to sho# that it is currently being e*!lored= '#o other values, the distance and the !redecessor, are initiali8ed to G and 7one res!ectively $or the starting verte*= 6inally, start is !laced on a Xueue= 'he ne*t ste! is to begin to systematically e*!lore vertices at the $ront o$ the 3ueue= e e*!lore each ne# node at the $ront o$ the 3ueue by iterating over its adjacency list= +s each node on the adjacency list is e*amined its color is chec,ed= I$ it is #hite, the verte* is une*!lored, and $our things ha!!en0 2= 9= ;= <= 'he ne#, une*!lored verte* n<r, is colored gray= 'he !redecessor o$ n<r is set to the current node current8ert 'he distance to n<r is set to the distance to current8ert % 1 n<r is added to the end o$ a 3ueue= +dding n<r to the end o$ the 3ueue e$$ectively schedules this node $or $urther e*!loration, but not until all the other vertices on the adjacency list o$ current8ert have been e*!lored=

:rom p0thonds.graphs import Traph. 8erte3 :rom p0thonds.<asic import Xueue de: <:s(g.start)> start.setDistance(0) start.setNred(7one) 2ertXueue + Xueue() 2ertXueue.enqueue(start) Fhile (2ertXueue.siRe() > 0)> current8ert + 2ertXueue.dequeue() :or n<r in current8ert.getJonnections()> i: (n<r.getJolor() ++ 6Fhite6)> n<r.setJolor(6gra06) n<r.setDistance(current8ert.getDistance() % 1) n<r.setNred(current8ert) 2ertXueue.enqueue(n<r) current8ert.setJolor(6<lac=6)

Let:s loo, at ho# the <:s $unction #ould construct the breadth $irst tree corres!onding to the gra!h in Figure 1= Starting $rom $ool #e ta,e all nodes that are adjacent to $ool and add them to the tree= 'he adjacent nodes include !ool, $oil, $oul, and cool= )ach o$ these nodes are added to the 3ueue o$ ne# nodes to e*!and= Figure 3 sho#s the state o$ the in4!rogress tree along #ith the 3ueue a$ter this ste!=

'he 6irst Ste! in the Breadth 6irst Search

9<G

In the ne*t ste! <:s removes the ne*t node -!ool. $rom the $ront o$ the 3ueue and re!eats the !rocess $or all o$ its adjacent nodes= 1o#ever, #hen <:s e*amines the node cool, it $inds that the color o$ cool has already been changed to gray= 'his indicates that there is a shorter !ath to cool and that cool is already on the 3ueue $or $urther e*!ansion= 'he only ne# node added to the 3ueue #hile e*amining !ool is !oll= 'he ne# state o$ the tree and 3ueue is sho#n in Figure 4=

'he Second Ste! in the Breadth 6irst Search 'he ne*t verte* on the 3ueue is $oil= 'he only ne# node that $oil can add to the tree is $ail= +s <:s continues to !rocess the 3ueue, neither o$ the ne*t t#o nodes add anything ne# to the 3ueue or the tree= Figure 5 sho#s the tree and the 3ueue a$ter e*!anding all the vertices on the second level o$ the tree=

9<2

Breadth 6irst Search 'ree +$ter Com!leting One Level

9<9

6inal Breadth 6irst Search 'ree >ou should continue to #or, through the algorithm on your o#n so that you are com$ortable #ith ho# it #or,s= Figure 6 sho#s the $inal breadth $irst search tree a$ter all the vertices in Figure 3 have been e*!anded= 'he ama8ing thing about the breadth $irst search solution is that #e have not only solved the 6OOLAS+G) !roblem #e started out #ith, but #e have solved many other !roblems along the #ay= e can start at any verte* in the breadth $irst search tree and $ollo# the !redecessor arro#s bac, to the root to $ind the shortest #ord ladder $rom any #ord bac, to $ool= 'he $unction belo# sho#s ho# to $ollo# the !redecessor lin,s to !rint out the #ord ladder=
de: tra2erse(0)> 3 + 0 Fhile (3.getNred())> print(3.get9d()) 3 + 3.getNred() print(3.get9d())

9<;

tra2erse(g.get8erte3(6sage6))

Breadth ,irst Search Analysis


Be$ore #e continue #ith other gra!h algorithms let us analy8e the run time !er$ormance o$ the breadth $irst search algorithm= 'he $irst thing to observe is that the #hile loo! is e*ecuted, at most, one time $or each verte* in the gra!h V8V= >ou can see that this is true because a verte* must be #hite be$ore it can be e*amined and added to the 3ueue= 'his gives us '-8. $or the #hile loo!= 'he $or loo!, #hich is nested inside the #hile is e*ecuted at most once $or each edge in the gra!h, V-V= 'he reason is that every verte* is de3ueued at most once and #e e*amine an edge $rom node u to node * only #hen node u is de3ueued= 'his gives us '--. $or the $or loo!= combining the t#o loo!s gives us '-8K-.= O$ course doing the breadth $irst search is only !art o$ the tas,= 6ollo#ing the lin,s $rom the starting node to the goal node is the other !art o$ the tas,= 'he #orst case $or this #ould be i$ the gra!h #as a single long chain= In this case traversing through all o$ the vertices #ould be '-8.= 'he normal case is going to be some $raction o$ V8V but #e #ould still #rite '-8.= 6inally, at least $or this !roblem, there is the time re3uired to build the initial gra!h= the analysis o$ the <uildTraph $unction as an e*ercise $or you= e leave

Depth ,irst Search


The 1night<s Tour Problem
+nother classic !roblem that #e can use to illustrate a second common gra!h algorithm is called the ?,night:s tour=@ 'he ,night:s tour !u88le is !layed on a chess board #ith a single chess !iece, the ,night= 'he object o$ the !u88le is to $ind a se3uence o$ moves that allo# the ,night to visit every s3uare on the board e*actly once= One such se3uence is called a ?tour=@ 'he ,night:s tour !u88le has $ascinated chess !layers, mathematicians and com!uter scientists ali,e $or many years= 'he u!!er bound on the number o$ !ossible legal tours $or an eight4by4eight chessboard is ,no#n to be 2=;GBc2G;BU ho#ever, there are even more !ossible dead ends= Clearly this is a !roblem that re3uires some real brains, some real com!uting !o#er, or both= +lthough researchers have studied many di$$erent algorithms to solve the ,night:s tour !roblem, a gra!h search is one o$ the easiest to understand and !rogram= Once again #e #ill solve the !roblem using t#o main ste!s0 Re!resent the legal moves o$ a ,night on a chessboard as a gra!h= 5se a gra!h algorithm to $ind a !ath o$ length ro sccolu"ns[2 #here every verte* on the gra!h is visited e*actly once=

Building the 1night<s Tour Graph

9<<

'o re!resent the ,night:s tour !roblem as a gra!h #e #ill use the $ollo#ing t#o ideas0 )ach s3uare on the chessboard can be re!resented as a node in the gra!h= )ach legal move by the ,night can be re!resented as an edge in the gra!h= 6igure 2 illustrates the legal moves by a ,night and the corres!onding edges in a gra!h=

Legal Moves $or a &night on S3uare 29, and the Corres!onding Gra!h 'o build the $ull gra!h $or an n4by4n board #e can use the %ython $unction sho#n belo#= 'he =nightTraph $unction ma,es one !ass over the entire board= +t each s3uare on the board the =nightTraph $unction calls a hel!er, gen1egalGo2es, to create a list o$ legal moves $or that !osition on the board= +ll legal moves are then converted into edges in the gra!h= +nother hel!er $unction pos)o7ode9d converts a location on the board in terms o$ a ro# and a column into a linear verte* number similar to the verte* numbers sho#n in 6igure 2= $rom !ythonds=gra!hs im!ort Gra!h de$ ,nightGra!h-bdSi8e.0 ,tGra!h P Gra!h-. $or ro# in range-bdSi8e.0 $or col in range-bdSi8e.0 nodeId P !os'o/odeId-ro#,col,bdSi8e. ne#%ositions P genLegalMoves-ro#,col,bdSi8e. $or e in ne#%ositions0 nid P !os'o/odeId-eSGT,eS2T. ,tGra!h=add)dge-nodeId,nid. return ,tGra!h

9<B

'he gen1egalGo2es $unction ta,es the !osition o$ the ,night on the board and generates each o$ the eight !ossible moves= 'he legalJoord hel!er $unction ma,es sure that a !articular move that is generated is still on the board= de$ genLegalMoves-*,y,bdSi8e.0 ne#Moves P ST moveO$$sets P S-42,49.,-42,9.,-49,42.,-49,2., - 2,49.,- 2,9.,- 9,42.,- 9,2.T0 $or i in moveO$$sets0 ne#` P * K iSGT ne#> P y K iS2T i$ legalCoord-ne#`,bdSi8e. and ^ legalCoord-ne#>,bdSi8e.0 ne#Moves=a!!end--ne#`,ne#>.. return ne#Moves

de$ legalCoord-*,bdSi8e.0 i$ * JP G and * Q bdSi8e0 return 'rue else0 return 6alse 6igure 9 sho#s the com!lete gra!h o$ !ossible moves on an eight4by4eight board= 'here are e*actly ;;C edges in the gra!h= /otice that the vertices corres!onding to the edges o$ the board have $e#er connections -legal moves. than the vertices in the middle o$ the board= Once again #e can see ho# s!arse the gra!h is= I$ the gra!h #as $ully connected there #ould be <,GEC edges= Since there are only ;;C edges, the adjacency matri* #ould be only F=9 !ercent $ull=

9<C

+ll Legal Moves $or a &night on an FcF Chessboard

Implementing 1night<s Tour


'he search algorithm #e #ill use to solve the ,night:s tour !roblem is called de!th $irst search -D6S.= hereas the breadth $irst search algorithm discussed in the !revious section builds a search tree one level at a time, a de!th $irst search creates a search tree by e*!loring one branch o$ the tree as dee!ly as !ossible= In this section #e #ill loo, at t#o algorithms that im!lement a de!th $irst search= 'he $irst algorithm #e #ill loo, at directly solves the ,night:s tour !roblem by e*!licitly $orbidding a node to be visited more than once= 'he second im!lementation is more general, but allo#s nodes to be visited more than once as the tree is constructed= 'he second version is used in subse3uent sections to develo! additional gra!h algorithms= 'he de!th $irst e*!loration o$ the gra!h is e*actly #hat #e need in order to $ind a !ath that has e*actly C; edges= e #ill see that #hen the de!th $irst search algorithm $inds a dead end -a !lace in the gra!h #here there are no more moves !ossible. it bac,s u! the tree to the ne*t dee!est verte* that allo#s it to ma,e a legal move= 9<D

'he =night)our $unction ta,es $our !arameters0 n, the current de!th in the search treeU path, a list o$ vertices visited u! to this !ointU u, the verte* in the gra!h #e #ish to e*!loreU and limit the number o$ nodes in the !ath= 'he =night)our $unction is recursive= hen the =night)our $unction is called, it $irst chec,s the base case condition= I$ #e have a !ath that contains C< vertices, #e return $rom =night)our #ith a status o$ )rue, indicating that #e have $ound a success$ul tour= I$ the !ath is not long enough #e continue to e*!lore one level dee!er by choosing a ne# verte* to e*!lore and calling =night)our recursively $or that verte*= D6S also uses colors to ,ee! trac, o$ #hich vertices in the gra!h have been visited= 5nvisited vertices are colored #hite, and visited vertices are colored gray= I$ all neighbors o$ a !articular verte* have been e*!lored and #e have not yet reached our goal length o$ C< vertices, #e have reached a dead end= hen #e reach a dead end #e must bac,trac,= Bac,trac,ing ha!!ens #hen #e return $rom =night)our #ith a status o$ *alse= In the breadth $irst search #e used a 3ueue to ,ee! trac, o$ #hich verte* to visit ne*t= Since de!th $irst search is recursive, #e are im!licitly using a stac, to hel! us #ith our bac,trac,ing= hen #e return $rom a call to =night)our #ith a status o$ *alse, in line 22, #e remain inside the Fhile loo! and loo, at the ne*t verte* in n<r1ist= $rom !ythonds=gra!hs im!ort Gra!h, 7erte* de$ ,night'our-n,!ath,u,limit.0 u=setColor-XgrayX. !ath=a!!end-u. i$ n Q limit0 nbrList P list-u=getConnections-.. iPG done P 6alse #hile i Q len-nbrList. and not done0 i$ nbrListSiT=getColor-. PP X#hiteX0 done P ,night'our-nK2, !ath, nbrListSiT, limit. iPiK2 i$ not done0 \ !re!are to bac,trac, !ath=!o!-. u=setColor-X#hiteX. else0

9<F

done P 'rue return done Let:s loo, at a sim!le e*am!le o$ =night)our in action= >ou can re$er to the $igures belo# to $ollo# the ste!s o$ the search= 6or this e*am!le #e #ill assume that the call to the getJonnections method on line C orders the nodes in al!habetical order= e begin by calling =night)our(0.path.A.6) =night)our starts #ith node + 6igure ;= 'he nodes adjacent to + are B and D= Since B is be$ore D al!habetically, D6S selects B to e*!and ne*t as sho#n in 6igure <= )*!loring B ha!!ens #hen =night)our is called recursively= B is adjacent to C and D, so =night)our elects to e*!lore C ne*t= 1o#ever, as you can see in 6igure B node C is a dead end #ith no adjacent #hite nodes= +t this !oint #e change the color o$ node C bac, to #hite= 'he call to =night)our returns a value o$ *alse= 'he return $rom the recursive call e$$ectively bac,trac,s the search to verte* B -see 6igure C.= 'he ne*t verte* on the list to e*!lore is verte* D, so =night)our ma,es a recursive call moving to node D= 6rom verte* D on, =night)our can continue to ma,e recursive calls until #e get to node C again= 1o#ever, this time #hen #e get to node C the test n , limit $ails so #e ,no# that #e have e*hausted all the nodes in the gra!h= +t this !oint #e can return )rue to indicate that #e have made a success$ul tour o$ the gra!h= hen #e return the list, path has the values -A.P.D.@.*.J/, #hich is the the order #e need to traverse the gra!h to visit each node e*actly once=

Start #ith node +

)*!lore B

/ode C is a dead end

9<E

bac,trac, to B

6inish 6igure D sho#s you #hat a com!lete tour around an eight4by4eight board loo,s li,e= 'here are many !ossible toursU some are symmetric= ith some modi$ication you can ma,e circular tours that start and end at the same s3uare=

9BG

+ Com!lete 'our o$ the Board

1night<s Tour Analysis


'here is one last interesting to!ic regarding the ,night:s tour !roblem, then #e #ill move on to the general version o$ the de!th $irst search= 'he to!ic is !er$ormance= In !articular, =night)our is very sensitive to the method you use to select the ne*t verte* to visit= 6or e*am!le, on a $ive4by4$ive board you can !roduce a !ath in about 2=B seconds on a reasonably $ast com!uter= But #hat ha!!ens i$ you try an eight4by4eight board" In this case, de!ending on the s!eed o$ your com!uter, you may have to #ait u! to a hal$ hour to get the resultsR 'he reason $or this is that the ,night:s tour !roblem as #e have im!lemented it so $ar is an e*!onential algorithm o$ si8e '-)3., #here / is the number o$ s3uares on the chess board, and , is a small constant= 6igure F can hel! us visuali8e #hy this is so= 'he root o$ the tree re!resents the starting !oint o$ the search= 6rom there the algorithm generates and chec,s each o$ the !ossible moves the ,night can ma,e= +s #e have noted be$ore the number o$ moves !ossible de!ends on the !osition o$ the ,night on the board= In the corners there are only t#o legal moves, on the s3uares adjacent to the corners there are three and in the middle o$ the board there are eight= 6igure E sho#s the number o$ moves !ossible $or each !osition on a board= +t the ne*t level o$ the tree there are once again bet#een 9 and F !ossible ne*t

9B2

moves $rom the !osition #e are currently e*!loring= 'he number o$ !ossible !ositions to e*amine corres!onds to the number o$ nodes in the search tree=

+ Search 'ree $or the &night:s 'our

/umber o$ %ossible Moves $or )ach S3uare e have already seen that the number o$ nodes in a binary tree o$ height / is 93K2[2= 6or a tree #ith nodes that may have u! to eight children instead o$ t#o the number o$ nodes is much larger= Because the branching $actor o$ each node is variable, #e could estimate the number o$ nodes using an average branching $actor= 'he im!ortant thing to note is that this algorithm is e*!onential0 )3K2[2, #here ) is the average branching $actor $or the board= Let:s loo, at ho# ra!idly this gro#sR 6or a board that is B*B the tree #ill be 9B levels dee!, or / P 9< counting the $irst level as level G= 'he average branching $actor is )P;=F So the number o$ nodes in the search tree is ;=F9B[2 or ;=29c2G2<= 6or a C*C board, )P<=<,

9B9

there are 2=Bc2G9; nodes, and $or a regular F*F chess board, )PB=9B, there are

2=;c2G<C= O$ course, since there are multi!le solutions to the !roblem #e #on:t have to
e*!lore every single node, but the $ractional !art o$ the nodes #e do have to e*!lore is just a constant multi!lier #hich does not change the e*!onential nature o$ the !roblem= e #ill leave it as an e*ercise $or you to see i$ you can e*!ress ) as a $unction o$ the board si8e= Luc,ily there is a #ay to s!eed u! the eight4by4eight case so that it runs in under one second= In the listing belo# #e sho# the code that s!eeds u! the =night)our= 'his $unction, called order<0A2ail #ill be used in !lace o$ the call to u.getJonnections in the code !reviously sho#n above= 'he critical line in the orderP0A2ail $unction is line 2G= 'his line ensures that #e select the verte* to go ne*t that has the $e#est available moves= >ou might thin, this is really counter !roductiveU #hy not select the node that has the most available moves" >ou can try that a!!roach easily by running the !rogram yoursel$ and inserting the line res1ist.re2erse() right a$ter the sort= 'he !roblem #ith using the verte* #ith the most available moves as your ne*t verte* on the !ath is that it tends to have the ,night visit the middle s3uares early on in the tour= hen this ha!!ens it is easy $or the ,night to get stranded on one side o$ the board #here it cannot reach unvisited s3uares on the other side o$ the board= On the other hand, visiting the s3uares #ith the $e#est available moves $irst !ushes the ,night to visit the s3uares around the edges o$ the board $irst= 'his ensures that the ,night #ill visit the hard4to4reach corners early and can use the middle s3uares to ho! across the board only #hen necessary= 5tili8ing this ,ind o$ ,no#ledge to s!eed u! an algorithm is called a heuristic= 1umans use heuristics every day to hel! ma,e decisions, heuristic searches are o$ten used in the $ield o$ arti$icial intelligence= 'his !articular heuristic is called arnsdor$$:s algorithm, named a$ter 1= C= arnsdor$$ #ho !ublished his idea in 2F9;= de$ orderBy+vail-n.0 resList P ST $or v in n=geConnections-.0 i$ v=getColor-. PP X#hiteX0 cPG $or # in v=getConnections-.0 i$ #=getColor-. PP X#hiteX0 cPcK2 resList=a!!end--c,v.. resList=sort-,eyPlambda *0 *SGT. return SyS2T $or y in resListT

General Depth ,irst Search


9B;

'he ,night:s tour is a s!ecial case o$ a de!th $irst search #here the goal is to create the dee!est de!th $irst tree, #ithout any branches= 'he more general de!th $irst search is actually easier= Its goal is to search as dee!ly as !ossible, connecting as many nodes in the gra!h as !ossible and branching #here necessary= It is even !ossible that a de!th $irst search #ill create more than one tree= hen the de!th $irst search algorithm creates a grou! o$ trees #e call this a de!th $irst $orest= +s #ith the breadth $irst search our de!th $irst search ma,es use o$ !redecessor lin,s to construct the tree= In addition, the de!th $irst search #ill ma,e use o$ t#o additional instance variables in the 8erte3 class= 'he ne# instance variables are the discovery and $inish times= 'he discovery time trac,s the number o$ ste!s in the algorithm be$ore a verte* is $irst encountered= 'he $inish time is the number o$ ste!s in the algorithm be$ore a verte* is colored blac,= +s #e #ill see a$ter loo,ing at the algorithm, the discovery and $inish times o$ the nodes !rovide some interesting !ro!erties #e can use in later algorithms= 'he code $or our de!th $irst search is sho#n in the ne*t listing= Since the t#o $unctions d:s and its hel!er d:s2isit use a variable to ,ee! trac, o$ the time across calls to d:s2isit #e chose to im!lement the code as methods o$ a class that inherits $rom the Traph class= 'his im!lementation e*tends the gra!h class by adding a time instance variable and the t#o methods d:s and d:s2isit= Loo,ing at line 22 you #ill notice that the d:s method iterates over all o$ the vertices in the gra!h calling d:s2isit on the nodes that are #hite= 'he reason #e iterate over all the nodes, rather than sim!ly searching $rom a chosen starting node, is to ma,e sure that all nodes in the gra!h are considered and that no vertices are le$t out o$ the de!th $irst $orest= It may loo, unusual to see the statement :or a8erte3 in sel:, but remember that in this case sel: is an instance o$ the D*STraph class, and iterating over all the vertices in an instance o$ a gra!h is a natural thing to do= $rom !ythonds=gra!hs im!ort Gra!h class D6SGra!h-Gra!h.0 de$ OOinitOO-sel$.0 su!er-.=OOinitOO-. sel$=time P G

de$ d$s-sel$.0 $or a7erte* in sel$0 a7erte*=setColor-X#hiteX. a7erte*=set%red-42. $or a7erte* in sel$0 i$ a7erte*=getColor-. PP X#hiteX0 sel$=d$svisit-a7erte*. 9B<

de$ d$svisit-sel$,start7erte*.0 start7erte*=setColor-XgrayX. sel$=time KP 2 start7erte*=setDiscovery-sel$=time. $or ne*t7erte* in start7erte*=getConnections-.0 i$ ne*t7erte*=getColor-. PP X#hiteX0 ne*t7erte*=set%red-start7erte*. sel$=d$svisit-ne*t7erte*. start7erte*=setColor-Xblac,X. sel$=time KP 2 start7erte*=set6inish-sel$=time. +lthough our im!lementation o$ <:s #as only interested in considering nodes $or #hich there #as a !ath leading bac, to the start, it is !ossible to create a breadth $irst $orest that re!resents the shortest !ath bet#een all !airs o$ nodes in the gra!h= e leave this as an e*ercise= In our ne*t t#o algorithms #e #ill see #hy ,ee!ing trac, o$ the de!th $irst $orest is im!ortant= 'he d:s2isit method starts #ith a single verte* called start8erte3 and e*!lores all o$ the neighboring #hite vertices as dee!ly as !ossible= I$ you loo, care$ully at the code $or d:s2isit and com!are it to breadth $irst search, #hat you should notice is that the d:s2isit algorithm is almost identical to <:s e*ce!t that on the last line o$ the inner :or loo!, d:s2isit calls itsel$ recursively to continue the search at a dee!er level, #hereas <:s adds the node to a 3ueue $or later e*!loration= It is interesting to note that #here <:s uses a 3ueue, d:s2isit uses a stac,= >ou don:t see a stac, in the code, but it is im!licit in the recursive call to d:s2isit= 'he $ollo#ing se3uence o$ $igures illustrates the de!th $irst search algorithm in action $or a small gra!h= In these $igures, the dotted lines indicate edges that are chec,ed, but the node at the other end o$ the edge has already been added to the de!th $irst tree= In the code this test is done by chec,ing that the color o$ the other node is non4#hite= 'he search begins at verte* + o$ the gra!h -6igure 2G.= Since all o$ the vertices are #hite at the beginning o$ the search the algorithm visits verte* += 'he $irst ste! in visiting a verte* is to set the color to gray, #hich indicates that the verte* is being e*!lored and the discovery time is set to 2= Since verte* + has t#o adjacent vertices -B, D. each o$ those need to be visited as #ell= e:ll ma,e the arbitrary decision that #e #ill visit the adjacent vertices in al!habetical order= 7erte* B is visited ne*t, so its color is set to gray and its discovery time is set to 9= 7erte* B is also adjacent to t#o other nodes -C, D. so #e #ill $ollo# the al!habetical order and visit node C ne*t=

9BB

7isiting verte* C brings us to the end o$ one branch o$ the tree= +$ter coloring the node gray and setting its discovery time to ;, the algorithm also determines that there are no adjacent vertices to C= 'his means that #e are done e*!loring node C and so #e can color the verte* blac,, and set the $inish time to <= >ou can see the state o$ our search at this !oint in 6igure 2;= Since verte* C #as the end o$ one branch #e no# return to verte* B and continue e*!loring the nodes adjacent to B= 'he only additional verte* to e*!lore $rom B is D, so #e can no# visit D and continue our search $rom verte* D= 7erte* D 3uic,ly leads us to verte* )= 7erte* ) has t#o adjacent vertices, B and 6= /ormally #e #ould e*!lore these adjacent vertices al!habetically, but since B is already colored gray the algorithm recogni8es that it should not visit B since doing so #ould !ut the algorithm in a loo!R So e*!loration continues #ith the ne*t verte* in the list, namely 6= 7erte* 6 has only one adjacent verte*, C, but since C is colored blac, there is nothing else to e*!lore, and the algorithm has reached the end o$ another branch= 6rom here on, you #ill see in 6igure 2D thru 6igure 92 that the algorithm #or,s its #ay bac, to the $irst node, setting $inish times and coloring vertices blac,=

Constructing the De!th 6irst Search 'ree42G

Constructing the De!th 6irst Search 'ree422

Constructing the De!th 6irst Search 'ree429

9BC

Constructing the De!th 6irst Search 'ree42;

Constructing the De!th 6irst Search 'ree42<

Constructing the De!th 6irst Search 'ree42B

Constructing the De!th 6irst Search 'ree42C

Constructing the De!th 6irst Search 'ree42D

9BD

Constructing the De!th 6irst Search 'ree42F

Constructing the De!th 6irst Search 'ree42E

Constructing the De!th 6irst Search 'ree49G

Constructing the De!th 6irst Search 'ree492 'he starting and $inishing times $or each node dis!lay a !ro!erty called the !arenthesis !ro!erty= 'his !ro!erty means that all the children o$ a !articular node in the de!th $irst tree have a later discovery time and an earlier $inish time than their !arent= 6igure 99 sho#s the tree constructed by the de!th $irst search algorithm=

'he Resulting De!th 6irst Search 'ree

Depth ,irst Search Analysis


'he general running time $or de!th $irst search is as $ollo#s= 'he loo!s in d:s both run in '-8., not counting #hat ha!!ens in d:s2isit, since they are e*ecuted once $or each verte* in the gra!h= In d:s2isit the loo! is e*ecuted once $or each edge in the adjacency list o$ the

9BF

current verte*= Since d:s2isit is only called recursively i$ the verte* is #hite, the loo! #ill e*ecute a ma*imum o$ once $or every edge in the gra!h or '--.= So, the total time $or de!th $irst search is '-8K-.=

Topological Sorting
'o demonstrate that com!uter scientists can turn just about anything into a gra!h !roblem, let:s consider the di$$icult !roblem o$ stirring u! a batch o$ !anca,es= 'he reci!e is really 3uite sim!le0 2 egg, 2 cu! o$ !anca,e mi*, 2 tables!oon oil, and ;< cu! o$ mil,= 'o ma,e !anca,es you must heat the griddle, mi* all the ingredients together and s!oon the mi* onto a hot griddle= hen the !anca,es start to bubble you turn them over and let them coo, until they are golden bro#n on the bottom= Be$ore you eat your !anca,es you are going to #ant to heat u! some syru!= 6igure 9; illustrates this !rocess as a gra!h=

'he Ste!s $or Ma,ing %anca,es 'he di$$icult thing about ma,ing !anca,es is ,no#ing #hat to do $irst= +s you can see $rom 6igure 9; you might start by heating the griddle or by adding any o$ the ingredients to the !anca,e mi*= 'o hel! us decide the !recise order in #hich #e should do each o$ the ste!s re3uired to ma,e our !anca,es #e turn to a gra!h algorithm called the to!ological sort= + to!ological sort ta,es a directed acyclic gra!h and !roduces a linear ordering o$ all its vertices such that i$ the gra!h 7 contains an edge -*, . then the verte* * comes be$ore the verte* in the ordering= Directed acyclic gra!hs are used in many a!!lications to indicate the !recedence o$ events= Ma,ing !anca,es is just one e*am!leU other e*am!les include so$t#are !roject schedules, !recedence charts $or o!timi8ing database 3ueries, and multi!lying matrices= 'he to!ological sort is a sim!le but use$ul ada!tation o$ a de!th $irst search= 'he algorithm $or the to!ological sort is as $ollo#s0 9BE

Call d:s(g) $or some gra!h g= 'he main reason #e #ant to call de!th $irst search is to com!ute the $inish times $or each o$ the vertices= Store the vertices in a list in decreasing order o$ $inish time= Return the ordered list as the result o$ the to!ological sort=

6igure 9< sho#s the de!th $irst $orest constructed by d:s on the !anca,e4ma,ing gra!h sho#n in 6igure 9;=

Result o$ De!th 6irst Search on the %anca,e Gra!h 6inally, 6igure 9B sho#s the results o$ a!!lying the to!ological sort algorithm to our gra!h= /o# all the ambiguity has been removed and #e ,no# e*actly the order in #hich to !er$orm the !anca,e ma,ing ste!s=

Result o$ 'o!ological Sort on Directed +cyclic Gra!h

Strongly #onnected #omponents


6or the remainder o$ this cha!ter #e #ill turn our attention to some e*tremely large gra!hs= 'he gra!hs #e #ill use to study some additional algorithms are the gra!hs !roduced by the

9CG

connections bet#een hosts on the Internet and the lin,s bet#een #eb !ages= e #ill begin #ith #eb !ages= Search engines li,e Google and Bing e*!loit the $act that the !ages on the #eb $orm a very large directed gra!h= 'o trans$orm the orld ide eb into a gra!h, #e #ill treat a !age as a verte*, and the hy!erlin,s on the !age as edges connecting one verte* to another= 6igure 9C sho#s a very small !art o$ the gra!h !roduced by $ollo#ing the lin,s $rom one !age to the ne*t, beginning at Luther College:s Com!uter Science home !age= O$ course, this gra!h could be huge, so #e have limited it to #eb sites that are no more than 2G lin,s a#ay $rom the CS home !age=

'he Gra!h %roduced by Lin,s $rom the Luther Com!uter Science 1ome %age I$ you study the gra!h in 6igure 9C you might ma,e some interesting observations= 6irst you might notice that many o$ the other #eb sites on the gra!h are other Luther College #eb sites= Second, you might notice that there are several lin,s to other colleges in Io#a= 'hird, you might notice that there are several lin,s to other liberal arts colleges= >ou might conclude

9C2

$rom this that there is some underlying structure to the #eb that clusters together #eb sites that are similar on some level= One gra!h algorithm that can hel! $ind clusters o$ highly interconnected vertices in a gra!h is called the strongly connected com!onents algorithm -SCC.= e $ormally de$ine a strongly connected com!onent, 6, o$ a gra!h 7, as the largest subset o$ vertices 68 such that $or every !air o$ vertices *, 6 #e have a !ath $rom * to and a !ath $rom to *= 6igure 9D sho#s a sim!le gra!h #ith three strongly connected com!onents= 'he strongly connected com!onents are identi$ied by the di$$erent shaded areas=

+ Directed Gra!h #ith 'hree Strongly Connected Com!onents Once the strongly connected com!onents have been identi$ied #e can sho# a sim!li$ied vie# o$ the gra!h by combining all the vertices in one strongly connected com!onent into a single larger verte*= 'he sim!li$ied version o$ the gra!h in 6igure 9D is sho#n in 6igure 9F=

'he Reduced Gra!h Once again #e #ill see that #e can create a very !o#er$ul and e$$icient algorithm by ma,ing use o$ a de!th $irst search= Be$ore #e tac,le the main SCC algorithm #e must loo, at one other de$inition= 'he trans!osition o$ a gra!h 7 is de$ined as the gra!h 7T #here all the edges in the gra!h have been reversed= 'hat is, i$ there is a directed edge $rom node + to

9C9

node B in the original gra!h then 7T #ill contain and edge $rom node B to node += 6igure 9E and 6igure ;G sho# a sim!le gra!h and its trans!osition=

+ Gra!h 7

Its 'rans!ose 7T Loo, at the $igures again= /otice that the gra!h in 6igure 9E has t#o strongly connected com!onents= /o# loo, at 6igure ;G= /otice that it has the same t#o strongly connected com!onents= e can no# describe the algorithm to com!ute the strongly connected com!onents $or a gra!h= Call d:s $or the gra!h 7 to com!ute the $inish times $or each verte*=

Com!ute 7T= Call d:s $or the gra!h 7T but in the main loo! o$ D6S e*!lore each verte* in decreasing order o$ $inish time= )ach tree in the $orest com!uted in ste! ; is a strongly connected com!onent= Out!ut the verte* ids $or each verte* in each tree in the $orest to identi$y the com!onent=

Lets trace the o!eration o$ the ste!s described above on the e*am!le gra!h in 6igure 9D= 6igure ;2 sho#s the starting and $inishing times com!uted $or the original gra!h by the D6S algorithm= 6igure ;9 sho#s the starting and $inishing times com!uted by running D6S on the trans!osed gra!h=

9C;

6inishing times $or the original gra!h 7

6inishing times $or 7T 6inally, 6igure ;; sho#s the $orest o$ three trees !roduced in ste! ; o$ the strongly connected com!onent algorithm= >ou #ill notice that #e do not !rovide you #ith the %ython code $or the SCC algorithm, #e leave #riting this !rogram as an e*ercise=

9C<

'he Strongly Connected Com!onents as a 6orest o$ 'rees Shortest %ath %roblems hen you sur$ the #eb, send an email, or log in to a laboratory com!uter $rom another location on cam!us a lot o$ #or, is going on behind the scenes to get the in$ormation on your com!uter trans$erred to another com!uter= 'he in4de!th study o$ ho# in$ormation $lo#s $rom one com!uter to another over the Internet is the !rimary to!ic $or a class in com!uter net#or,ing= 1o#ever, #e #ill tal, about ho# the Internet #or,s just enough to understand another very im!ortant gra!h algorithm= ==MOimagesMInternet=!ng Overvie# o$ Connectivity in the Internet 6igure 2 sho#s you a high4level overvie# o$ ho# communication on the Internet #or,s= hen you use your bro#ser to re3uest a #eb !age $rom a server, the re3uest must travel over your local area net#or, and out onto the Internet through a router= 'he re3uest travels over the Internet and eventually arrives at a router $or the local area net#or, #here the server is located= 'he #eb !age you re3uested then travels bac, through the same routers to get to your bro#ser= Inside the cloud labelled ?Internet@ in 6igure 2 are additional routers= 'he job o$ all o$ these routers is to #or, together to get your in$ormation $rom !lace to !lace= >ou can see there are many routers $or yoursel$ i$ your com!uter su!!orts the traceroute command= 'he te*t belo# sho#s the out!ut o$ the traceroute command #hich illustrates that there are 2; routers bet#een the #eb server at Luther College and the mail server at the 5niversity o$ Minnesota= 2 2E9=9G;=2EC=2

9CB

9 hilda=luther=edu -92C=2BE=DB=2. ; IC/4Luther4)ther=icn=state=ia=us -9GD=2CB=9;D=2;D. < IC/4IS%42=icn=state=ia=us -9GE=BC=9BB=2. B !;4G=hsa2=chi2=bbn!lanet=net -<=9<=9G9=2;. C ae424B<=bbr9=Chicago2=Level;=net -<=CF=2G2=ED. D so4;4G4G=m!ls9=Minnea!olis2=Level;=net -C<=2BE=<=92<. F ge4;4G=hsa9=Minnea!olis2=Level;=net -<=CF=229=2F. E !24G=minnesota=bbn!lanet=net -<=9<=99C=D<. 2G 'elecomB4BR4G247<GG9=ggnet=umn=edu -2E9=<9=2B9=;D. 22 'elecomB4B/4G247lan4;GGG=ggnet=umn=edu -29F=2G2=BF=2. 29 'elecomB4C/4G247lan4D2G=ggnet=umn=edu -29F=2G2=FG=2BF. 2; baldric,=cs=umn=edu -29F=2G2=FG=29E.-/R. FF=C;2 ms -/R. Routers $rom One 1ost to the /e*t over the Internet )ach router on the Internet is connected to one or more other routers= So i$ you run the traceroute command at di$$erent times o$ the day, you are li,ely to see that your in$ormation $lo#s through di$$erent routers at di$$erent times= 'his is because there is a cost associated #ith each connection bet#een a !air o$ routers that de!ends on the volume o$ tra$$ic, the time o$ day, and many other $actors= By this time it #ill not sur!rise you to learn that #e can re!resent the net#or, o$ routers as a gra!h #ith #eighted edges= ==MOimagesMrouteGra!h=!ng Connections and eights bet#een Routers in the Internet

6igure 9 sho#s a small e*am!le o$ a #eighted gra!h that re!resents the interconnection o$ routers in the Internet= 'he !roblem that #e #ant to solve is to $ind the !ath #ith the smallest total #eight along #hich to route any given message= 'his !roblem should sound $amiliar because it is similar to the !roblem #e solved using a breadth $irst search, e*ce!t that here #e are concerned #ith the total #eight o$ the !ath rather than the number o$ ho!s in the !ath= It should be noted that i$ all the #eights are e3ual, the !roblem is the same= Dij,stra:s +lgorithm 'he algorithm #e are going to use to determine the shortest !ath is called ?Dij,stra:s algorithm=@ Dij,stra:s algorithm is an iterative algorithm that !rovides us #ith the shortest !ath $rom one !articular starting node to all other nodes in the gra!h= +gain this is similar to the results o$ a breadth $irst search= 'o ,ee! trac, o$ the total cost $rom the start node to each destination #e #ill ma,e use o$ the dist instance variable in the 7erte* class= 'he dist instance variable #ill contain the current total #eight o$ the smallest #eight !ath $rom the start to the verte* in 3uestion= 'he algorithm iterates once $or every verte* in the gra!hU ho#ever, the order that #e iterate over the vertices is controlled by a !riority 3ueue= 'he value that is used to determine the order o$ the objects in the !riority 3ueue is dist= hen a verte* is $irst created dist is set to a very large number= 'heoretically you #ould set dist to in$inity, but in !ractice #e just set it to a number that is larger than any real distance #e #ould have in the !roblem #e are trying to solve=

9CC

'he code $or Dij,stra:s algorithm is sho#n in the $ollo#ing listing= hen the algorithm $inishes the distances are set correctly as are the !redecessor lin,s $or each verte* in the gra!h= $rom !ythonds=gra!hs im!ort %riority(ueue, Gra!h, 7erte* de$ dij,stra-aGra!h,start.0 !3 P %riority(ueue-. start=setDistance-G. !3=build1ea!-S-v=getDistance-.,v. $or v in aGra!hT. #hile not !3=is)m!ty-.0 current7ert P !3=delMin-. $or ne*t7ert in current7ert=getConnections-.0 ne#Dist P current7ert=getDistance-. ^ K current7ert=get eight-ne*t7ert. i$ ne#Dist Q ne*t7ert=getDistance-.0 ne*t7ert=setDistance- ne#Dist . ne*t7ert=set%red-current7ert. !3=decrease&ey-ne*t7ert,ne#Dist. Dij,stra:s algorithm uses a !riority 3ueue= >ou may recall that a !riority 3ueue is based on the hea! that #e im!lemented in the 'ree Cha!ter= 'here are a cou!le o$ di$$erences bet#een that sim!le im!lementation and the im!lementation #e use $or Dij,stra:s algorithm= 6irst, the %riority(ueue class stores tu!les o$ ,ey, value !airs= 'his is im!ortant $or Dij,stra:s algorithm as the ,ey in the !riority 3ueue must match the ,ey o$ the verte* in the gra!h= Secondly the value is used $or deciding the !riority, and thus the !osition o$ the ,ey in the !riority 3ueue= In this im!lementation #e use the distance to the verte* as the !riority because as #e #ill see #hen #e are e*!loring the ne*t verte*, #e al#ays #ant to e*!lore the verte* that has the smallest distance= 'he second di$$erence is the addition o$ the decrease&ey method= +s you can see, this method is used #hen the distance to a verte* that is already in the 3ueue is reduced, and thus moves that verte* to#ard the $ront o$ the 3ueue= Let:s #al, through an a!!lication o$ Dij,stra:s algorithm one verte* at a time using the $ollo#ing se3uence o$ $igures as our guide= e begin #ith the verte* u= 'he three vertices adjacent to u are v,#, and *= Since the initial distances to v,#, and * are all initiali8ed to sys=ma*int, the ne# costs to get to them through the start node are all their direct costs= So #e u!date the costs to each o$ these three nodes= e also set the !redecessor $or each node to u and #e add each node to the !riority 3ueue= e use the distance as the ,ey $or the !riority 3ueue= 'he state o$ the algorithm is sho#n in 6igure ;= In the ne*t iteration o$ the #hile loo! #e e*amine the vertices that are adjacent to *= 'he verte* * is ne*t because it has the lo#est overall cost and there$ore bubbled its #ay to the beginning o$ the !riority 3ueue= +t * #e loo, at its neighbors u,v,# and y= 6or each neighboring verte* #e chec, to see i$ the distance to that verte* through * is smaller than the !reviously ,no#n distance= Obviously this is the case $or y since its distance #as sys=ma*int= It is not the case $or u or v since their distances are G and 9 res!ectively= 1o#ever, #e no# learn that the distance to # is smaller i$ #e go through * than $rom u directly to #= Since that is the case #e u!date # #ith a ne# distance and change the !redecessor $or # $rom u to *= See 6igure < $or the state o$ all the vertices=

9CD

'he ne*t ste! is to loo, at the vertices neighboring v= 'his ste! results in no changes to the gra!h, so #e move on to node y= +t node y #e discover that it is chea!er to get to both # and 8, so #e adjust the distances and !redecessor lin,s accordingly= 6inally #e chec, nodes # and 8= 1o#ever, no additional changes are $ound and so the !riority 3ueue is em!ty and Dij,stra:s algorithm e*its= ==MOimagesMdij,straa=!ng 'racing Dij,stra:s +lgorithm4; ==MOimagesMdij,strab=!ng 'racing Dij,stra:s +lgorithm4< ==MOimagesMdij,strac=!ng 'racing Dij,stra:s +lgorithm4B ==MOimagesMdij,strad=!ng 'racing Dij,stra:s +lgorithm4C ==MOimagesMdij,strae=!ng 'racing Dij,stra:s +lgorithm4D ==MOimagesMdij,stra$=!ng 'racing Dij,stra:s +lgorithm4F It is im!ortant to note that Dij,stra:s algorithm #or,s only #hen the #eights are all !ositive= >ou should convince yoursel$ that i$ you introduced a negative #eight on one o$ the edges to the gra!h that the algorithm #ould never e*it= e #ill note that to route messages through the Internet, other algorithms are used $or $inding the shortest !ath= One o$ the !roblems #ith using Dij,stra:s algorithm on the Internet is that you must have a com!lete re!resentation o$ the gra!h in order $or the algorithm to run= 'he im!lication o$ this is that every router has a com!lete ma! o$ all the routers in the Internet= In !ractice this is not the case and other variations o$ the algorithm allo# each router to discover the gra!h as they go= One such algorithm that you may #ant to read about is called the ?distance vector@ routing algorithm= +nalysis o$ Dij,stra:s +lgorithm 6inally, let us loo, at the running time o$ Dij,stra:s algorithm= e $irst note that building the !riority 3ueue ta,es O-7. time since #e initially add every verte* in the gra!h to the !riority 3ueue= Once the 3ueue is constructed the #hile loo! is e*ecuted once $or every verte* since vertices are all added at the beginning and only removed a$ter that= ithin that loo! each call to delMin, ta,es O-log7. time= 'a,en together that !art o$ the loo! and the calls to delMin ta,e O-7log-7..= 'he $or loo! is e*ecuted once $or each edge in the gra!h, and #ithin the $or loo! the call to decrease&ey ta,es time O-)log-7..= So the combined running time is 0math0Z O--7K). log-7..Z= %rim:s S!anning 'ree +lgorithm 6or our last gra!h algorithm let:s consider a !roblem that online game designers and Internet radio !roviders $ace= 'he !roblem is that they #ant to e$$iciently trans$er a !iece o$ in$ormation to anyone and everyone #ho may be listening= 'his is im!ortant in gaming so

9CF

that all the !layers ,no# the very latest !osition o$ every other !layer= 'his is im!ortant $or Internet radio so that all the listeners that are tuned in are getting all the data they need to reconstruct the song they are listening to= 6igure E illustrates the broadcast !roblem= ==MOimagesMbcast2=!ng 'he Broadcast %roblem 'here are some brute $orce solutions to this !roblem, so let:s loo, at them $irst to hel! understand the broadcast !roblem better= 'his #ill also hel! you a!!reciate the solution that #e #ill !ro!ose #hen #e are done= 'o begin, the broadcast host has some in$ormation that the listeners all need to receive= 'he sim!lest solution is $or the broadcasting host to ,ee! a list o$ all o$ the listeners and send individual messages to each= In 6igure E #e sho# a small net#or, #ith a broadcaster and some listeners= 5sing this $irst a!!roach, $our co!ies o$ every message #ould be sent= +ssuming that the least cost !ath is used, let:s see ho# many times each router #ould handle the same message= +ll messages $rom the broadcaster go through router +, so + sees all $our co!ies o$ every message= Router C sees only one co!y o$ each message $or its listener= 1o#ever, routers B and D #ould see three co!ies o$ every message since routers B and D are on the chea!est !ath $or listeners 2, 9, and ;= hen you consider that the broadcast host must send hundreds o$ messages each second $or a radio broadcast, that is a lot o$ e*tra tra$$ic= + brute $orce solution is $or the broadcast host to send a single co!y o$ the broadcast message and let the routers sort things out= In this case, the easiest solution is a strategy called uncontrolled $looding= 'he $looding strategy #or,s as $ollo#s= )ach message starts #ith a time to live -ttl. value set to some number greater than or e3ual to the number o$ edges bet#een the broadcast host and its most distant listener= )ach router gets a co!y o$ the message and !asses the message on to all o$ its neighboring routers= hen the message is !assed on the ttl is decreased= )ach router continues to send co!ies o$ the message to all its neighbors until the ttl value reaches G= It is easy to convince yoursel$ that uncontrolled $looding generates many more unnecessary messages than our $irst strategy= 'he solution to this !roblem lies in the construction o$ a minimum #eight s!anning tree= 6ormally #e de$ine the minimum s!anning tree ' $or a gra!h GP-7,). as $ollo#s= ' is an acyclic subset o$ ) that connects all the vertices in 7= 'he sum o$ the #eights o$ the edges in ' is minimi8ed= 6igure 2G sho#s a sim!li$ied version o$ the broadcast gra!h and highlights the edges that $orm a minimum s!anning tree $or the gra!h= /o# to solve our broadcast !roblem, the broadcast host sim!ly sends a single co!y o$ the broadcast message into the net#or,= )ach router $or#ards the message to any neighbor that is !art o$ the s!anning tree, e*cluding the neighbor that just sent it the message= In this e*am!le + $or#ards the message to B= B $or#ards the message to D and C= D $or#ards the message to ), #hich $or#ards it to 6, #hich $or#ards it to G= /o router sees more than one co!y o$ any message, and all the listeners that are interested see a co!y o$ the message= ==MOimagesMmst2=!ng Minimum S!anning 'ree $or the Broadcast Gra!h

9CE

'he algorithm #e #ill use to solve this !roblem is called %rim:s algorithm= %rim:s algorithm belongs to a $amily o$ algorithms called the ?greedy algorithms@ because at each ste! #e #ill choose the chea!est ne*t ste!= In this case the chea!est ne*t ste! is to $ollo# the edge #ith the lo#est #eight= Our last ste! is to develo! %rim:s algorithm= 'he basic idea in constructing a s!anning tree is as $ollo#s0 hile 0math0Z'Z is not yet a s!anning tree 6ind an edge that is sa$e to add to the tree +dd the ne# edge to 0math0Z'Z 'he tric, is in the ste! that directs us to ?$ind an edge that is sa$e=@ e de$ine a sa$e edge as any edge that connects a verte* that is in the s!anning tree to a verte* that is not in the s!anning tree= 'his ensures that the tree #ill al#ays remain a tree and there$ore have no cycles= 'he %ython code to im!lement %rim:s algorithm is sho#n in the listing belo#= %rim:s algorithm is similar to Dij,stra:s algorithm in that they both use a !riority 3ueue to select the ne*t verte* to add to the gro#ing gra!h= $rom !ythonds=gra!hs im!ort %riority(ueue, Gra!h, 7erte* de$ !rim-G,start.0 !3 P %riority(ueue-. $or v in G0 v=setDistance-sys=ma*si8e. v=set%red-/one. start=setDistance-G. !3=build1ea!-S-v=getDistance-.,v. $or v in GT. #hile not !3=is)m!ty-.0 current7ert P !3=delMin-. $or ne*t7ert in current7ert=getConnections-.0 ne#Cost P current7ert=get eight-ne*t7ert. ^ K current7ert=getDistance-. i$ v in !3 and ne#CostQne*t7ert=getDistance-.0 ne*t7ert=set%red-current7ert. ne*t7ert=setDistance-ne#Cost. !3=decrease&ey-ne*t7ert,ne#Cost. 'he $ollo#ing se3uence o$ $igures sho#s the algorithm in o!eration on our sam!le tree= e begin #ith the starting verte* as += 'he distances to all the other vertices are initiali8ed to in$inity= Loo,ing at the neighbors o$ + #e can u!date distances to t#o o$ the additional vertices B and C because the distances to B and C through + are less than in$inite= 'his moves B and C to the $ront o$ the !riority 3ueue= 5!date the !redecessor lin,s $or B and C by setting them to !oint to += It is im!ortant to note that #e have not $ormally added B or C to the s!anning tree yet= + node is not considered to be !art o$ the s!anning tree until it is removed $rom the !riority 3ueue= Since B has the smallest distance #e loo, at B ne*t= )*amining B:s neighbors #e see that D and ) can be u!dated= Both D and ) get ne# distance values and their !redecessor lin,s are u!dated= Moving on to the ne*t node in the !riority 3ueue #e $ind C= 'he only node C is

9DG

adjacent to that is still in the !riority 3ueue is 6, thus #e can u!date the distance to 6 and adjust 6:s !osition in the !riority 3ueue= /o# #e e*amine the vertices adjacent to node D= e $ind that #e can u!date ) and reduce the distance to ) $rom C to <= hen #e do this #e change the !redecessor lin, on ) to !oint bac, to D, thus !re!aring it to be gra$ted into the s!anning tree but in a di$$erent location= 'he rest o$ the algorithm !roceeds as you #ould e*!ect, adding each ne# node to the tree= ==MOimagesM!rima=!ng 'racing %rim:s +lgorithm422 ==MOimagesM!rimb=!ng 'racing %rim:s +lgorithm429 ==MOimagesM!rimc=!ng 'racing %rim:s +lgorithm42; ==MOimagesM!rimd=!ng 'racing %rim:s +lgorithm42< ==MOimagesM!rime=!ng 'racing %rim:s +lgorithm42B ==MOimagesM!rim$=!ng 'racing %rim:s +lgorithm42C ==MOimagesM!rimg=!ng 'racing %rim:s +lgorithm42D

Summary
In this cha!ter #e have loo,ed at the gra!h abstract data ty!e, and some im!lementations o$ a gra!h= + gra!h enables us to solve many !roblems !rovided #e can trans$orm the original !roblem into something that can be re!resented by a gra!h= In !articular, #e have seen that gra!hs are use$ul to solve !roblems in the $ollo#ing general areas=

Breadth $irst search $or $inding the un#eighted shortest !ath= Dij,stra:s algorithm $or #eighted shortest !ath= De!th $irst search $or gra!h e*!loration= Strongly connected com!onents $or sim!li$ying a gra!h= 'o!ological sort $or ordering tas,s= Minimum #eight s!anning trees $or broadcasting messages=

1ey Terms
acyclic gra!h adjacency list adjacency matri*

9D2

adjacent cyclic gra!h de!th $irst search -D6S. directed gra!h !arenthesis !ro!erty s!anning tree verte*

breadth $irst search -B6S. D+G digra!h edge cost !ath strongly connected com!onents -SCC. #eight

cycle de!th $irst $orest directed acyclic gra!h -D+G. edge shortest !ath to!ological sort W uncontrolled $looding

Discussion 2uestions
2= Dra# the gra!h corres!onding to the $ollo#ing adjacency matri*=

2= Dra# the gra!h corres!onding to the $ollo#ing list o$ edges= %rom to cost 2 2 2 9 ; ; < C 9 2G ; 2B C B ; D < D C 2G B D < B

B C 2; 9= Ignoring the #eights, !er$orm a breadth $irst search on the gra!h $rom the !revious 3uestion= ;= hat is the Big4O running time o$ the <uildTraph $unction"

9D9

<= Derive the Big4O running time $or the to!ological sort algorithm= B= Derive the Big4O running time $or the strongly connected com!onents algorithm= C= Sho# each ste! in a!!lying Dij,stra:s algorithm to the gra!h sho#n above= D= 5sing %rim:s algorithm, $ind the minimum #eight s!anning tree $or the gra!h sho#n above= F= Dra# a de!endency gra!h illustrating the ste!s needed to send an email= %er$orm a to!ological sort on your gra!h= E= Derive an e*!ression $or the base o$ the e*!onent used in e*!ressing the running time o$ the ,nights tour= 2G= )*!lain #hy the general D6S algorithm is not suitable $or solving the ,nights tour !roblem= 22= hat is the Big4O running time $or %rim:s minimum s!anning tree algorithm"

Programming ()ercises
2= Modi$y the de!th $irst search $unction to !roduce a to!ological sort= 9= Modi$y the de!th $irst search to !roduce strongly connected com!onents= ;= rite the transpose method $or the Traph class= <= 5sing breadth $irst search #rite an algorithm that can determine the shortest !ath $rom each verte* to every other verte*= 'his is called the all !airs shortest !ath !roblem= B= 5sing breadth $irst search revise the ma8e !rogram $rom the recursion cha!ter to $ind the shortest !ath out o$ a ma8e= C= rite a !rogram to solve the $ollo#ing !roblem0 >ou have t#o jugs, a <4gallon and a ;4gallon= /either o$ the jugs has mar,ings on them= 'here is a !um! that can be used to $ill the jugs #ith #ater= 1o# can you get e*actly t#o gallons o$ #ater in the < gallon jug" D= Generali8e the !roblem above so that the !arameters to your solution include the si8es o$ each jug and the $inal amount o$ #ater to be le$t in the larger jug= F= rite a !rogram that solves the $ollo#ing !roblem0 'hree missionaries and three cannibals come to a river and $ind a boat that holds t#o !eo!le= )veryone must get across the river to continue on the journey= 1o#ever, i$ the cannibals ever outnumber the missionaries on either ban,, the missionaries #ill be eaten= 6ind a series o$ crossings that #ill get everyone sa$ely to the other side o$ the river=

9D;

S-ar putea să vă placă și