You are on page 1of 265
Google This book is provided in digital form with the permission of the rightsholder as part of a Google project to make the world's books discoverable online. The rightsholder has graciously given you the freedom to download all pages of this book. No additional commercial or other uses have been granted Please note that all copyrights remain reserved About Google Books Google's mission is to organize the world’s information and to make it universally accessible and useful. Google Books helps readers discover the world’s books while helping authors and publishers reach new audiences. You can search through the full text of this book on the web at ittp//books.google.com4 Daniel Danciu George Mardale ARTA PROGRAMARII IN JAVA vol II - Algoritmi gsi structuri de date viizessy Google Cuprins 9 Analiza eficientei algoritmilor 10 94 92 93 94 95 Ce este analiza algoritmilor? Notajia asimptotics 9.2.1 O notafie pentrs ordinul de marime al timpului de exe~ ccufie al unui algoritm Tehnici de analiza algoritmilor 9.3.1 Sortarea prin selectie 9.3.2 Sortarea prin inserie 9.33 Tumurile din Hanoi Analiza algoritmilor recursiv 9.4.1 Metoda itera 9.4.2 Inducfia constructiva, 9.4.3 Recurenje liniare omogene 9.44 Recurenje liniare neomogene 9.4.5 Schimbarea variabilei Implementarea algoritmilor Structuri de date 10.1 102 103 104 105 106 Cum implementam structusile de date? Stive Cozi ste inlinjuite Arbor. : 10.5.1 Nogiuni generale 10.52 Arboribinari 10.5.3 Arboribinaride ctutare Tabele de repartizare 10.6.1. Tratarea coliziunilor 3 15 16 18 19 21 2 23 24 28 28 26 26 28 31 33 40 B 45 sl 2 55 65 69 - 83 cura 10.7 Cozi de prioritate 107.1 Ansamble Metoda Backtracking 11.1 Preentare generals 112 Prezentarea metodei 1121 Atribuie si avanseaza 11.22 incercareepuati 1123 Revenire 11.24. Revenire dupa constuirea une slut 11.3 Implementarea metode backtracking 114 Probleme clasicerezolvabile prin backtracking 114.1. Problema gener permutirilor : 114.2. Generarenaranjamentelor ga combinisilor 1143 Problema damelor 114.4 Problema colori hiqilor 12 Divide et impera 12.1 Introducere in recursivitate 12.1.1 Funefii recursive 12.1.2. Recursivitatea nu inseamna recurenyii 12.2 Prezentarea metodei Divide et Impera 12.3 Céutare bina’ 124 Sortarea prin interclasare (MergeSort) 125 Sortarea rapids (QuickSort) 126 B 13 Algoritmi Greedy 13.1 Problema spectacolelor (selectarea activittitor) 13.1.1 Demonstrarea corectitudini algoritmului 13.1.2. Solujia problemei spectacolelor 13.2 Elemente ale strategiei Greedy 13.2.1. Proprictatea de alegere Greedy 13.2.2. Substructura optim’ 13.3 Minimizarea timpului mediu de asteptare 134 Interclasarea optima a mai multor sirusi ordonate 92 108 109 no 14 14 1s 15 7 119 119 124 126 7 437 138 138 43 145 146 149 152 157 167 168 169 im 173 176 176 7 180 4 15 16 Programare dinamici 14.1 Istorie gi descriere 14.2 Primi pasi in programarea dinamici 14.2.1. Probleme de recurensa matematica trata dinamic 14.3 Fundamentare teoreticd 144 Principiul optimalititii .. . . ss. 14.4.1 Metoda “inainte” si metoda “inapoi” . . 14.4.2. Determinarea efectiva a solutiei optime 14.5 Inmultirea unui sir de matrice 14.6 Subgir comun de lungime maxima 14.7 Distanja Levensthein ‘Metoda Branch & bound 15.1. Prezentare general’ 15.1.1 Fundamenteteoretice 15.2. Un exemplu: Puzzle cu 15 elemente 15.2.1. Enunjul problemei 15.2.2. Rezolvarea problemei Metode de elaborare a algoritmilor (sintezi) 16.1 Backiracking 16.2 Divide et impera 16.3 Greedy 1644 Programare dinamict 16.5 Branch & bound cures 186 187 138 188 198 2.201 2204 205 208 215 20 236 236 237 240 240 241 255 255 255 256 256 256 viizessy Google Introducere Nu calcula capacitatea unui pod rnumirind persoance care traverseaz acum rl int “Auziti lao prezentare Oricine a folsit cel pun o data Intemetal sau acitit o revista de specialitate {in domeniul informatici, a auzit ou siguranficuvanal Java". Java reprezinta un limbaj de programare eeat de compania Sun Microsystems in anu 1995, Ini Java fost gndit penta imibunat coninutul paginilor web prin adaiu- garea unui conjnatdinamic: animatie, multimedia etc. In momentul lansirit sale, Java a revolutionat Interetul, deoarece era prima tehnologie care oferea un asfel de contnst. Ultrior au apart si alte tehnologiaseminatoare (cum ar fi Microsoft ActiveX sau Macromedia Shockwave!), dar Java gi-a pistrat immportana deoscbitt pe care a dobindit-o i randul programatorilor. i primal rind datort facilitilor pe care Ie oferea.Incepnd cu anul 1998, cind a apdrut versinmea 2a limbajuui (engl. Java 2 Platform), Java a fost extins, acoperind g tte direct de deavoltre: programaveaaplicafilor enterprise (aplcaii de tip server), precum sia celor adresatedisportivelor eu resurse limita, cum arf telefoane mobile, pager-e sau PDA-uri2. Toate acestea au reprezentat faclitiyi noi adiugatelimbajulu, care a pasta inst si posible de a crea aplicatit standard, de ip aliafilr a inte de comands sau apicait bazate pe GUT! "Gai care wilzecl aides Iteretal sunt probabil big cu contoale ActiveX sa ev ani: ‘mai ash ead papier web. SPDA = Personal Digital Assistant (mci dspoive de eau, de dimension poi mai mac ect sl unui telefon mobi capable fee fait de agen, dat is uleze apical fran ‘mod ela aseminstor cu celal unis PC)-La moment acl exist ml multe pride PDA Pullm-us, pockelPC-u GUT = Graphical User Inrface, itera grafic de comunicare cu uilzatorl, cum sunt in several aplcaile disponiile pe sistomal de operare Microsoft Windows. 7 serRODUCERE Lansarea versiunii 2 a limbajului Java a fost 0 dovada a succesului imens de care s-au bucurat versiunile anterioare ale limbajului, dar gia dezvoltiritimba- jului in sine, a evolugiei sale ascendente din punct de vedere al facilitator pe care le ofer, cat si al performanjelor pe care le realizeazs. Cum este organizata aceasti carte? Avand in vedere popularitatea extraordinari de care se bucurlimbajul Java {in cadrul programatorilor din intreaga lume, am considerat util scrierea unei lucrari in limba romana care si fie accesibili celor care dorese si invefe sau si aprofundeze acest limbaj. Ideea care a stat la baza realizarii acestei c&rji a fost aaceea de a prezenta nu numai limbajul Java in sin, ci si modul in care se imple- ‘menteaza algoritmii gi structure de date fundamentale in Java, elemente care sunt Agadar, cartea nu este 0,3no EN, astfel incat V n> no avem t(n) Sex f(n)} Cualte cuvinte, Of (se cites “ordinul lu *) este muljimea tuturos functi- lor ¢ marginite superior de un multiplu real pozitiv al lu , pentru valori suf- cient de mari ale argumentuluin. Vom conveni s& spunem ed reste in ordinul Jui (sau, echivalent, reste in OG), sau t € O(f) ) chiar si atunci cénd rn) este negativ sau nedefinit pentru anumite valori n < no. in mod similar, vom vorbi despre ondinul lui f chiar si atunci cénd valoareaf{n) este negativa sau nedefnits pentra un num finit de valor ale lui in acest eaz, vom alege no Suficient de mare, astfl inet pentru n > no acest Iners s8 nw mai apard. De exemplu, vom vorbi despre ordinul lui wlog n , chiar dack pentru n=0 si n=I functia nu este definté. in loc de t € O(f), uncori este mai convenabil si foosim notaia t(n) € O(f(n)),subinelegsnd aici cin) gi fin) sunt foneti Fie un algoritm dat si fie o funeyie t : N+ (0,0), astfel inet o anumita implementare a algoritmului s& necesite cel mult o(n) unitaji de timp pentru a rezolva un caz de mirime n, unde n € N. Principiul invariajei' ne asigura atunei ci orice implementare a algoritmului necesita un timp fn ordinul lit Cu alte cuvinte, acest algoritm necesité un timp in ordinul lif pentru orice funcyie f : N ~¥ [0,00) pentas care t € O(f). In particular avem relay £€ O(t) . Vom ciuta, in general, si g8sim cea mai simplé funcye f,astfel int, te O(f). Exemplu: Fie functia t(n) = 3n? —9n+13, Pentru n suficient de mare, vom avea relatia t(n) < 4n?, in consecinfa, luand ¢ = 4, putem spune ca t(n) € (O(n?), La fel de bine puteam si spunem cd t(n) € O(13n? — V2n + 12.5), dar pe noi ne intereseaza sa gisim o expresie cit mai simpli, Este adevarat si relatia ¢(n) € O(n) dar, asa cum vom vedea mai tirziu, suntem interesai de @ margini cat mai strins ordinal de marime al algoritmalui, pentru a putea obiectiva cét mai bine durata sa de executic. Proprietajle de baz ale lui O() sunt date ca exerciti (1 - 5) si ar fi reco ‘mandabil si le studiajiinainte de a trece mai depart. TAcestpincipu afin cl dood implements df ale aceluasalgvim au dtr, cf ica, deci ol malt panto constanté muipicav. 19 92. NOTATIA ASIMPTOTICA Notatia asimptoticd defineste o relate de ordine pargiald inte functis, prin urmare, inte eficienja relativ’ a diferifilor algoritmi care rezolvé © anumiti problema. Vom da in continuare o interpretarealgebrici a nota’ asimptotice. Pentru oricare doud functii f,g : N -> 3" definim urmatoarea relayie binark: f < g dack O(f) C O(g). Relatia "< * este o relagie de ordine partial (reflexiva, tranzitiva, antisimetricd) in multimea functilor definite pe N si cu valori in [0, 0) (exercitiul 4). Definim si o relate de echivaleni@: f = 9 daca O(f)=0(g). Prin aceasti relate objinem clase de echivalenta, 0 clasd de echivalenta cuprinzind toate functile care diferd intre ele print-o constant rmaltiplicativa De exemplu, gn = Inn si avemo clasa de echivalenga a functi- ilor logaritmice, pe care 0 notim generic cu Offog n) . Notand cu O(1) clasa de cchivalent a algoritmilor cu timpul marginit superior de o constanta (cum ar terschimbarea a dow’ numere, sau maximul a tri elemente), ierarhia celor mai cunoscute clase de echivalengi este: 0(2) c O(logn) c O(n) ¢ O(ntogn) ¢ O(n?) ¢ O(n8) ¢ O(2") Aceasti ierarhie corespunde unei clastic a algoritmilor dupa un exteria al performanjei. Pentcu o problem dats, dorim mereu si objinem un algoritm corespunzitorunei clase aflate c&t mai “de jos" (cu timp de execute ct mai mic). Astfl, se considerd afi o mare realizare dack in locul unui algoritm exponenyial gisim un algoritm potinomia. Exerciiul 5 ne di o metods de simplificare a calculelorin care apare notaia asimptticd. De exemplu: n+ 4n? + 2n-+7 € O(n? + (4n? + 2n +7) = O(maz(n', An? + 2n +7) = O(n) Ultima egalitate este adevirati chiar dack maz(n®,4n? + 2n +7) # n® pentri 0 0,3ng EN, astfel incat V n> np avem tn) > c+ f(n)} Existd o anumiti dualitateintre notajiile O() si Of): pentru dous functi oarecare f,g : N > [0, 00), aver F € O(g) daci si numai dacd g € Mf) O-estimare foarte precisa atimpului de exccuie se objneatuncicndtimpul de executie al unui algoritm este limitat atat inferior cat si superior de cate un tulip real pocii al aceleag fei. fn acest scop introducer nota: Of) = OF) NAA) numiti ondinul exact al lui f- Pentru a compara ordinele a doua functii notajia © nu este ini mai putemicd decat notaia O, in sensul c& OY)=Ot¢) este echivalent eu O(f) = 0(4). Exist situati im care timpul de exeeufie al unui algoritm depinde simaltan dle mai mult parameti, Aceste situa sunt tipice pentru anumit algoritmi care opereazi cu grafuri si la care timpul depinde atit de numirul de varfuri ct si de numarl de muchii. Notajiaasimptoticd se generalizeazA in mod natural si pentru functii cu mai multe variable. Astfel, pentru 0 funeiiearbitrara f Nx N= [0, 00) definim O(f) = {t:N x N— (0,00) | 3e > 0, no, mo € N, astfel incat V m2>mo,¥ n>no avem t(m,n) < e+ f(m.n)}. Similar se objin gi celelalte generalizi 9.3 Tehnici de analiza algoritmilor [Nu existi o metodé standard pentru analiza eficienjei unui algoritm. Este ‘mai curind 0 chestiune de rajionament, intuijie $i experien{a. Vom aria pe bari de exemple cum se poate efectua o astfel de analiza. 93.1 Sortarea prin selectie Considerim algoritmul de sortare prin selectia minimului, reprodus mai jo: 9.3 TBHNICI DE ANALIZA ALGORFTMILOR pentrui =1,n-1 ‘Yhe caleuleaza poritia minimului lui a(i),a(é +1),-..,a(n) PozMin € i /initaliziom minimul cu indicele primului element pentruj=itin ‘dacd a(j) < a(PozMin) atunci PozMin = j sfarsit daca first pentru Maupaj Mse aseazii minimul pe pozitia i aur = a(i) a(i) € a(PozMin) a(PozMin) + auz sfarsit pentru dupa i Timpul necesar pens o singurs execuie a eicului pentru dupa variabils j poate fi mirgint superior de o constanté «In total, pent un Bixat, indnd font de fatal sult b-+ a(n ~ 4) uni, unde beste o constant reprezentind timp pent iniializarea buclei,O singurexecoie a bucleienterioare ae loc in cel mult e-+b-+ a(n ~ i) unity de imp, unde eesteo alté constant. Tinnd cont de faprl cd bucla dup j se realizeazt de n- ori timpul total de execusie al algoritmutu este cel mut: d+ DiS (c+b+a(n—i)) se realizeazi n-i iterafi, acest ciclu necesita un timp de cel Uniti de timp, d find din now o constanti. Simplificdm aceasté expresie gi cobjinem $n? + (b+.e— $)n-+ (d— ¢~}), de unde deducem ci algoritmul necesiti tn timp in O(n). analiza similar asupra imiteiinferioare aac cc timpol este de fapt in @(n2). Nu este necesar si considerim cazul cel mai nefavorabil sau cazul mediu deoarece timpul de executi al sorte prin select este independent de ordonarea prealabili a elementelor de sot. fn acest prim exemplu am analizat tate detaliile. De obicet inst, detalii cum af fi timpul necesar inijializarii ciclurlor nu se vor considera explicit, deoarece ele nu afecteazA ordinul de complexitate al algoritmului. Pentru cele ‘mai multe situfi, este sufcient si alegem o anumit& instrucjiune din algoritm ca baromeiru sisi numirim de cite ot se executéaceast instrejiune. in cazul nosteu, putem alege ca barometeu testul ali] < ofPozMin] din bucta interioari, Este ugor de observat ck acest test se executi de 25-2 2 93, TEHNICI DE ANALIZA ALGORITMILOR 93.2 Sortarea prin insertie ‘Timpal pentru algorismul de sortare prin insertie este dependent de ordo- narea prealabili a elementelor de sortat, Algoritmul este implementat in cadrul primului volum, la capitolul Mogtenire, sectiunea Extinderea clasei Shape. A~ naliza algoritmului se realizeazd pe baza implementisii prezentate tn cadrul acelei sectiuni, Vom folosi comparayia tmp.lessThan(alj - 11) din cichl for ca barometr, ‘Si presupunem ci p este fixat si fie n = alength lungimea sirului, Cel ‘mai nefavorabil caz pare atunci cind trap < alj — 1] pentra fiecare jintre p si 1, algoritmul ficdnd fn aceastd situa p comparayii. Acest leru se intim- pla (pentru fiecare valoare a lui p de la I la n ~ 1) atunci efnd tabloul a este inigial ordonat descresedtor. Numarul total de comparagii pentru eazal eel mai nefavorabil este: Dit i= EY € O(n") Vom estima acum timpul mediv necesar pentru un caz oarecere, Presuptnem cltclementeletaloului a sunt distinct sie orice permutare alo are aceasi probabilitate de aparitie, Atunci, daci 1 < k < p, probabilitatea ca alp] si fie cel de-al k-lea cel mai mare clement dintre elementele a{1],a[2),...,alp] este 4. Pentra un p fixat, conditia alp] < alp — 1] este falsi cu probabilitatea 4, deci probabilitatea ca si se execute comparatia "tmp < alj — 1]" o singurit dati inainte de iesirea din bucla while este . Comparatia "tmp < alj ~ 1)" se executi de exact doud or tot cu probabilitatea 1 ete, Probabilitatea ca si se execute comparaia de exact p— 1 ori este 2, deoareceaccasta se inp at cind tmp < af0] eit i céindaf0] < tmp It (n> 0) . ot 5 hanoi(n = 1, 1,6 = 1 = 05 ‘ System. out. printin(i # "5" + 3): 9 hanoi(a— 16— ij. 1s so ” Pentru rezolvarea problemei inijiale, facem apelul anol (64, 1, 2): m4 94, ANALIZA ALGORFTMILOR RECURSIVL Considerim insrucjiunea print Ln ca barometr. Timpul necesar agri aula este exprimat prin umtoarerecurengh 1 dict n=1 an) teeter doch n>1 Vom demonstra ci t(n) = 2" — 1, Rezulti ch t € ©(2") Aces algoritm este optim in sensul ef este imposibil si mutim discuri de peo ji pe alta cu mai putin de 2" ~1 opera Penta a muta 64 de discur vor fin consecingknecesare un numir astronomic de 2 opera. Implementarea ‘riarelimbaj de programare care admit exprimarea recursivi se poate face aproape in mod direct. 9.4 Analiza algoritmilor recursi ‘Am vzut in exemplul precedent eft de putemic’ si in acelasi timp eft de elegant este recursivitatea in elaborarea unui algoritm. Cel mai impor: tant cigtg al exprimiit recursive este faptl ck ea este natural gi compacta, fick st ascundS esenqaalgoritmului prin detalile de implementare. Pe de alti pare, apelurile recursive tebuie folosite cu dscemnimént, deoarece solicits st ele resursele calculatoralu timp 3% memorie). Analiza unui algortm recurs implied aproape incotdeauna rezolvarea unui sistem de recurene. Vom vedea in continuare cum pot frezolvate atfel de recurenge.Incepem cu tehnica cea mai simpli. 9.4.1 Metoda iteratiei Cu pusind experieng si inmisie putem rezolva de multe or asfel de 1e- curenye prin metodaiterajie: se execu primii passe intueste forma genera- 1 iar apoi se demonstreazi prin inducie matematica ct forma este coretd. Si considerim de exemplu recurena probleme tumusilor din Hanoi. Se observ’ ciipentra a muta n discuri este necesar si mutim n — 1 discuri, poi si muti un dsc in final din nou n ~ 1 discui i consecin,pentro un anumit n > 1 objinem suceesiv: t(n) 2-141) + D732 2e(n-1) +1 =2e(n-2) +241 = Rezulti ci t(n) = 2” ~ 1, Prin inducjie matematicy se demonstreazat acum cou usuringi cd aceasta forma general este corectd. 25 94 ANALIZA ALGORFTMILOR RECURSIVI 9.4.2 Induetia constructiva Induefia matematicd este folosita de obicei ca tehnick de demonstrare a unei asertiuni deja enunjate. Vom vedea in aceasti secjiune ed inducyia matematicd poate fi utilizaté cu succes si in descoperirea parfalt a enunjului asertunii, A- plicind aceasti tehnicd, putem simultan si demonstrim o aseryiune doar paral specificati si si descoperim specificaiile care lipsese gi datorta cirora aserti- tunea este corecti, Vom vedea el aceasta tehnic’ a inducfiei constructive este utilé pentru rezolvarea anumitor recurenfe care aparin contextul analizei algo- ritmilor. incepem cu un exemplu, Fie functia f : N+ N definita prin recurenta: 0 dacs n=1 Fn) -{ f(n—1) +n altel ‘Si presupunem pentru moment cf nu stim c& f(n) = Aven Sn) = Digi s Don = 0? sideci f(n) € O(n?). Aceasta ne sugereazi si formulim ipoteza inductiei specificate partial IISP(n) conform cireia f este de forma f(n) = an® +n + ¢. Aceastipotezi este parjalé in sensul c& a, b si nu sunt inc8 cunoscute ‘Tebnica inductici constructive const in a demonstra prin inducyie matematic aceasta ipotezA incomplet sia determina in acelagi timp valorile constantelor necunoscute a,b si Presupunem ca /ISP(n-1) este adevarata pentru un anumit n > 1. Atunci, S(v-1) = aln—1)?-40(n—1) +e = an?-+(1+b—2a)n-+(a—b+c). Dac dorim ‘si aritim c& //SP(n) este adeviratd, trebuie sit artim c& f(n) = an? + bn +e. Prin identiicarea coeficienilor puterilor lin, objinem ecuagile 1+b— 2a = sia—b+ 4, ¢ putind fi oarecare. Avem acum 0 ipotezd “mai completa” (abuzul de limbaj este inevitabi), pe care © numim tot ISP(n), f(n) = 3 + $ +c. Am ardtat ci dact IISP(n-1) este adevaratt pentru un anumit n > 1, aunei este adevarat si ISP(n). Ramane s8 artim eX este adevirata si ISP(0). Trebuie si aritim c& (0) = a0? + 60 +c. Stim ck $(0) = 0, deci HSP(O) este adevatati pentru c = 0, In concluzie am demonstrat, ci f(n) = % + 2 pentru orice n. 9.43 Recurente liniare omogene Exist din fericite gi tehnici care pot fi folosite aproape automat pentru a re- zolva anumite clase de recurenje. Vom incepe prin a considera ecuaii recurente liniare omogene, adic& ecuafi de forma: 26 94, ANALIZA ALGORFTMILOR RECURSIVL Aoty + Oita tes FOKtnk =O (*) unde t; sunt valorile pe care le c&utm, iar coeficientii a; sunt constante ‘Conform intuijiei?, vom céuta solugi de forma: ty =a" unde x este o constant (deocamdati necunoscut). Dac inlocuim aceasti solufie in ecuagia (*), objinem gz” + aya"! +... aga Solufile acestei ecuapi sunt fe solugia trivial. fie solusile ecuatie ), care nu ne intereseazi, agat + aye! +. tay = ‘care se numeste ecuafia caracteristicd a recurentei liniare si omogene (*) Presupundnd deocamdati ci cele kridacini r1,r2,...,1p ale acestet ecuafi ccaracteristice sunt distincte, se verificd ugor cd orice combinafie iniari te = Dh er? ste o solutie arecurenjei (*) unde constantele cy, ¢2,..-,¢k sunt determinate le. Se poate demonstra faptul c& (*) are solujii numai de aceasta forma. ‘Si exemplificim prin recurenja care defineste iru! lui Fibonacci ty = tat + tran 22 jar to = 0,, = 1 . Putem si rescriem aceasti recurena sub forma ty tra tha =0 ‘care are ecuafia caractersticd 0 uridine ria = 53, Sotuia general are forma tart terk De fp, adel este ac au et vorba de intuit, i de experent. 94 ANALIZA ALGORFTMILOR RECURSIVI Impundnd condigile inifiate, fo = 0,f, = 1, obginem ate =0n=0 an ter =1n de unde determinm os Deci, ty = Jp(rf +18). Observim cd ny = g,72 = Gs objinem: ye -(-") care este cunoscuta relate a lui Moivre, descoperitala inceputul secolului XVII Na prezinti nici o dificultate si aritim acum ed timpul pentru ealeulul recursiv al sirului lui Fibonacci este in @(¢"). ‘Cum procedim ins atunci cénd ridacinile ecuatici caracteristice nu sunt distincte? Se poate arita cl daca r este 0 ridicin’ de mulkiplicitate m a ecuati caracteristice, atunci tn = 1" ,tn in = Posty = EM su solufii pentru (*). Solujia generali pentru o astfel de recurenfa este atunci ‘© combinatic liniara a acestor termeni si a termenilor proveniti de la celelalte idicini ale ecuafiei caracteristice. Din nou, sunt de determinat exact k con- stante din condifile inal. Vom da din nou un exemplu. Fie recurenja by = Stn ~ Blna2 + Atma cu to = 0,th = 1, ta = 2. Ecuatia caracteristicl are eidacinile | (de multiplici- tate 1) $i 2 (de multiplicitate 2). Soluyia generald este: 4 ex" +02" + end" Din conditile initiale, objinem ey = ~2,e2 = 2,3 9.4.4 Recurente li Considerim acum recurenje de urmatoarea forma mai general are neomogene Gotn + ditn—a + ++ Oetn—n = W*p{n) (**) 28 94, ANALIZA ALGORFTMILOR RECURSIVL unde b este o constant, iar p(n) este un polinom in n de grad d, Idea general’ este ca prin manipuliri convenabile si reducem un astfel de caz Ia o forma omogeni, De exemplu, 0 astfel de recurenga poate fi ty — 2p fn aces caz b = 3 si p(n) = 1 un polinom de grad 0. O simpli manipulare ne permite sf reducem acest exemplu la forma (+). inmulfind recurenja cu 3, objinem: Btn — Gta = 3"? fntocuind pe m cu n + 1 fn recurenja original avem: thei — Qty = arth fn final, setdem aceste dou ecuat si obginem tag — Btn + Bty. Am objinut o recurenta omogent pe care 0 putem rezolva ca in secjiunea precedenti, Ecuatia earacteristica este 2252 +6=0 adici (2 — 2)(2-3 Intuitiv, observm c@ factoral (2 — 2) corespunde parti stingi a recurenfe originale, in timp ce factonal (2 — 3) a aparut ca ezultat al manipulator efee- tuate pentru a scipa de partea dreapta Tati un al doilea exemplu: ty Mn in +5)3" Manipalarile necesare sunt putin mai complicate. Tebuie si: 1. fnmutyim recurenja cu 9; 2. ilocuim in recurenga pe meu n +2 3. fnlocuim in recureny pe n un + 1 gis tnmullim apoi eu -6 Adunfind cele tei ecuatii objinute anterior aver: 94 ANALIZA ALGORIFMILOR RECURS! tng2 — tng + 2ty — 18,1 = 0 ‘Am ajuns din nou la 0 ecuafie omogen’, Eeuay cearacteristic corespunzi- 82? +212 — 18 adiex (2 — 2)(— 39°. inci o dati, observim ed factorul (x — 2) provine din partea stingi a re- ccurenjei originale, in timp ce factorul (z ~ 3)* este rezultatul manipula Generalizind acest procedeu, se poate arita c& pentru a rezolva (**) este suficient si um urmatoarea ecuayie caracterisic (agz* + a,x! +... +a4)(2 — 441 = 0 Odati ce sa objinut aceasti ecualie, se procedeazi ca in cazul omogen. ‘Vom rezolva acum recurenia corespunzitoare probleme’ turnurilor din Hanoi ty = 2p t1n>1 iar fo = 0. Rescriem recurenja astfel ty — tna = 1 care este de forma (+*) cu b= 1 sip(n) = 1, un polinom cu grad 0. Ecuayia ccaracteristici este atunci (x — 1)(x — 2), cu sotutile I si 2. Solutia generali a recurenfei ese: th =e +02" ‘Avem nevoie de dou’ conditiiiniale, Stim c& to = 0; pentau a gisi cea de-a doua conditie caleulam 4 tot m1, Din condigile inifiate, objinem tn Observaie: daci ne intereseaza doar ordinul lui ta, nu este necesar i calk culim efectiv constantele in soluyia general. Dacd stim cl ty = e,1" + 622", rezulti ct € O(2"). Din faptul cf mumiral de mutaei a unor discuri nu poate fi negativ sau constant (deoarece avem in mod evident ty > n), deducem ci 2 > 0. Avem atunci ty € (2%) si deci ty € @(2"). Putem obtine chiar ceva ‘mai mult ‘Substituind solutia generala inapoi in recurenfa originara, gsi 1=ty—2ty ey +022" — (cy +22") Indiferent de conditiainigal, cy este 1 30 94. ANALIZA ALGORITMILOR RECURSIVL 9.4.5 Schimbarea variabilei Uneori putem rezolva recurenje mai complicate prinino schimbare de vai- abitd. fn exemplele care uemeazs, vom nota cu 7(n) termenul general al re- curenei si cu ty termenul noi recurenge objinute print-o schimbare de vari- abili. Presupunem pentru inceput cm este o putere a lui 2 Un prim exemplu este recurenja T(n) =4T() +n >1 {in care tnlocuim pe m eu 2*, notim ty = T(2*) = 7(n) si objinem th = Ate +2" Ecuatia caracteristicd a acestei recurenye liniare este (conform paragrafului anterior): (2-4)(2-2)=0 sideci ty = c14¥ + 622, Inlocuim pe k cu Ign T(n) =eyn? + ean Remulti ch T(n) € O(n? | nesteoputere alui 2), Un al doilea exemplu fl reprezinté ecuayia T(n) =47(3) +n2,n>1 Procedind la fel, ajungem la recurenja te = Ate +4 cu ecuafiacaracteristic& (e- 4) =0 si solufia general ty = c14¥ + exkA, Atunci, T(n) = crn? +ean? Ign si objinem c& T(n) € O(n? logn | nesteoputereatui?) fn fine, sk consideram st exemplul a 974 ANALIZA ALGORFTMILOR RECURSIVI T(n) =37(3) +en,n >1 ¢ fiind 0 constants, Objinem succesiv T(2*) = 37 (2-1) + 2 th = Sta +2 cu ecuafia caracteristicd (e~3)(@-2)=0 te =a3' +e,2* Pin) = 43!" +n $i, deoarece als) = yao obyinem T(n) = ern! +e.n deci, T(n) € O(n'¥? | neste oputere atu 2) {In toate aceste exemple am fost notafia asimptotica conditionata. Pentru 4 arita ci rezulatele objinute sunt adevirate pentru orice m, este sufcient si adiugim conditia ca T(n) si fie crescatoare pentru n > No. Putem enunjaacum o proprietate care este ui caret pent analiza algo- ‘tmilor eu recursivitati de forma celor din exemplele precedente. Proprietatea, acirei demonstrareo lism ca exercifiu este foarte util Ia analiza algoritmilor Divide et Impera, Propozije. Fie T : N~> RY o functie nedescrescitoare T(n) = a (3) +ent,n > no unde ng > 1, > 2 si k > 0 sunt intregi, a gic sunt numere reale pozitive, iar Beste o putere a lui b. Atunci aver: (nt) daca < be Tin) € 4 O(ntlogn) dach_a=b* (niles) daca >be 2 95. IMPLEMENTAREA ALGORITMILOR 9.5 Implementarea algoritmilor ‘Am considerat utili prezenja la sfirgtul capitolului a implementisilor Java pentru problemele prezentate pe parcursul acestui capitol. Este cazul algorit- milor de sortare prin selecfie, a celui de sortare prin insergie gia algoritmulut ‘urnurilordin Hanoi Listing 9.2: Implementarea algoritmului de sortare prin selecjia minimului import java-io.es slmport to-Reader: tie So Sortare prin selectia minimului lic class SortareSelMin /e* Ordonarea prin selectia minimulul.+/ bite static void ordonare (int {] a) ( for (int i = 0; 4 < astength — ie) fi int_pozMin for (int j= i #1; j 0) RR Camp < al) — ID: i » ot > aU = at - 01 a , > aly) = imp: so = 2B /es Programul principal.+/ public static void main(String [] ares) > > | Hettirea elementetor siratut hs System-out. printin("Tntroduceti elementele sirului" + s "" (pe-aceeasi linie, separate prin spatiu):"): > Unt (5 = Reader, readintArray Qs % ordonare(s): 95. IMPLEMENTAREA ALGORITMILOR » Hafisare reculiate % — System-out.print("Sirul ordonat este: *) fer (int i= 0; 1 < sylength; 144) rn fb Systemout. print (sil +" oy System. out.printin Q) : oy “) Listing 9.4: Implementarea problemei turnurilor din Hanoi Import java-io.e: Hmport io. Reader; 3 8 Turmurite din Hanoi Spublie class Hanoi a +) fae Implemensarea algorismului “Turnurite din Havol”. +/ SS public statle void hanoi(int -n, iat i, ime j)) ad 5 i (0) » ot he hanoi(m = 1, 1, 6 1 js 's System: our. printinGi + * + De Me hanoi(n = 1,6 = i = J. ie sy a 3 fee Programul principal. +/ public static void main(String (] args) af b System-outprint("Tntroduceti umarul de diseuri: *): Int 9 = Reader. readint Os apelut metodei hanoi » — hanoi(n, Ty 2): 4 ” Rezumat Capitolul de fay a realizat o scurtiintroducere in domeniul vast al analizei algoritmilor. Ideea cea mai important care reiese de aici este c& algoritmii 35 915 IMPLEMENTAREA ALGORFFMILOR utilizayi afecteaza timpul de execusie al unui program mult mai drastic decdt antficile de programare, Algoritmii care au un timp de lueru exponengial nu sunt in general aplicabili pentru date de intrare de dimensiuni rezonabile, spre R* definim urmitoarea relate bi- nari: f < g dack O(f) C O(g). Demonstrati ct relajia"<" este o relayie de ordine partiali in muljimea functilor definite pe N si cu valori in R Indicayie: Trebuie ardiat ci relajia este reflexiva, tranzitiva si antisime- tricd. Tineji cont de exercigil 3 5. Pentna oricare dou funciif,g : N > R'demonstrayi ci O(f + 9) = Ofmact( f,g)) unde sum si maximal se iau punctual. 6. Fie f(n) = aman +... + an +9 un polinom de grad m, cu > 0 Aritayi cd f € O(n), 1. Consideram afemasia O(n?) = O(n + (n? —n8)) = Ofmaa(n®,n? — n3)) = O(n). Unde este eroarea? 8, Consideram afirmagia 37? Olmaz(1 +2+...+n)) =1424...4n€ O1424...4n) = O(n). Unde este eroarea? 9, Pentru oricare doua functii f, Q(f +9) = O(maz(f,9)) se iau punctual, :N—+ RY demonstrajict @(f)+ O(a) nax(@(f),@(g)), unde suma si maximul 10, Analizajieficienja urmatoriloralgoritmi: (a) pentmn i=1.n enim j=1,5 {operajie elementari) () pentru i=1,n entra jel i+ {operat elementari) (©) pentru enim j=1,6 penta k=1,n {operatic elementari (@ pentru enim jel pentma k=1.n Loperatie elementari 11, Construiji un algoritm cu timpul in @(n log n). 38 95. IMPLEMENTAREA ALGORITMILOR 12. Fie un algoritm: pentru i=O.0 jet cittimp j<>0 ie idiv2 Gasiti ordinul exact al timpului de execute, 13, Rezolvaji urmatoarea recurenja: ty — Bty1 — 4ty2 = On > 2eu Ot 14, Care este timpul de executie pentru un algoritm recursiv cu recurenja: ty = tna tn? Indicatie: Se ajunge la ecuatia caracteristica (2 — 2)(w — 1)? = 0, iar solujia generald este ty = ¢,2" +21" +cgnl”. Rezultd ed ty € O(2"). Substituind solufia generala in recurenta, objinem ca, indiferent de con- ditia initiald, c = —2 si cg = —1. Atunci, toate solutile interesante ale recurenei trebuie st aibet cy > 0 si ele sunt toate in (2%), deci in O02"), 15. Siise calculeze secvenja de sum’ maxima, formati din termeni consecu- Livi, ai unui sir de numere, 39 10. Structuri de date Nu potiobtine intotdeauna ceea ce ores, dar, dact inerei, uneori vei objine ceca ce ai nevoie ‘Autor anonim oui programe care rezolvié aceeasi problemi pot si arate complet diferit. Unul poate fi extrem de lizibil, concis si ugor de modificat pentru a se adapta la rezolvarea unor probleme aseminitoare, iar celilalt poate fl impenetrabil, ‘obscus, interminabil si dificil de modificat. Cele dou’ programe pot si difere atit de mult in ceea ce priveste durata de executie si necesarul de memorie incdt, pentru un anumit set de intrare, unul furnizeazi rispunsul dupii 2 secunde, iar celilalt dupa céteva secole! Experienja a demonstrat c& aceste diferenge sunt generate de structura pro- ‘gramului side structura datelor. Programele sunt scrise pentru a rezolva probleme reale, Structurarea pro- _gramului imparte problema si solujia ei in componente mai simple si mai ugor de injeles. Informatia care trebuie procesati este refinuti in structuri de date (Cablouri, inregistrar, liste, sive, arbor, figere ete.), O structura de date gru- peazii datele, O structuri de date aleasi adecvat poate face operajile simple gi cficiente, iar una aleas neadecvat poate face operafiile alambicate gi ineficiente ‘Structurile de date congin informatie asupra clreia se opereaza in timpul ex- ‘ecufiei unui program. Despre programe obignuim si spunem c& procesea’ in- formajie,cind, de fapt, ele proceseazi structuri de date. Astfel, nu mai pare sur- prin2itor faptul c& structura datelor sia programelor sunt extrem de importante si cl ele trebuie corelate corespunzitor pentru a programa cu succes. Asimi- larea cunostinjelor legate de structuri de date gi algoritmi,alaturi de stipanirea conceptelor fundamentale ale programirii orientate pe obiecte, ii permit pro- ‘gramatorului si menjind o suprematie regal asupra programelor, astfel incdt 40 Figura 10.1: Inchiderea datelor intro cutie neaged. Datel pot fi accesste doar prin invocarea unei opera permis. Cutie neagrd Rezultat permisé operatie acestea si riména lizibile, usor de intrefinut si eficiente, chiar si atunci cind ‘erese in dimensiune. Atat programele edt si datele au o anumiti structurare gi att structura pro- ‘gramului efit gi a datelor trebuie si fie adeevath problemei de rezolvat. Vom urmaci si prezentim structurile de date nu ca un subiect teoretic izolat, ci ca pe un instrument esengial al procesului de rezolvare a problemelor care conduce la ‘rearea de programe eficient. Structurile de date sunt importante, deoarece modul in care programatorul lege si reprezinte datele afecteaz’i in mod semnificativ clartatea, concizia, viteza de executie si necesarul de memorie al programului. in acest capitol, et sin cele care urmeazi, vom prezenta cum si folosim diferte structuri de date Pentru a crea programe corecte gi eficiente. Vom vedea ci operafile care tre- buie realizate asupra datelor sunt cele care determing care este cea mai potriviti, structuri de date care trebuie folosit Dezvoltarea de programe este dificil, mai ales atunci cAnd este fut fri nici un fel de strategie, Progamarea orientata pe obiecte, prezentata in prima parte a lucrari, usureaza mult dezvoltarea programelor si conduce la programe bine structurate, Ea consti in impaijirea atenti a unei probleme complexe in componente mai simple a cAror interfafi este apoi cu usurinj& combinati pentru a rezolva problema initial, Abstractizarea datelor const in a trata o colecjie de date extrigind aspectele sale esengiale, ignorind pe eat se poate detalile. Abstractizarea datelor reduce datele la o colectie gi la operajiile cate se pot realiza asupra acestei colecti Efectul este ca $i cum colecjia de date ar fi inchisi ints-o cutie neagr (black box) impenetrabil,singurul mod de a accesa datelefiind invocarea uneia sau ‘mai multor operafii permise (Figura 10.1). 41 Modul in care datele sunt agezate in acea cutie neagr gi modu fn care ope- raile se executi devin detalii irelevante!. Astfel de detalii determina eficienta progeamului, dar nu ii afecteaza stuctura logics “Abstractizareadatelortrebuie privitd'mai degrabacao facilitate care ugureaza efortal de programare, si nu ca 0 noua constringere in privinfa stilului de pro- gramare. Pentru a injeloge mai bine aceste noyiuni, si vedem cum poate fi definitasimplitica o stivi ca tip abstract de date. Stiva este o colecic de date omogene (de acelagi tip) asupra cdreia se pot realiza urmatoarele opera: ‘© PUSH) - are ca efect depunerea ui X pe varful stivet; # POP(X) - are ca efect incdircarea valorii din varful stivei in parametrul X sicliminarea fli stivei, Modul in care cele dous operaii (PUSH si POP) sunt implementate gi modal in care datcle sunt refinute in stv (stati, inlinfut ete.) nu trebuie si transpari utlizatoruluis pe el pur si simplu nu trebuie si il intereseze acest luera. Este exact ca $i curentul electri: atunci eénd actionim comutatorul de la veiozs, stim eX becul se va aprinde; care este procesul prin care filamentul becului se {ncinge si emite mind nu ne priveste. Tot astel, i istele, cozile, arbor binart {mpreund eu operafile care se fae asupra lor pot ft privite ca tipur abstracte de date ‘Unui tip abstract de date muljime putem si-i asociem operagii cum ar fi reuniune,intersectie, dimensiune, complementard. intro alt situa, putem ‘avea nevoie numai de operatorii de reuniune si apartenenya, care definese un alt tip abstract de date (TAD), cate poate s& aiba o cu totu alté organizare intern, new Object [DEFAULT_CAPACITY }: 1 Je Adauga elemental x in stiva.sf 3 pabite veld porn onject x) s ‘ If (topPosition zt 3 | increarestacksize (0: a elements length — 1) elements [+stopPosition | = x3 nd few Mareste dimensiunea (capacitatea) stivel ex 102. stive + DEFAULT_CAPACITY atunci cand stiva este plina. */ Private void increaseStackSize () ‘ Object {)_newStack DEFAULT_CAPACTTY }: yew Object {elements .Jength + Ueopiem elementele in noua stiva for (Int | = 0: | < elements length: i++) i ) newStack[i] = elements [i]: Melements devine nowa stiva elements = newStack: 1 fue Extrage elemental din varful stiver. «/ Public vold pop() throws, UnderflowExcepiion ( 1 Cisempty 0) i throw ’ UnderflowException ("Stiva vida”) topPosition—-: 1 Jee Returneaza elementul din varful stivei © (uttimal adaugat).+/ Public Object top() threws, UnderflowException ( IF Cisempty 0) i throw ) UnderflowException ("Stiva vida.” return elements [topPosition |: 1 (ee Returneaza elementul din varful stivet si it elimina apoi din stiva.+/ public Object topAndPop() throws UnderflowException, ( i isEmpty 0) a throw new UnderflowException ("Stiva. vida") ) return elements [topPosition 1 49 12. srive SS /es Verifiea daca stiva ¢ vida. 4/ return topPos: a & /es Elimina toate elementele din stiva. «/ public vold makeEmpty() ot % | topPosition = -1 wo “1 Listing 10.6: Exempla de utilizare a stivei. Programul va afiga: Conjinutul stivei este 43.210 simport_datastructures dimport exceptions -+ s/ae Clase de tes! simpla pentru 0 stiva, care adeuga 5 numere ts dupa care le extrage in ordine inverse */ Spublic class TestStack “ > public static void main(String (a oe + Stack $= new StackAr(: — Hintroducem etemente in stiva for (int i= 0; 1 <5; 144) » Has push(mew Integer (i))5 soy 5 Yscoatem elementele din stiva si te afisam System.out. print(*Continutul stivei este: "): mony » 1 a fer Gs) a t e System. out. print(s.topAndPop() + * *) x , % cateh(UndertlowException we) > 1 sd > ” 13. cou Figura 10.3: Modelul unei coi: adugarea la coada se face prin enqueue (), accesul prin get Front (), stergerea prin dequeue () ‘enqueue ‘dequeue, getFront Queue 10.3 Cozi © alt structra simp de date este coada, n multe situa este important si avem acces gisau si stergem ultimal element inserat. Dar, intr-un numa la fel de mare de stvati, acest lucra nu numa cd nu mai este important, este chiar nedorit, De exempt intro rea de calculatonre care au acces lao singurd im- primani este normal ca daci in coada de aseptare se afd mai multe documente prea fitipart,priortatea si fie acordaté documentali cel mai vechi. Acest Ivers mu numai ea este core, dar este gi necesarpentra a garanta c& documen- tul nu astcapt la infnit. Astfel, pe sstemele mar ese normal se floscasca cori de tipi Operaile fundamental suporate de cori sunt «© enqueue -inserarea unui clement la capitul cozii; + dequeue - stergetea primului element din coada, © getFront - .ccesul la primul element din coads, Figura 10.3 ilustreazi operajile pe 0 coadi. Traditional, metodele de- queue () si getFront () sunt combinate intr-una singura. Prima metoda retumeazit primul element, dupi care il scoate din coada, in timp ce cea de-a ddous returneaza primul element Pri 2-1 scoate din coads. Implementarea structurii de coadi este aseminatoare pind la un punct cu cea a stivei. Coada pastreaza elementele intrun gir de obiecte eu o capacitate initial, iar dacd prin adiugiri repetate aceasti capacitate este atinsl, atunci ea vva fi mariti automat. Spre deosebire de stiva, coada are doi indici care indies poziiile de inceput si de sfarsit ale cozi Listing 10.7 ilusireazX interfaa pentru o coadi, in timp ce Listing 10.8 pre- inti o implementa a interfejei anterioare, bazati pe giruri. Spre deosebire de sl 103. cou stivi, in care adiugarea si extragerea unui element au loc Ia acelasi capt, in azul cori adiugarea are loc la final, dar stergerea se face de la inceput. Astfel, pentru a putea utiliza sirul element s la intreaga lui capacitate,elementele lui ‘sunt privite “circular”, ca si cid ultimul element ar fi legat de primul. Listing 10.7: Interfaya pentru coud’ «package datastractures Simport exceptions .¢: i/es Interfata peniru 0 coada. Expune metode pentru adeugarea Ss unui element, stergerea primului element, consultarea G2 primulut elemento! Spublic Interface Queve ut + public vold enqueue (Object x): i public Object getFront () throws UnderflowException : 5 publte Object dequeue () throws UnderflowException : 5 public boi public void makeEmpty 0: “" an isEmpty 0) Listing 10.8: Implementarea unei structuri de package Hmport exceptions .+; t/a Implementarea unel cozi folosind un tablow. +/ Spublic class QueucAr Implements Queve at fos Tablon care retine elementele din condas! {private Object {] elements ¢ fx Indicele primulut element +/ private Int front: fax Indicele ultimului element +/ h private int. back: hh fee Dimensiunea cozit +/ ho private Int currentsize fee Mumare! de elemente elocat initial pentru coada+/ ‘private final statte Int DEFAULT.CAPACIFY = 10; WN feeConstructor care aloca memorie pentru clementele cozit te si seteaza valorile atributelors/ public. Queuear() a elements = new Object [DEFAULT CAPACITY }; 2 13. cou smakeEmpty (): 1 fen Intoarce true daca este vidas! Public boolean isEmpty () t return currentSize 1 o Je Adauga elementul x in coada. +f public veld enqueue (Object x) t in (curcemtsize fi ’ elements . length ) increaseQueuesize() bback = increment (back ); elements [back] =X! currentSize +4 1 fos Blimina toate clementele din conde. +/ public veld makeEmpty Q ( currentSize Front = 0 back 1 (es Bstrage primal element din cadral cozit sGihrows UnderflowExeeption daca coada este goale+/ Public Object dequeue) throws UnderflowException ( ie Cistimpty 0) i ) throw new UnderflowException ("Coads vida"): currentSize——3 Object returnValue = elements {front }: front = inerement (front) 1 rotuenVelue : /es Intoarce primul element din cadrul cozii SOthrows UnderflowExeeption daca coada este goale./ Public Object getFront () throws UnderflowException ‘ 3 103. cou > Af GsEmpty O) ut throw new UnderflowException ("Coada vida"); soy % return elements {front}; 4 ts Incrementeaza circular indicele din conda. «/ S private int increment (int x) ot Sf (44x == elements length) So x= on ean . No /ex Incrementeaza dimensiunea cozii cw DEFAULT-CAPACTIY atunci & private void increaseQueueSize() Si % Object {] newQueve = new Object elements length + %DEFAULT.CAPACITY |; for Cint 4 = 0; i < elements tengths 144) mf i -newQueve[i} = elements [4]: i" front = increment (front }: mo} elements = newQueve: ™ front > back = currentSize — 1 i) Exercifiul 3 propune o a doua modalitate de a implementa aceasta interfati, si anume cu ajutorul listelor, care vor fi prezentate mai tirziu in cadrul acestui capitol. Listing 10.9 prezinti modul de utilizare a covii. Deoarece operatile pe ‘6 coadi sunt restricjionate int-un mod asemiinitor eu operafile pe o stivi, este de asteptat ca gi aceste operafii si fie implementate inte-un timp constant, Inte adevir, oate operajile pe o coada pot fi implementate in timp constant, O(). 34 Listing 10.9: Exempla de uilizare a cozii. Programul va afiga: Conjinutul coz este: 01234 vimport datastructures +; Hmport exceptions -+ d/ae Clasa simpla de test pentru 0 coada. Se ada t+ dupa care elementele sunt extrase pe rand */ Spublic class TestQueve at +) public static void main(String (] args) oe 5 etemente, + © Queue q = mew Quewedr(): % Hadaugam elemente in coada bo for int i= 0; ie 5 144) » ot he qvenqueve(new Integer(i))s sy 5 Hscoatem si afisam elementele din coada ts System-out.print('Continatul cozit estes ")s muy » » fer Gs) Q hi _ System. out. print (g. dequeue () + "Od » 4 mM cateh(UndertlowBxception we) 1 10.4 Liste inlantuite ino Hist tnlinguté elementele sunt refinute discontinuu, spre deosebire de siruri in care elementele sunt refinute in locaji continue. Acest Iuery este realizat prin stocarea fiectrui obit int-un nod care confine obiectl so refe- ‘inj cdtre urmatoral element io ist, ca in Figura 10.4. in acest model se rej referinge atit etre primul (fst) ft si cXtre utimul (ast element din list, Un nod al une! lst este implementat in Listing 10.10, Listing 10.10: Un nod al unei liste 35 tog, Liste INLANTURTE \ package datastructures 30+ Un mod al Uistel intantuite. Clase este vizibita 4% doar in pachet (package-friendly }, deoarece este 5 § pentru went intern al Uistel aa Selass ListNode “ + fas Valoarea continuta de nod.+/ Object clement: fee Legatura catre modul urmator.«/ fh ListNode next 4‘ publle ListNode(Object element) clement = clement: ListNode(Object element, ListNode next) element = element {in orice moment, putem adiuga in lista un nou element x prin urmatoarele operat last next = new ListNode(x)s //ereaza am nod cu continutul = last = last next; //nodul creat anterior este ultimal in lista fn cazal unei liste infinite un element oarecare nv mai poste fi gait eu un singuracces. Aceasia este oarecum similar eu diferena inte accesareaunet melodii pe CD (un singur acces) si accesarea unei melodii pe easetd (acces Seevental). Desi din acest motivlistle pot sh park mai putin atractive decdt simul, exist toi edteva avantaje importante. fn primal ind, inserarea unui Figura 10.4: O listi simplu inkinuit first last 56 tog, Liste IMeANTUITE clement in mijlocl listei nu implick deplasarea tutor elementelor de dup punctul de inserare. Deplasarea datelor este foarte costisitoare (din punct de ‘vedere al timpalui, iar stele tnlinuite permit iserarea cu un mums constant de instuciun de atibuire Merithobservat ci dack permitem accesul doar la frst, atunciobjinem o stv, ia da permitem insriti doar la last i aceesiri doar la first, objinem 0 coadi, Exercijle 1 gi 3 de la fnaul acest capitol propun exact acest hens restritionarea operator pe o list penta a objineo stivi respect o coadi in general, atuneicind folosimo list, avem nevoie de mai multe opera. cum arf gisiea sau stergerea nui element onrecare din lis. Trebue sk per- miter sinseraea unui nou element in orice punct.Accasia este deja mul¢ mai tmult deci ne permite o stivi sano coadi. Pentns a acesa un clement in ist, tebuie si obsinem oreferingicte nodal care i corespunde. Evident cb ofeireauneireferinge edtre un element inca principiulascunderi informe. Trebue sine asigurim ci orice acces la stk Prin intermedi uneireeringe nu pericliteazi stuctura lise. Pentra a realiza acest ues, lista este defini in dou pi: o cas lists o cas iterator. Clas listi va refine elementele propriu-zse ale lise in timp ceiteratonal va ofr o modalitate de a parcurge si modifica etementelelistei fii a periclitastructura ci. Listing 10.12 fornizeara intrfaja de bard pene o list inlinuits,oferind si metodele care descr doar starea liste Listing 10.14 definesteo casi iterator care este folosté pens toate ope- rajle de accesare a iste. Pentru a vedea cum functioneazi\ aceasti clas, i examin seevenga de cod clasick pentru afigareatturorclementelor din cadral tneistructriliniare, Daca lista arf stocat int sir, secvenja de cod ar arta astiet: sUparcurge sirul a, afisand fiecare element sfor (Int index = 0; index < length; ++ index) Hl 1 System out. printin(alingex I): " {in Java elementar, codul pentru a itera o list este: \Wparcurge lista theList de tip List, afisand fiecare element Bor (ListNode p= theList. first; p != mull p = p.next) ot {System out. printin(p.d " Pe de altk parte, trebuie avut in vedere faptul c¥ anumite operagii in cadrul Tistet pot egua (de exemplu stergerea unui element inexistent), motiv pentru care este utilizatd urmatoarea clasa TtenNotFoundzxcept ion din Listing 7 25 tog, Liste INLANTURTE 10.11 Listing 10.11: Clasa de exceptii TeemNNot FoundException 1 package exce s/ee Clase de exceptii care semmaleaza tentative de a cauia un te clement Inexistent iw cadrul ancl structuri de date #/ Spublie class ItemNotFoundException extends Exception “ +> public ItemNotFoundException () oe 5 super: wo 1: public ItemNotFoundException( String msg) ot he super (mse): nod ") Listing 10.12: Interfata pentru o lista abstract \ package datastructures: i/ae Interfata pentru un tip abstract de lista inlantuita. «/ ‘public Interface List a © fae Testeaza daca lista ¢ vida. */ 5 boolean isEmpty (): t/a Sterge toate elementele din lista, of void makeEmpty 0): Lis 1g 10.13: Implementarea unei liste inlinuite 1 package 4 Lista simplu intantuita 5 + Accesarea elementelor se face cu lterarorul LinkedListlir oe lic class LinkedList implements List + ListNode header: 4, LISTE INLANTUIE 5 publle LinkedList() of Me header = mew ListNode (null); wd 5 public bestean isEmpty () ad SS return header. next == mull so 2 public: vold. makeEmpty() af BM header-next = ull; = s) 1g 10.14: Interfags pentru u ct package datastructures: Nimport exceptions +; ts Interfate iterator pextra parcurgeres elementelor nei Ff Uste Inlantuite absiracte (simplu Inlantuita, dublu ft ¢ intanruita, cireulara, ete.) public Interface Listltr ho fee Insereaza un element la positia curenta. «/ 5 Vold insert (Object x) throws’ ItemNotFoundException : Boles Me © Seteaza pozitia curenta pe elementul x daca neil gaseste tn lista boolean find (Object x): fee Sterge elementul x din Lista. af Yold remove( Object x) throws. ItemNotFoundException 4 fxs Verifiea daca lista @ fost parcursa in roralitate. +/ > Doolean isinList (): 2 /es Obtine elementul aflat pe pozitia eurenta. +f Object retrieve Qs BM fee Seteaze positia ineintea primului element. «/ veld zeroth () 39 tog, Liste INLANTURTE n /es Seteaza positia curenta pe primul clement. +/ dvoid firsts w fes Avanseaza in liste ta urmatorul clement. */ void advance() Pornind de ta interfja unei liste abstracte, codul pentru implementarea unei liste inkinquite este dat in Listing 10.13, iar implementareaiteratonului unei liste inkinuite este data in Listing 10.15, ‘Mecanismul de iterare pe care I-ar folosi limbajul Java ar fi similar eu us mitoarea secvenyi: \Uparcurge List, folosind abstractizarea si an iterator pListlee ite = new LinkedListltr(theList): for (itr first Qs ite istaList Qs ite-edvanee()) st 4 System. out. printin (itr retrieve ()s ” Inifiatizareadinainteaciclului for creeazdun teratoral liste. Testl de er- iminarea ciclului folosegte metoda i TnLi.st () definté pentru clasa Linked- List Jer. Metoda advance () tece laurmatoru! nod din cadul iste. Putem access elementul curent prin apelul metodei ret rieve () definitdin Linked- List Zee. Prinepiul general este cd accesl find realizat prin intermediulcla- sei List It, securtatea datelor este garantati Putem avea mai mul iteratort care i raversezesimultano sigur list Pentru a functiona corect, casa List Itz trebuie si menina dous obiecte. fn primul rind, are nevoie de o referinjcatre nodul eurent. in al doilea rind ane nevoie de referngs eitre obiectul de tip List pe care tl indie (aceasta refering este inijializat o singuri dat in cadrul constrctoruli). ing 10.15: Implementarea iteratorului liste fokinquite package datastructures Simport exceptions .¢; te Merator pentru lista inlantuite ter ‘public class LinkedListitr Implements Listrte i fee Referinta catre lista care va fi iterate of Nt protected LinkedList theList bs IeeReferinia carre modul eurent.4/ 5 protected ListNode current: 4 LISTE INLANTUITE JesConstruleste un iterator pe lista Uist es public LinkedListItr(LinkedList list) ( theList = list current = list isEmpty () 2 list header + list header next: 1 Jes Construieste ou parametru de tip List. Daca list ‘mu refera o instanta LinkedList, se arunca 0 exceptie fide tipul ClassCastEception +? public LinkedListiie(List list) throws ClassCastException ‘ thls ((LinkedList) list): 1 Jes Rereteaza iteratorul care va indica pozitia dinaintes ‘ primulut element din Listas! public void. zeroth) ‘ 1 ent = theList header Jes Adauga obiectul x la pozitia curenta in lista + G@throws lemNotFoundException daca lista este vida +f public vold insect (Object x) throws ItemNotFoundException ‘ it (current t > throw new ItemNotFoundException ("Eroare la inserare* ) ListNode newNode = new ListNode(x, current .next ) ent next = newNode 1 fos Intoarce true dace obiectal = se afla in liste +f public boolean find (Object x) ListNode itr = theList.header.next: white Cite t ) null && !itr. element equals (x)) ie Cite i return false: ) 6 tog, Liste INLANTURTE oe 1 Jes Sterge obiectul x din lista = Gihrows NemNotFoundEsception daca x mu se afla in listae/ public. vold remove( Object x) throws. ItemNotFoundException i ListNode itr = theList.header while (itr next 1 c mull && tite next element -equals(x)) ie Gitrenext = i throw new ItemNotFoundException ("Stergere esu: null) ite next = itrenextonext: //trecem peste nodal stere current = theList. header: ’ fas Imoarce clementul de pe potitia eurenta */ public Object retrieve) i return (isiaList () ? current.element > mull); ) Jes Imoarce true dace ne aflam in interiorul Listel #/ public boolean isiaList() i return (current t= mull) && (current ’ theList header): fee Elementul curent va fi primal element din lista +f public vold first () i current = theList. header next 1 Jes Avanseaza iterarorul pe urmetorul element «/ public void advance () c In (current i , : ) null) wel Tati i exemplul de utilizare a listei Listing 10.16; Exemplu de utilizare a listei, Programul va afiga: Conjinutul listei: 43.210 Import datastractures = import exceptions -+: h/as Clasa simpla pentru testarea unei liste, care adauga S numere ts dupa care afiseaza continutul Uistei.+/ Spublic class ‘TestList at 5) public statie vold main(String (} args) oe {0 List theList = new LinkedList Qs 0 Listtte itr = mew LinkedListlte(theList ys dae insereaza elemente pe prime positie for (int = 0; be 8: Uae) wot “ ty wo ® ite insert (new Intezer(i)): " ) {atch (ItemNotFoundException e) > of : 1 > ite zeroth (05 //se trece ta inceputal listed uy % System-out.print("Continutul listei: *) for Cite first (Qs itrsistmbist Qs ite advanceQ) en % System out. print (itr retrieve () + * *)s sy an ” Desi discujias-a axat pe liste simplu inlinuite,interfojele din Listing 10.12 si Listing 10.14 pot fi folosite pentru oricare tip de lista, indiferent de imple- ‘mentatea pe care o are la baz&. Interfaja nu precizeaz’ faptul ci este nevoie de liste simplu inkanguite. cy 10S. ARBOR! Figura 10.5: Un arbore generic JN Ue 10.5 Arbori 10.5.1 Notiuni generale ‘Vom trece acum si studiem cele mai importante structur neliniare care apar {in algoritmii pentru caleulatoare:arbori. in general vorbind, structuraarbores- enti implied o rele de ramificare intre nodusi, foarte aseminstoare cele in- tilnite la crengile unui arbore din natura ‘Una dint definite cele mai rispanite ale arborilor (nu neaparat bina) este urmatoarea (dupa D.E. Knuth) Definite: Un arbore (Figura 10,5) este o mulime fniti T de unul sau mai multe nodur, care ae proprictjile: 4) exist un nod special, numit ridicina arboreluis ji) toate celelalte nodusi din T' sunt repartzate in mulfimi T),T3y..-»T>u disjunct, fiecare muljime la rindul sau find un arbore. Arbor Ty,T3,---,Tm se numese subarbori ridacini Se observ ci definitia de mai sus este recursiva (recursvitata este prezen- tata in capitolul 12): am definitun arbore pe baza unor arbor Totus, privind ea atenjie definifia ne dim seama c& nu se pune problema circularitii, deoarece un arbore cu un singur nod este aledtuit doar din ridicing, iar arborii cu n> 1 noduri sunt defini pe bazaarborilor cu mai pugin de n nodusi. Exist gi defini, nerecursive ale arborilor, dar defniia recursivi este mai adeevati, deoarece vom vedea ci recursivitatea pare si ie o trisiturl inerenté operatilor pe steuc- turiarborescente, Caracterul recursiv al arborlor este de altfl prezent si in natur8, deoarece muguti arborilor tines crese gi se dezvolté in subarbori, care Ja randul lor fac mugusi si asa mai departe. [Nodul ridcini al fieciruisubarbore se numeste fil (sau copiul)ridacinii iar cina este taal (sau parintele) fiecdrui nod ridacina din subarbor. "De expla eo graf, un arbre este definitcaun graf cones Ftc 64 105, ARBOR! aK RB RI dg pase rm Din definiia recursiva reiese cd un arbore este o colesfie de m nod, dintre care unul est ridcina,sin—1 muichi. Fatolc& exist n— 1 muchii se deduce din observatia simple flecare muchic leagt un nod de parintele siu i fecare nod, in afar de ridcin, are exact un print. fn arborcle din Figura 10.6, ridicina este 1. Nodul 5 il areca prime pe 1 si are fit 12,13 si 14. Nodurile cae nu au fi se mumese frunze. Frunzele in arborele de mai sus sunt 8, 3, 12, 13, .. 21. Nodurile eu aceasi parinte se numese fra. In mod asemanator se definexc relaile nepot, bane ec. Undrumde la unnod n; Iaun nod geste osecvengde nodurim,725-+-sme astfel inet m este tat hui nya pentru = 1, &— 1. Langimea unui dum este data de numarul de muchii ale drumului, adic’ k — 1, Pentru oricare nod nj, nivelul (adneimea) nodolui este hungimes unicului drum de la ridcina la Astfel,nivelal sie 0, In arborele din Figura 10.6, nivelul nodulat 2 ste I, jar al nodulai 15 este 3. Adincimea unui arbore este defnta ca find maximal adéncimilornodurior. fn exemplulnostru,adéneimes arborelui este palin adincimea nodului 15, care ete 3 10.5.2 Arbor Defin fi Figura 10.7 arati chun arbore binar consti intro ricind gi doi subarbort T, $i Ty, oricare din ei putind si fie vid (si lipseased) (© proprietate deosebit de importants a arborilor binari este cX adncimea ‘edie a unui arbore binar cu n nodusi este considerabil mai mick deeat n. Se poate arita cf adincimea medie a unui arbore binar este proportionala ca V7, jar adancimea medie a unui caz particular de arbore binar, arborele binar de 6s ‘Un arbore binar este un arbore in care orice nod are cel mult doi 10S. ARBOR! Figura 10.7: Arbore binar generic =) LX LS Figura 10.8: Exemple de arbori binari (a) arbore binar degenerat (b) arbore Dinar nedegenerat . wm a p ° $ fo ' g godbo 2 } é\ : é a clutare (seotnea 10.5.3), este proportional cu login . Din picae, in cazurile degenerate, adancimea unui arbore poate f chiar n ~ 1, dupa cum se vede gin Figura 10.8¢@), fnakimea (adancimea) unui arbore bina este foarte importanta, deoarece molt operat definite asupra arborilor (stergere de nod, inseare de nod et.) sunt proporjonale cu inaimea arborehi. Din acest moti, s-a recurs la difeite metode pentru a mentine adncimea unui arbore proportionala cu log n in orice situate (arbori AVL, arbori bicolor et). Parcurgerea arborilor binari Dupti cum reiese si din Figura 10,7, putem defini un arbore binar ca flind 6 muljime finiti de noduri care este fie vida, fie este formatd dints-0 ridacind si doi arbori binari, Aceasti definijie sugereaza o metoda natural de reprezentare ‘ arborilor binati: fiecare nod va fi descris de tei componente: element - informajia uta a nodului, Left - o referinga catre fiul din stinga si right - 66 105, ARBOR! Figura 10.9: Reprezentarea inlinjuiti a arborilor din Figura 10.8 root FZ root Ao a ile o]a]o 4a) (oy o refering citre ful din dreapta, Dact un nod nu are fu in stinga atunci Left este nu11, analog, dacd nu are fu in dreapta, atunci right este aul. Putem astfel defini clasa BinaryNode, care refine un nod al unui arbore binar: ‘public class BinaryNode wt } Object element 4 BinasyNode left”; 5 BinaryNode right + Weonstructori si alte metode Informatia utili din cadrul nodului este refinuti de atributul element, ¢ este de tip Object, deci poate referio instantade orice tip. Figura 10.9 prezin- ‘i modul in care se reprezint’ inlnquit arbori binari din Figura 10.8, Variabila oot din Figura 10.9 este o refering care indica ridicina arborelui, Exist mai mulfialgoritmi pentru manevsarea structurilor arborescente, si 0 idee care apate de foarte multe ori este nojiunea de parcurgere, de “deplasare’ prin arbore. Parcurgerea unui arbore este de fapt o metoda de examinare sis- {ematicd a nodurilor arborelui in aga fel inet fiecare nod si fie vizitato singuri 0 10S. ARBOR! dati, Parcurgerea completi a unui arbore ne oferito aranjare linear’ a nodusilor, si operarea multor algoritmi este simplificatd dac stim care este urmatorul nod Ia care ne vom deplasa int-o astfel de secvenf, pornind de la un nod dat. Exist rei moduri principale in care un arbore binar poate fi parcurs: nodurile se pot vizita in preordine, inordine si in postordine. Vom deserie aceste trei metode recursiv, ca si definitia arborelui acl un arbore binar este vid (nu are nici un nod) parcurgerea lui nu pre- supune nici o operatie; i caz contrar parcurgerea comport trei etape, descrise ul urmator: Seperune starting | Seviieacn icon | Se page bare de Pentru arborele din Figura 10.8 gisim ei nodurile in preordine sunt: ABDHIECFG deoarece mai inti se viziteazi ridicina A, apoi subarborele sting (B D-H T ) si apoi subarborele drept(C FG). ‘Similar, parcurgerea in inordine are ca rezultatsirul HDIBEAFCG iar parcurgerea in postordine: HIDEBFGCA [Numele de preordine, inordine gi postordine deriva, bineinjeles de la pozi- Jia relativi a ridicinii faa de subarbori. © posibili metoda de a parcurge un arbore in preordine este dati in Listing 10,17. Metoda primeste ca parametru 0 referini citreridicina subarborelui care este vizitat. Evident ci la primul apel, parametrl este chiar ridicina arborelui (referinja root din Figura 10.9). Vom. vedea cum se integreazii parcurgerea unui arbore in cadrul unei clase complete {in paragraful 10.5.3. Listing 10.17: Metodi generic’ pentru parcurgere binar preordine a unui arbore ‘bite vold preord(BinaryNode t) > process ( t.element ) preord( to left ) 5 Preord( toright ) 105, ARBOR! Celelalte doutt parcurgeri se realizeazii absolut analog, prin simpla reor ddonare a instructiunilor de parcurgere, 10.5.3. Arbori binari de ciutare Una dintre cele mai importante aplicai ale arborilor este uilizarea acestora probleme de cdutare. Proprietatea care face ca un arbore binar si devina un arbore binar de edutare este: pentru orieare nod X al arborelui toate nodurile din subarborele sting sunt mai mici decit X, si toate nodurile din subarborele rept sunt mai mari decdt X. Agadar, fai de arborii binari obignufi, arborit de ciutare mai adaugi o relayie de ordine intre elemente. Pentru a putea fi comparate, nodurile nu var mai confine obiecte de tip Object. cain paragraful 10.5.2, ci instanfe ale clasei Comparable. Arborele binar de © structuri de date in care, pe lang etutare rapidd, putem adiuga sau sterge eficient elemente. Figura 10,10 ilustreaza operafiile de baz’ permise asupra, unui arbore binar de ciutare, Figura 10.10: Modelul pentru arborele binar de eiutare, inser’ find.remove SS 7 Arbore binar de cautare De exemplu, arbori din Figura 10.8 nu sunt arbori binari de ciutare, deoa- rece, in ambele cazuri, in stinga nodului A se afl nodul B, care are valoare mai ‘mare decat A (daci considerim ordinea alfabeticd). ‘SA studiem cu atenjie arborii din Figura 10.11. La prima vedere, ambii par si fie arbori binari de ciutare; examindnd totusi mai minujios arborele din dreapta, constatim e% nodul 7, desi este mai mare decat rdicina, 6, se afl in stinga ei, ceea ce contravine regulii arborilor de cdutare. Co) 10S. ARBOR! Figura 10.11: Doi arbori binari. Doar arborele in stinga este si arbore binar de cutare, Principalele operaii care se realizeazit asupra arborilor binari de ciutare sant: Ciutarea unui nod tn arbore; # Gisirea minimului si maximuluis « Inserarea unui now nod; « Stergerea unui nou nod; + Videreaarborelui(tergerea tuturornodurilon. © posibisinterfgh care descrieaceste opera este prezentaiin Listing 10.19. Setul de oper permise este acum extns fat de stv si cond pentra 8 permite gisiea unui clement arbitrar, alituri de inserre gi stergere. Metoda find () intone o refernfs cite un obiect care este egal (in sensul metodei compareTo() din intrfafa Comparable) cu clementul efutat. Dact mi exist nici un element egal eu el eluta, £5nd() anuned 0 exceptie Teen NotFound=xcept ion, prezenaté in seciunea anterioars. Accasta exe 0 decizie de proietare. O ali posibilitate arf fost si intoareem a1 in cazul fn care clementulclutat nu este git. Diferenja inte cele doud abordiri con- Sti in faptul ck metoda nossa il oblig pe programator si trateze explicit sitagia fn care efutarea nu are succes. fn ceaalts situaie, dacd am fi fn- tors nul}, si nu sa fi flcut verfcdile necesare, programul ar fi generat un 70 105, ARBOR! Listing 10.18: Clasa de excepfie DuplicatettenException \ package exceptions: Spevlic Claas” Bupiciciembception Sends Exception + supers 24 {: publte DuplicateltemException (String msg) of he super(mse): mod Nul1PointerExcept ion la prima tentativa dea folosi referinja, Din punct de vedere al eficienfe, versiunea cu exceptii ar putea fi ceva mai lenta, dar este pujin probabil ca rezultatul si fie observabil, cu exceptia situajiet in care codul ar fi foarte des executat in cadrul unor situaii in care viteza este critic’. fn mod similar, inserarea unui element care dea est in arbore este sem- nalataprint-o exceptie Dup! icatertenExcept ion (veri Listing 10.18) Exist i alte posiilealtemative, Una dinte ele const in permite noi valor si suprasrievaloarea soca ‘Vom da ca exemplu un arbore de cdutare care rejine stringuri. Acest lueru este posibil deoarece String implementeaza interfaja Comparable, Im- plementarea arborelui binar in conformitate cu interfaja SearchTree este prezentati in Listing 10.21. Pentru a implementa nodurile arborelui binar se utilizeazi clasa Bi nar yNode, prezentati in Listing 10,20, Implementarea arborelui binar de efutare este mult mai complexi decit pen- mu stivi sau coadi gi foloseste recursivitatea (care va fi prezentati in eapitolul 12), Nu vi ingrijoragi daci nu injelege{i acum toate detalile de implementare; putefi trece mai departe fed nici o problema si reveni mai tirziu, dup’ ce afi parcuss si injeles capitolul 12 ‘Toate elementele din arborele binar ne sunt accesibile prin intermediul ri- 2, nodul ciutat se afl in subarborele drept. Comparim pe 4 cu fiul din dreapta al lui 2, constatim ca valorile sunt ‘gale si ne oprim, Dacd in loc de cheia 4 am fi cAutat cheia 5, atunci am fi ajuns in subarborele drept al lui 4, care este vid, deci nodul 5 nu se giseste in arbor. (Ciutarea unui nod se realizeazai cu metoda £ ind () implementatiin liniile 75-95 din Listing 10,21. Aceasti metodi porneste cu edutarea de la riiicina ar- borelui si coboari fie edtrestinga fe cdtre dreapta (Iuncjie de relajia dintre ele- ‘mentul etutat si ridcina subarborelui) pan cdind elementul eStat este gsi s- si” din arbore, caz in care se arunci\/o TtemNotFoundException () Gisirea clementului minim si a celui maxim: Gisirea elementului minim (gisirea maximului se face analog) consti pur si simplu in a cobori in arbore pe ppartea sting (liiile 105-108) pani se ajunge la frunz’i, Elementul din franz este chiar minimul, n 105, ARBOR! Listing 10.20: Clasa care modeleaza un nod al unui arbore binar \ package datastructures: Le Reprezinta un nod in arbore. Este pentru uz intern BinaryNode 1 Comparable elemen + BinaryNode left vw BinaryNode rig! 5 BinaryNode(Comparable ) wee mn lett ooright a BinaryNode(Comparable ¢, BinaryNode It, BinaryNode rt) a element left = 1k sight = ts Adijugarea unui nod in arbore: Adiugarea unui nod in arbore se realizeaza folosind metoa insert (Comparable) din linile 20-24, care la rindul et delegi problema citre insert (Comparable, BinaryNode) de la liniile 129-150. Probabil c& v8 intrebai de ce a fost nevoie si scindim operagia de adaugare in dou metode? Metoda propriu-2ist de stergere are si un parameteu de tip BinaryNode, care Ia inceput este chiar root, ridicina arborelui. Uti- lizatorul obignuit nu are acces la acest atribut, de aceea el poate apela doar metoda insert (Comparable), care fiind o metoda din cadrul clasei, va putea apela la linia 23 insert (x, root). Aceasti tehnicd este folosits pen- tru toate metodele existente in clasa BinarySearchTree. Metoda de adiugare a unui nod in arbore este conceptual destul de simpli Pentru a insera x in arborele cu ridacina t, ne “afundim” in interiorul arborelui exact ca gi in cazul metodei find (). Daci valoarea x este gisiti in arbore, atunci anuncim DuplicateTtenExcept ion. in caz contrar inserdim un nod cu cheia x, in ultimul punet din calea care a fost parcursi, Figura 10.12 B 10S. ARBOR! Figura 10.12: Arborele binar de clutare inainte si dupa inserarea noduluiS. ne arati ce se petrece. Pentru a insera valoarea 5, traversiim arborele ca si cind am realiza procesul de ciutare. Cand ajungem la nodul cu cheia 4, trebuie si ‘mergem cdtre dreapta, dar nu exist subarbore drep, deci 5 nu este in arbore gi acesta este locul in cate trebuie inserat Ca orice metodi recursiva, insert () incepe la linia 132 eu conditia de terminare: wee ccare este adeviiati in momentul in care subarborele curent este vid. fn acest ‘caz se creeazi pur si simplu un now nod in care se plaseaz’ obiectul x gi se ac- tualizeza ridacina subarborelui cu nodul curent, in cazul in care subarborele in ‘cate se insereazi x nu este Vid, comparim x cu valoarea din ridiicina arborelui: x. compareTo( t-element ) Dacé valoarea din x este mai mic, atunci x se va insera in subarborele sting: Leleft = insert, tem) + altel, dae este mai mar se va insera in subarborele dept: ovight = insert(x, toright) ine daci valorile sunt eyaleinseamni cd nodulrespetivexista deja in arbore gi se anunci o DuplicateTten=xcept ion Metoda insext () confine un aspect de finefe: cum se leagi noul nod inserat (5 in exemplol nost) detail sau (49? fn metoda insert () nu pare si existe 0 secvenfi de cod care si semnaleze ci ful din dreapta alli 4 nu mai este nu, ci este noul nod insert. Réspunsil se aft in modul in care se 4 105, ARBOR! realizezii apelul recursiv al metodei insert () : subarborelui sting (sau drept) curent i se atribuie rezultatul inseririi nodului x curent. La un moment dat, metoda Va crea un nou nod, iar adresa acelui nod va fi intoarsi ede nodul parinte Stergerea clementului minim sia celui maxim: | Stergerea clementului minim gisirea lui, du subarborele drept in locul lui, Metoda removeMfin () dela linile 152-170 realizeaza exact acest lucru, Observafi ci aici, pentru variajie,ciclul wh Le de la linile 105-108 ale metodei findMin () ‘fost inlocuit eu un apel recurs. “Ridicarea” subarborelui drept in locul ele- ‘mentului sters se face simplu, prin atribuirea de la linia 166: const are se “ridi toeiant ‘Stergerea elementului maxim se realizeazi absolut analog. Stergerea unui nod din arbore: Operatia de stergere a unui nod este cea ‘mai delicati operatie pe arborele binar de ciutare, deoarece pe ling’ eliminarea, rnodului mai implied si operafii suplimentare pentru a pastra structura de arbore binat. In cazul operatiei de stergere, dupa ce am gisit nodul care trebuie sters trebuie si considerim mai multe posibilit: ‘ Dacit nodul care trebuie sters este 0 frunzi, el poate fi sters imediat prin Inlocuirea leg’turii printelui siu cu nui 1; # Dac nodul care tebuie slers are doar un singur fiu (indiferent c& este sting sau drept), stergerea lui se face prin ajustarea legaturi parintelui siu pentru al “ocoli” (Figura 10.13); © Cazul complicat apare atunci cnd nodul care trebuie sters are doi fi, Strategia generalé in acest caz. este de a inlocui cheia nodului care tre buie sters cu cea mai mic& cheie din subarborele stu drept (care este uusor de gisit) dupa care nodul cu aceasta cheie se sterge folosind metoda removeltin () descrisa anterior (Figura 10.14). ‘Stergerea unui nod din arbore se realizeazi folosind metoda remove (Com parable) din liniile 28-32, care la rindul ei delegi problema citre remove- (Comparable, BinaryNode) de la linile 172-199. Ca orice metoda recur- sivd, remove () incepe la linia 175 cu conditia de terminare: inc == mult) 15 10S. ARBOR! Figura 10.13: Stergerea unui nod (4) cu un singur fu. Legitura 2-3 “ocoleste” nodul 4 Figura 10.14: Stergerea unui nod eu doi fii. Cel mai mie nod din subarborele drept al lui2 este 3. Se inlocuiese 2 cu 3, dup’ care 3 se sterge prin “ocolire” 6 105, ARBOR! care este adeviratlcind subarborclecurent este vid, in aceast situayieelemen- {ul x nueste gist gi se aruncl o Teentiot FoundExcepticn acl subarborele nu este vid, se compari elementul care tebuie sles cu ri- dicina si, dact sunt diferite, se coboar fe pe subarborele dept fe pe cel sting. in cazul in care clement care trebuie sles a fost gist (adieX x. compare~ To(t element) este O)trebuie si elimindm nodulrespeciv din arbore avand {nsf mate gi si nu pierdem strctura de arbore binar de eSutare, Dac nodul curent ate descendenj att in stanga cit fn dreapta,adie8 teleft t= na AB teright f= null este true, vom folosi artificiul descris anterior: vom aduce in locul nodului sles, cel mai mie nod din subarborele drept (care este evident mai mare decit toate nodurile din subarborele sting, deci se va pistra siructura de arbore de cfutare) toelement = findMin(t, right ).element dupii care vom apela removeltin () pentru a sterge elemental minim din acest subarbore: tright = semoveMin(t. ig! > Dac nodul curent nu are descendenji in ambele parti, operayia de stergere este mult mai simpli: puri simplu se “urea” subarborele nevid in locul nodului care a fost sters (altel spus, nodul sters este “ocolit”): be (lent ts YP deft stright: Metodele isEmpty () simakeZmpty () sunt banale gi nu Te vom detalia Listing 10.21: Implementarea arborelui binarde ciutare «package datasteuctures: Mimport exceptions .+: tye Arbore binar de coutare alocat inlantuit. Toate be cautarile se fac pe baza metodel compareTo( ). Expune te metode pentru inserare, stergere, caulare ete. +f ‘public class BinaryScarchTrce, Implements SearchTree ut to fae Referinta catre radacina arboretui e/ Si protected BinaryNode root ; 1 /exConstructor care initializeaza radacina ew null +/ 5 publle: BinarySearchTree() n 10S. ARBOR! fue Adauga clementul x in arbore © Gthrows DuplicateltemException dace elemental deja existe. e/ public void insect (Comparable x) throws DuplicateltemException ) Oy ro0t): Jes Sterge clementul x din arbore + Gibrows NemNorFoundEsception daca clementul mu se afla : in arbore.4/ Public void remove(Comparable x) throws. emNotFoundE xeeption i root = remove(x, root): ) (ae slerse etemencat minim din arbore + Othrews ItewNotPoundEsception dace arborele este vid+/ Public void romoveMin() throws. ItemNotFoundException c root = removeMin root ): ) fee Imtoarce elemental minim din arbore + Gthrows ItemNotFoundbxception daca arborele este vids/ Public Comparable fiadMin() throws TtemNotFoundException i return fingMin( root). clement ) fos Intoarce elemental marin din arbore + Othrews HtewNotPoundException dace arborele este vid+/ publle Comparable findMax () throws ItemNotFoundException i return findMax( root). element: ) fee Canta elemental x tn arbore + Grhrows ItemNotFoundException dace * mu este gasit.»/ public Comparable find (Comparable x) throws. ItemNotFoundException return find(x, root). element: ’ 105, ARBOR! 4 fea Intoarce true daca arborele este vid +/ public boolean isEmpty () “f “1 % /esVideaza arborele, setand radacina la mull «/ 2 public. vold makeEmpty() ni an % protected BinaryNode find (Comparable x. BinaryNode 1) > throws. ItemNotFoundException mt 0 while Co t= mull) » ot a it (x.compareTo(1 element) < 0) E fi ® better: Hy else If (x.compareTo(t clement) > 0) t= rights ) else = 4 . return ti //element gasit * ) sy % throw new ItemNotFoundException ("Element nega: a % protected BinaryNode fingMin(BinaryNode ¢) & throws. IemNotFoundException mt we Uf (== mult) fi vs) throw mew ItemNotFoundException ("Element negasit”): my te while (1 left != mull) tren: my 2» 10S. ARBOR! protected BinaryNode findMax (BinaryNode t) throws. ItemNotFoundException ira i throw new ItemNotFoundException ("Element negasit") > white (1.cight t= mult) jected. Bina throws, Duplica JNode insert (Comparable x, BinaryNode 1) ItemException na i {= new BinaryNode(x, mult, null): , elec if (x.compareTo(t element) < 0) fi toleft = insert(x, tteft): ) else If (x.compareTo(t clement) > 0) C toright = insert(x, teright)s > throw new DuplicateltemException (“Elemental exista deja"): ) protected BinaryNode removeMin(BinaryNode 1) throws, ItemNotFoundExeeption t a ( throw new ItemNotFoundException ("Element negasit"): nut) ie (iteft t= manly i tert removeMin( ett): ARBOR! o t= tonights m= . 5) protected BinaryNode remove(Comparable x, BinaryNode 1) be throws. ItemNotFoundException mae oS null) throw new ItemNotFoundException ("Element negasit”): ie th HF (x-compareTo(t element) < 0) mt ‘° toler my is else If (x.compareTo(t clement) > 0) mt emove(x, t. left): toright = remove(x, teright): ) se AE (4 left t= mal Rk fright t= nul S| tuelement = findMin(t. eight ). clement; me Uoright = removeMin tight )s mt mo tle ™ ot we t= deft te matty 2 tteet s tartent an mo : Listing 10.22 prezint& modul in care arborele binar de cdutare poate fi folosit pentru obiecte de tip String. Interfaja SearchTree mai are dou metode suplimentare: una pentru a sisi cel mai mic element si una pentru a gsi cel mai mare element. Se poate arita c& transpirdind un pie mai mult se poate gisi foarte eficient gi cel mai mic al k-lea element, pentru oricare ktrimis ca parametru ‘Si vedem care sunt timpii de execusie pentru operajile pe un arbore bi- nar de ciutare. Este normal si sperim c& timpii de execufie pentru £ind (), 81 10S. ARBOR! insert () si remove () si fie logaritmici, deoarece aceasta este valoarea pe care 0 vom objine pentru clutarea binari (paragraful 12.3). Din nefericire, ‘pentru cea mai simpli implementare a arborelui binar de cdiutare, acest luera nu este adevarat. Timpul mediu de execusie este intr-adevat logaritmic, dar in cazal cel mai nefavorabil (cdnd arborele este “dezechilibrat”)timpul de executie este 0(n), caz care apare destul de frecvent. Totusi, prin aplicarea anumitor trucuri de algoritmica se pot objine anumite structusi mai complexe (arbori bicolori) ‘care au intt-adevar un cost logaritmic pentru fiecare operatie. Listing 10.22: Model de program care utilizeazi arbori de efutare. Programul va afiga: Gisit Cristi;Alina nu a fost gisita simport datastructures.+3 simport exceptions .¢: j/ee Clara simpla de test pentru arborii binari de cantare. «/ lie class ‘TestSearchTree public state vold main(String [J args) i SearchTree { = new BinarySearehTree (); tring result = mull Sooty » ™ toinsert(* Cristi"): Boy eaten (DuplicateltemException ¢) can soy > ony st e result = (String) ¢. find ("Cristi 3 System-out.priat("Gasit " + result + * an) % cateh(ItemNotFoundException ¢) i % System. out, print ("Cristi mu a fost gasit » 4 yoy an ” result = (String) ¢. find (“Alina "); System. out. print ("Gasit " + result + * 5") an) > €ateh ItemNotFoundException e) 106. TABELE DE REPARTIZARE System-out.print("Alina nu a fost gasita;*) Ce putem spune despre operajile £indMin() si £indmax()? fn mod cert, acest operaii necestd un timp constant in cazul cButirii binare, deoarece implick doar accesarea unui element indicat. in cazul unui arbore binat de cutare aceste opera iu acelayi timp ca o ctutare obignuitf,adict O(1og 1) fn cazul mediu gi 0 (n) in eazul cel mai nefavorabil 10.6 Tabele de repartizare Existé foarte multe aplicayii care necesiti 0 clutare dinamic’ bazati doar pe un nume. O aplicajie clasici este tabela de simboluri a unui compilator. Pe ‘miisurk ce compileaza programul, compilatorul ebuie si ejin’ numele (impre- uni cu tipul, durata de viapi,locayia de memorie) tuturor identiicatorilor care au fost declaraji. Atunci cind vede un identificator in fara unel instrucfiuni de declarare, compilatorul verified si vad dacd acesta a fost declarat. Dacia fost, compilatorul verified informayia adeevaté din tabela de simbolusi ‘Avid in vedere faptul cd arborele binar de cfutare permite acces logaritmic la obiecte cu denumiri oarecare, de ce am avea nevoie de o ata structurt de date? Riispunsul este ci arborele binar de ediutare poate st dea un timp de execujie liniar pentru accesul unui element, iar pentru a ne asigura de cost logaritmic este nevoie de algoritmi mult mai sofsticaji Tabela de repartizare (engl. hashtable) este o structura de date care eviti timpul de execute liniar, ba mai mult, suport aceste operat in timp (mediu) constant. Astfel,timpul de acces la un clement din abel nu depinde de numarul 4c elemente care sunt in tabela. In acelasi timp, tabela de repartizare nu foloseste neapfiat alocarca inliguita (ca arborele binar). Aceasta face ca tabela de repar- tizare si fie rapid in practic’. Un alt avantaj fai de arborele binar de e¥utare este c& elementele stocate in tabela de repartizare nu trebuie si implementeze interfaja Comparable. Acum probabil cd vi intrebaj: bine, dar dacd tabela de repartizare este atit de eficienti, de ce se mai folosec arbori binari? Rispunsul este c8 arborii binari, desi au operafi de inserare gi acces eare se execu in timp logaritmie dispun de operafii pe care tabele de repartizare nu le suporti. Astfel, ru este posibil si parcurgem eficient elementele dintr-o tabeli de repartizare Practic, tabelele de repartizare ofer% un suport eficient pentru numai trei ope- rai: adgarea unui element, stergerea unui element si ciutarea unui element. Parcurgerea elementelor, calculul minimului sau maximului nu sunt suportate. 83 106. TABELE DE REPARTIZARE Figura 10.15: Modelul pentru tabela de repartizare: orice element etichetat poate fi adiugat sau ster in timp practic constant inser’ find, remove Tabeld de repartizare Interfaja pentru tabele de repartizare Simport exceptions .¢; i/ee Interfata expusa deo tabela de repartizare. Ofera 12 operatii de adaugare, stergere, coutare si golire. «/ Spublic Interface HashTable x 1 yold inseet(Hashable x): + Yold remove(Hashable x) throws ItemNotFoundException Mashable find (Hashable x) throws ItemNotFoundExcey void makeEmpty O: " Operate permise asupra une tabele de reparizare snt date in Figura 10.13, iar o interfyé este prezentata in Listing 10.23, In acest caz,insera- rea unui clement care este dupicat nu genereaza o excepfie,deoarece clemen- tol va fi infocuit cu noua valoare. Aceasta este 0 altemativa la metoda pe care am aplica-o in cazularborilorbinari de ciutare. ‘Tabela de reparzare functioneazii doar pentru clemente care implementeaza interfaja Hashable*. Interfaja Hashab1e (Listing 10.24) expune o functie de repartizare, care aso- ciazi obiectului de tip Hashable un mumarintreg. Fecare dintre elementele coninute de o tabel de epartizare va fi asociat makempty Qs = 5 /es Goleste tabela de repartizare, si elibereaza toate us referintele din tabloul elements. «/ lie void makeEmpty() a 5 currentSize = 0: % for (int i = 0; i < elements. length; i+4) » elements fi) md > MN (ex Intoarce elementul cu chela x-hash() Xs @rhvows TtemNorFoundException daca elementul mu ¢ gasit +/ public Hashable find (Hashable x) i throws, ItemNotFoundE xeeption mt Int currentPos = findPos (x): hs assertound(currentPos, “Element negasit): {return elements [curreatPos |. element oo DD fee Verifica daca elementul de pe potitia currensPos bf Grhrowe ItemNotFoundbxception in caz contrar +/ 87 106. TABELE DE REPARTIZARE vate vold assertFound(int currentPos . String mess throws, ItemNotFoundException ) if (elements [eurrentPos == null II clements [eurrentPos |. isActive fl throw new ItemNotFoundException (message) false) ) fue Sterge clementul x din tabela de repartizare Gthrows ltemNorFoundException daca x mee gasit. 4/ public vold remove(Hashable x) throws, ItemNotFoundException int currentPos = findPos (x): assertFound(curreatPos , “Element aegasit”) clements [currentPos ].isActive = false: ) fos Adauga clementul x tabelei de repertizare. Daca ste linge gradul de incarcere marina adit te * dubleaza numarul de elemente din elements */ public vold. insert (Hashable x) i Int currentPos = findPos (x) elements [currentPos | = new HashEntry (x, true): if (s+ currentSize < elements length / 2) i Mdimensinnen tobstei este pree mice Wi" pot aparea conflicte, deel vom duble mumarul de elemente MashEmtry {] oléElements = elements: Uereara un tabel de dimensinne dubla elements = new HashEotry (oldElements. length } : currentSize = 0 Heople vechiul tabel in cet now Tor(int i= 0; 1 < oldElements length: i++) if (oldElements [i] != mull && oldBlements (i. isActive) i insert (oldElements [i]. element); 106. TABELE DE REPARTIZARE fee Asociaza un numar unic unei chei de tip String Seu valoarea intre Osi tablesize—I. #/ toe public static Int hash(String Key, at tableSize) int hashVal = 05 fe for (int i= 0; i < key. length Qs +4) mt re hashVal = 37 « hash: an) hn hashVal hr Hf (ashVal < 0) mt te hashVal » return hashVals my bel + key chara (i): tablesize: tablesize: ProbingHashTable este clasa cea mai important in implementarea tunei tabele de repartizare, Ea implementeaza interfaja HashTable gi de- fineste toate operaiile expuse de aceasta. Elementele din tabela de repartizare sunt rejinute intrun sir de obiecte de tip HashEntry (atributul elements). Structura mai specifica de asemenea si numa de elemente care sunt stocate la ‘momental curent(atributul current Size), Inserarea unui element in tabela de repartizare presupune asocierea unui rnumar unie respectivului element, prin intermediul metodei hash(). Acest rnumir devine indicele elementului in sirul element s, motiv pentru care acce- sul in timp constant este asigurat. Practic, prin inserarea elementelor in tabela de repartizare,sirul elements, care rejine aceste elemente, va fi popula intr- tun mod discontinuu (elementele nu se vor afla pe pozitii suceesive, pentru c& pozijia lor depinde de valoarea lor). Cand se va face clutarea elementului, se va realiza operatia de hash () prin care se objine numlrul asociat, si se va accesa direct elementul de pe pozia calculati. Evident, accesul este in timp constant ‘Metoda hash () calculeaz’i numiiul asociat unui element pe baza unui al- goritm simplu, Se realizeazi o sumi de produse pe baza codului Unicode al flecirui caracter din cheia elementului care va fi inserat in tabeld, iar in final se consider restul imparjirii acestei valori la dimensiunea tabelei, pentru ci 89 106. TABELE DE REPARTIZARE Listing 10.28: Clasa Qua: «package datastructures: s/ee Tabela cu repartizare patratica inchisa. Implementeaza metoda hs abstracta findPor() mostenita de la Probingiashtable +/ ipublic class QuadralicProbingTable extends ProbingHashTable a ticProbingTable protected Int findPos (Hashable x) at 1 int collisionNum = 0: Sint currentPos = x,hash(array length ): white (array [curteatPos | != mull && t array [curtentPos ]. element. equals (x)) ® i “ collisionNum +4; e curtentPos += 2 + collisionNum — 1 eI it (currentPos 5 ( ° curremtPos : ) arcay length) = array -Jength = return currentPos rnumrul asociat elementului trebuie si fie mai mic decét dimensiunea tabelet (numarul nu este altceva decdt un indice al girului element's). 10.6.1. Tratarea coliziunilor Este important si observim faptul ei metoda hash () nu ne asigurd de faptul e& obiecte distince vor avea repartizari distincte. De fapt, exist sanse considerable ca pentru doui elemente diferite, metoda hash () si returneze acelagi numir. Aceasta este o situafie inacceptabili, pentru ci nu putem avea dou elemente care si fie pe aceeasi pozitie in girul elements. Din acest motiv, avem nevoie de o strategie care si elimine coliziunile care pot si apara. Strategia va determina daci numirul asociat de metoda hash () este deja ocu- pat si va oferi un alt numér care nu a fost alocat anterior. Aceasta strategie va fi utiliza’ att in operajia de adaugare, ct si in cea de clutare a elementuli 90 106. TABELE DE REPARTIZARE Exist mai multe strategii disponibile, care se bazeaza pe clutarea unui spajiu neocupat in sirul elements. De aici provine gi numele clasei Pro- DingHashTable. Cu alte cuvinte, in caz de coliziune, se probeazd ele- ‘mentele din sirul @Lement's, pana se descopers unul neocupat. Pentru a oferi suport pentru implementarea oricSrei strategii, am decis ca ProbingHashTable si declare abstract metoda care trateaza situaiile de coliziune (este vorba despre metoda £indPos ()), motiv pentru care si clasa devine abstract, urmand ca fiecare strategie si defineasciiaceasti metoda int-o clasi derivati separati. ‘Cea mai simpli strategie pentru evitarea coliziuni este probarea liniari, cu alte cuvinte ciutarea secventiall (element cu element) in gir, pani se giseste © celuli goali, care si fie alocati elementului in cauzi. Performanta acestet strategii nu este ridicatS, mai ales in situajia fn care avem o tabelX de dimensiuni strategie mai performanti este cea patraticd, in care cAutarea nu se face liniar (i, i + 1,4 + 2,4 + 3ete.),cain exemplul anterior, ci in "salturi™ mai maridetipuli,i + 12,4 + 22,4 + Sete, Acesta este motivul pentro care clasa care defineste metoda £indPos () poarti numele de Quadratic- ProbingTable (quadratic == pitratic). Deoarec ‘mentul nu va fi pus pe pozifia data de funcyia de repartizare ci pe locayia liberi gisitt prin probare, ciutarea unui element va trebui ficuti tot prin probare, deci tot utilizand metoda £indPos (), apelati la linia 40 in cadrul metodei find () din clasa ProbingHashTable. Astfel, ciutarea se va oprifie cand elementul este gist, fle cAnd s-a ajuns Ia o locatie goal in element s. O alti observajie important este cd tergerea unui element au va putea fi realizati prin setarea pozifici care fi corespunde in elements la nu11, deoarece aceasta va ‘impiedica gisirea elementelor cu aceeasi valoare a funcjiei de repartizare care ‘au fost agezate prin probare dupa element sters. Acesta este motivul pen- tau care slergerea unui element se face prin setarea atributului isAct ive la false. Listing 10.29 prezinta un exemplu de utlizare al tabelei de repartizare, Exist foarte multe modalitiji de a implementa tabelele de repartizare. Noi ‘am prezentat aici doar una singur, numiti repartizare pitraticd inchis’. Pentru © detalii referitoare la acest subiect recomandiim excelenta lucrare Data Siruc- ‘ures (vezi [Tomescu)) cexzul unit conflict, ele Listing 10.29: Exempla de program care foloseste tabele de repartizare; pro- gramul va afga: Gasit Marcel Import datastructures = import exceptions -+ 91 107. COZ DE PRIORITATE ales Clas ‘public mpla de test pentru tabelele de repartizare. +/ '¢ TestHiashTable public static void main(String [1 ares) 1 | HashTeble b= new QuadeaticProbingTable () | MyString result = null: te heimsert (mew MyString(*Marcel"))s so eesult = (MyString ) h. find (new MyString ("Marcel )) System. out. printin("Gasit "+ result): Hoy eaten (IlemNotFoundException e) > 1 System. out. printia , > “) Marcel nu a fost gasit*); 10.7 Cozi de prioritate ‘Si pornim de la o problema concreti extrem de simpli: ordinea de tiparire ‘ documentelor la © imprimanta partajata, in cadrul unei refele, de un numar mare de utilizatori. In mod obisnuit documentele trimise unei imprimante sunt agezate, int-o coada simpld, dar aceasta nu este intotdeauna cea mai bun’ vari- anti, De exemplu, un document poate si fie deosebit de important, deci el ar trebui executat imediat ce imprimanta este disponibila. De asemenea, dacd imprimanta a terminat de tiparit un document, iar in coada se alfa citeva do- ‘cumente aviind 1-2 pagini si un document avind 100 de pagini, ar fi normal ‘ea documentul lung si fie tiparit ulimul, chiar daci nu este ultimul document Analog, in cazul unui sistem multiutilizator, sistemul de operare trebuie si ctementsti1 = otdetements I: ah a0 fee Intoarce elementul minia din ansomblu hh # @ohroms UnserflowException Daca ansamblul este gol +/ {public Comparable findMin() throws UnderflowException ( iF isEmpty 0) i throw new UnderflowException ("Heap vid") an) Sf Clorder0K) so EB fixHleap (): aan % return elements [1]; m4 m fee Transforme strut elements tntr—un ansamblu filtrand sot toate modurile care mu sunt frunze pena ajunge la radacina +/ ‘si pelvate yold fixHeap() mt | for (int i= currentSize / 2; 4 > 0: mt 5 percolateDowa (i): mo orderOK, 1 i Jes Biltreaza elemental de pe pozitia hole azezan: tt aubarborele cu radacita hole la local euvente +7 to private yold percolateDowa(int hole) mt int child: Comparable imp = elements (hole }: te while(hole + 2 <= currentSize) 101 wt ' child = hole + 25 hs it (ohild t= currentSize && rs elements {child + 1].compareTo(elements [child ]) < 0) 5 fi 5 ehildes, ™ rs if (elements {child ].compareTo(imp) < 0) mf 5 elements [hole] = elements [ehild]s ef , 5 else rm i oe break: ) me hale = ehitd my vb» elements [hole] = tmp: wy a fee Sterge clementul minim (flat pe positia I!) +i to + apeleaza algoritmul de filirare pentru a reface ansamblul tu + Gthrows UnderflowException daca ansamblul este vid. +/ 1s public Comparable deleteMin() throws UnderflowException wt Wo Comparable minliem = findMin()s tw elements (1] = elements {currentSize—— ‘percolateDowa (1); 9) return minitem; my te fee true daca ansamblul este vid +/ my return currentSize ta es Goleste ansamblut setend dimensiunes la O+/ 9 publle. void makeEmpty() wt fs curremtSize = 0; my eal 107. Coz DE PRIORITATE Pentra a testa ansamblul, am creat urmitorul exemplu simplu: Listing 10.32: Exemplu de utilizare a unei coz de prioritii, Programul va afisa: Continutul ansamblului: 0123.4 import datastractures = dimport exceptions + t/a Clasa de 16st simpla pentru coz de priorirare. +/ Spublic class TestPriority Queve “at {public static void main( Su 20) ares) lorityQueue pg = new BinaryHeap * rnew Integer(Integer -MINVALUE}): 2 pa Integer (4))5, » pa nteger(2))5 he pqvinsert (new Integer (1)): % pqcinsert (new Integer (3): “ pazinsert (new Integer (0)}: System. out. print("Continutul ansamblului ony » Ber css) fi 5 System. out. print(pq. deleteMin () +" uy sy % cateh(UnderflowException e) > so 2 ») Rezumat ‘Am prezentat pe scurt in cadrul acestui capitol cele mai importante steuctusi de date utilizate de programatori in practicd. Fiecare structuré de date oferi o interfaji clari cu toate operajile pe care le permite, implementarea ei putind fi ficutd in mai multe moduri. Stiva gi coada sunt structuri de date elementare, ‘care ofer operaji de adaugare respectiv stergere la un singur capat in timp ‘constant, Listele inkinguite permit operajii de adiugare si stergere arbitrare $i ‘au avantajul faja de siruric& inserarea unui element nu implica deplasarea ele- mentelor alate la dreapta. Arborii binari de clutare permit inserarea, cdtuarea 103 107. COZ DE PRIORITATE si stergereaf timp logaritmic. Ei oferd de asemeni o modaltate de a parcurge in ordine elementele conjinute. Tabelele de eparizare permit o implementare extom de efcienti a operailo de inserare si egisire. In sii, cove de pri- ortate permit opera asupra elementului minim (sau maxim) din cadralstruc- turf timp fogartmic, Ele au avantajl fala de arbor binar (are permits ei acelag cra) c& sunt mai simplo de implementat si nu implicit reinerea de legituri cite fi din sting si dreapta, Structure de dae reprezineo disciplina de sine stittoare, iar noi nu am putt aici decit si oferimo introducere in acest domeniv, Cei are doresc safle mai molte sont invitai st parcerga [Tomescu) $i {Cormen} fncepand cu urmatoral capitol, vor fi prezenate metodelefundamentale de elaborate a algortmior. Prima dintre ele este metoda cAutri cu revenie (back- tracking). Nofiuni fundamentale ansamblu binar: o varianti de arbore binar complet in care un nod este fie ‘mai mic fie mai mare dec fit si. arbore: structuri de date formati dintr-o multime de noduri gi muchit (fo- losite pentna a lega nodurile intr ele) astfl ineat nu existé noduri eare nu sunt legate direct sau indirect gi nu se pot realizacireuite ‘arbore binar: arbore in care ficcare nod are cel mult doi fi, arbore binar de cutare: varianti de arbore binar care suport eficient operajii de adaugare, stergere si ciutare, Fiul din stinga este mai mic decat Parintele, iar ful din dreapta este mai mare. clasi iterator: tip de clasi care permite manipularea unei liste ‘coadi: structurd de date care permite accesul doar la cel mai vechi element adiugat coadii de prioritifi:structuri de date care permite accesul doar la elemen- tul eel mai mi frunzi: intr-un arbore, reprezinti un nod fia fi funetie hash: funcie care caleuleaza pe baza unui obiect primit, un intrez care va fi asociat cu obiectul respectiv. Doar obiectele care implementeaza in- terfaja Hashable pot fi folosite de aceasta functic tiv structura de date care permite accesul doar la cel mai recent element inserat. structurd de date: o reprezentare a unor date si a operasillor pe acele date. Prin intermediul structurior de date se poate objine reutilizarea componentelor. tabelii de repartizare (hashtable): structuri de date care permite adiugai, slergeri si ciutaei ince-un timp mediu constant. 108 107. Coz De PRIORITATE Erori freevente I. Se consider eroare, incercarea de a accesa sau sterge elemente in cazul in care stiva, coada sau coada de priorititi sunt vide. 2. O coadi de priortaji nu are nici o legituri cu 0 coada. Este doar o coin- ceidengé de nume. 3. Funcfia hash () pentru o tabeld de repartizare returneaziio valoare de tip nt. Este posibil cain timpul calculelor intermediare si se product de- piri, agadar este necesar si se verifice ca rezultatul operatorului modulo si fie pozitiv. 4, Performanya unei tabele de repartizare se degradeazi semnificativ pe mi surlice factorul de incdrcare se apropie de 1.0. Mari dimensiunea tabelei de indata ce factorul de incdrcare a atins valoarea 0.5 Exercitii Pescurt Aritati care sunt rezultatele urmitoarei secvente de operaji: adauga (6) adauga(12), adauga(2), adauga(7), sterge(), ster ge () in cazul in care operatiile adauga() si sterge() corespund ‘operatillor de baz’ pentru: (a) stivas (6) coada; (©) arbore binar de ciutare; (@) coada de priori 2, Desenafi arborii binari de citutare de de chei (1,5, 8,9, 12, 17,29)! a 5 516 pentru muljimea 3. Scrieti ordinea nodurilor rezultata pentru parcurgerea in preordin« dine si postordine a arborilor de clutare de Ia exercitiul precedent, 4. Si presupunem ci avem numerele de la I la 1000 fntrsun arbore binar de clutare si ci dorim si cutim numarul 363. Care dintre urmatoarele seevenfe nu poate constitui o seeven{a de noduri examinate? (a) 2,252, 401, 398, 330, 344, 397, 363; 105 107. COZLDEPRIORITATE. (b) 924, 220, 911, 244, 898, 258, 362, 363; (©) 925, 202, 911, 240, 912, 245, 363; (2) 2, 399, 387, 219, 266, 382, 381, 278, 363; (©) 935, 278, 347, 621, 299, 392, 358, 363. 45, Desenaji ansamblal care rezulté in urma inseririi elementelor 47, 28, 19, 6,15, 12,3, 5,9, 14 fnte-un ansambluinigial vid! Teorie 1, S& presupunem c& am implementa coada din paragraful 10.3 far a aseza clementele circular. Gasiti o seeventa de operafi, care repetat la infnit ‘conduce la maitea nedefinitda tabloului elements, chiar daci in coada sunt doar edteva clemente. 2, Si presupunem cd dorim o structurii de date care si suporte doar uemi- toarele operaji: addugare, gsirea maximului si stergerea maximului, Cat de eficient pot fiimplementate aceste operatii? Indicafie: Se utlizeaza un ansamblu in care ridicina este mai mare decat, fii 43. Existi o posibilitate de a implementa urmitoarele operafi in timp logarit- mic in cadrul aceleiagi structuri de date: gisire minim si maxim, stergere ‘minim si maxim, adaugare? Indicatie: Se utilizeaza un arbore binar de cdutare 4. Exist posibltatea de @ implementa urmatoarele operat in timp con- stant: push, pop si gésirea minimului? Indicafie: Se observ ci nu se cere gi stergerea minimului, Putem astfel utiliza dous stive, una care refine clementele structurii de date, iar alta ‘care refine valorile minime, 5. De ce in cazul metodei findMin () din clasa BinarySearchTree nu a fost nevoie sa salvim valoarea parametrului t, care este modificat de cétre metodi? 6, Profesonul Stietot are impresia ci a descoperit o proprietate remarcabil 1 arborilor de ciutare, Si presupunem ci o e&utare pentru cheia intr un arbore de edutarese termind int-o frunzi. Considerim urmitoarele ‘muljimi: A: nodurile din stanga drumului parcurs pan’ la k, B: muljimea rodurilor aflate chiar pe acest drum si C, muljimea cheilor din dreapta 106 107. Coz De PRIORITATE drumului. Profesorul §tietot susfine c& toate cheile din A sunt mai mici decat cele din B, care sunt la randul lor mai mici deeat cele din C. Dati ‘cel mai mic contraexemplu care si spulbere afirmayia lui Stietot! 7. Care este numieul minim si numéral maxim de elemente fatr-un ansam= blu cu inalyimea h? 8 Aria chun ansambla cu 1 clemente ae ndkmea (logan! 9. Unde poate st se afle cel mal mae element intr-un min-ansambi? 10. Un tablou cu elementele ordonat creseitr este unansamblu? 11, Secventa47, 28,19, 6,15, 12,3,5,9, 14 este un ansambla? In practics 1. in paragraful 10:2 am vizut cum se poate implementa o sti folosind un sir penira a refine elementele. Implementai acum stiva folosnd clasa Linkedtist din paragraful 104 si un iterator special, care permite doar operate specific stv 2. in paragraful 103 am vizut cum se poate implementa ocoadi folosind un sir penis a refine elements, Implementaji acum coada folosind clasa Linkedtist din paragraful 10.4 si un iterator special, care permite doar operate specifice cori 3. Serieli o metod care afigeazs clementele dintr- list in ordine invers Pentru aceasta definigi un iterator care parcurge lista si depune fiecare ‘element inte-ostivl, Dupé ce lista a fost parcursi se vor scoate elementele din stiva pani cand aceasta se goleste, Proiecte de programare 1. fn paragraful 10.6 am vazut cum se implementeaza o tabeld de repart za utlizind un tablow pentru a rejne elementele. in cazal unui conflict, (doui clemente care sunt repantizate in acelasi loc) uilizam 0 funejie de repantizare pitratic’ pentru a gist o porte liber in cares inserim noul clement, Existé si o alts posibiltate de a gestiona contlictele: ficcare clement al tabloului elements este de fapto list inlinjuts. Astfel, conflictele se vor ezolva agez.ind elementele suecesiv in eadral liste in- Linquite Seriio clasi Chainediashtable care implementeaz¥ in- terfaa Hashtable folosind metoda deserisé anterior 107 11. Metoda Backtracking Ab uno disce omnes (Dupi unl fi oti judeca pe toi). Vergiu, Eneida Prima metoda de elaborare algoritmilor pe care 0 vom prezenta este back- tracking. Aceasti metoda este uilizabil& pentru un eadru larg de probleme, iar ‘modul ei de aplicare este aproape algoritmie, Dintre toate metodele de elabo- rare prezentate, backtracking est considera a fi cea mai elementar, deoarece ca se reduce lao parcurgere exhaustiviintligentéa spajului de clutare si nece- siti cele mai pujine adapt ale formei generale penta afi aplicatin probleme concrete. Discusiaasupra acestei metode incepe eu o prezentare a cadrului in care ea poate fi uilizaté schema general de rezolvare a problemelor backtracking, urmata de citeva exemple clasice in care aceasti metodi se aplic. fn cadral acestui capitol vom prezena «8 principiilor esentiale care stau Ia baza ei. Vom da apoi + Care sunt problemele cirora li se poate aplica metoda backtracking; + Ce sunt conditile interne si conditile de continuate, si cum influenjeazi acestea eficienja unui algoritm backiracking: # Care sunt cei patru pasi care se aplict start objineri soluyilor; ale a probleme in vederea © Care este schema generalii de rezolvare a problemelor backtracking si ‘cum se particularizeazi ea pentru diverse probleme concrete; + Exemple clasice de probleme care admit rezolvare prin aceast metod. 108 11.1 Prezentare general fn practic apar adeseoristuai in care rezolvareaunei probleme se reduce in ese la determinarea unor vector de forma: © = (41, 42,..-50n) unde: « fiecare component xj apargine unei multimi finite Vis ‘© componentele vectorului x respect anumite relagii, numite condi in- teme, astfel incat x este 0 solutie a problemei daci si numai daci aceste ‘conditi sunt satisficute de componentele 21, :22,.--, 2 ale veetonului Produsul cartezian Vi x Vz x ... x Vq 8© numeste spatial soluiilor posible. Elementele acestui produs cartezian care respecta conditile inteme se numese soluti ale probleme Exemplul 1: Fie dou muljimi de litere Vi = {4, B,C} si Vs = (M.NN}. Se cere si se determine acele perechi (z1,.r2) avand proprietatea cX daci 21 este A sau B, atunci 22 nu poate fiN. ‘Rezolvarea problemei de mai sus conduce la perechile: (A, M),(B, M), (C,M),(C,.N) deoarece din cele gase solutii posible, doar acestea indeplinese conditile puse {in enunjul problemei, Exemplul 2: Se di muljimea cu elementele {A, B,C, D}. Se cere sii se genereze toate permutiile elementelor acestei mulfimi. Se cer asadar evadeu- pletele de forma x = (21,:r2, 225,24) care respect condigile on A x; pentui xj; © 2; apartine muljimii V = Vi = {A,B,C,D}, 1 = 1,2,3,4. Existi mai multi vector ce respeoti aceste condi: (A, B, C, D}, {B, A,C, D}, {B,C, D, A}, (B,D, A, C} etc. Mai exact, numarul de permutiri ale elemen- telor unei mulfimi cu 4 elemente este 4! = 24 (© modalitate de rezolvare a problemei ar fi si se genereze toate cele 4 256 elemente ale produsuluicartezian Vi x Vo x Vs x Va (reprezentind solutile 109 11.2. PREZENTAREA METOD posible) si si se aleagi dintre ele cele 24 care respecti condiile interne. Si ‘observim insi cX daci\ in loc de 4 elemente mullimea noastri ar avea 7 elemente, vor exista 7? = 823.543 variante posible, dintre care doar 7! = 5040 (adic doar 0.6%) vor respecta condifjile interme. Aceasta inseamnd ck 99.4% dintre variante sunt generate inutil. Din cele aritate mai sus reiese ci are sens si ne punem problema de a gisi algoritmi mai eficienti, care si evite generarea brutali a intregului spafiu de solufii pentru a selecta apoi solufile care respect conditile interne. Metoda backiracking este 0 metoda foarte importanti de elaborare a algoritmilor pentru problemele de genul celor deserise mai sus. Desi algoritmii de tip backtracking au gi ci, in general, complexitate exponential, sunt totusi net superiori unui algoritm care genereazi toate solusile posibile. 11.2 Prezentarea metodei ‘Asa cum am vazut in paragraful anterior, metoda backtracking urmareste sit evite generarea tuturor solujiilor posibile, reducand astfel drastic timpul de calcul ‘Si vedem acum care este modalitatea prin care backtracking genereaz’ solufile, evitind parcurgerea exhaustivi a spasiului de ciutare. Componen- tele vectorului x primese valori in ordinea erescitoare a indicilor (vom nota aceste valori cu U1, 2,--;Up cu scopul de a face diferentaintre 0 component’ care nu are o valoare atribuit’, xp, si 0 component’ care are atribuitd o valoa- re, Ug). Aceasta inseamn’ ci lui x, nu i se atribuie o valoare decat dup’ ce 71,22,-+-,2k-1 au primit valori. Mai mult decdt atit, valoarea vg atribuita lui zy Va trebui astfel aleast incdt vy, v2,...,0p si respecte anumite conditi, rnumite condi de continuare, care sunt deduse de cite programator pe baza conditiilor interne. Astfel, daca in Exemplul 2, prima component, a primit valoarea v, = A, este clar cd lui zr nu i se va mai putea atribui acceasi valoare (clementele unei permutatitrebuie si fie diferite). "Neindeplinirea condiiilor de continuare exprima faptul c& oricum am alege valorile pentru componentele 4,.1,---,2in, nu Vom obfine nici o solutie (deci ccondijile de continuare sunt strict necesare pentru objinerea unei solufii). Prin ‘urmare, se va trece la alribuirea unei valori lui z~, doar daci condifile de con- \inuare pentru componentele 21, 2,..-, (avand valorile v1, v2,-..;Ue )sunt {ndeplinite, in cazul neindepliniti condijior de continuate, se alege 0 nous va- Toare pentru zp sau, in cazul in care muljimea valorilor posibile, Vg, a fost epuizati, se Incearci si se faci 0 nowi alegere pentru componenta precedenta, 74-1, Vectonului, micgorand pe k cu o unitate. Aceasti revenire a componenta 10 PREZENTAREA METODEL precedent di numele metodei, exprimand faptul eX daci nu putem avansa,ur- smirim (engl. track = "a urmir")inapoi (engl. back = "Inapoi”) seeventacurentt din solufe ‘Trebuie observa faptul ci respectarea condfilor de continuare de ere va Jove 22, -., 04 mu reprint nicidecum o garanfeafaptuluic vom objine o soluje continuand chutarea cu acest valri, Dec conde de continuare sunt condi necesare pentru ca, U2y...,Uk sf conduc la 0 soluje, dar nu sunt neaparat condi sufciente. ‘Alegerea condijilor de continuare este foarte important, o alegere bunt ducdnd lao reduceresubstanfialé a numirului de calcute. fn cazul ideal, acest condi ar ebui si fe nu numai necesare, ci chiar suficiente pentru objinerea unei solufi, ceca ce ar garanta ef toate seevenfele vy, U2... 0s generate Vor conduce in final lao solusc. in practic acest ueru nu este adeseori posibil, de aceea se urmirest gisiea unor condi de continuare care si fie eft mai “dure”, adic si elimine din start cit mai multe soli neviabile. De obiei,condiile de continuare reprezntirestricjia condijlor interne a primele k componente ale vectorului, Evident, condile de continuare in eazul k=n sunt chiar condiile interne. De exemplu, o condije de continuate fn cazul problemei permutirilor din Exemplul 2 arf ve #0,Vi= 1-1 Prin metoda backtracking, orice vector este construit progresiv, incepfind cu prima component $i mergénd citre ultima, cu eventuale reveniri asupra valo- rilor atribuite anterior. Reamintim c8 2,22, 22, primese valori in multimile Vi,Va,-.-,Va- Prin atribuiri sau incerciri de atribuiri eyuate din cauza ne- respectirii conditilor de continuare, anumite valori sunt consumate, Pentru 0 componenti oarecare 2 vom nota prin C mulfimea valorilor consumate Ia ‘momentul curent. Evident, Cy C Vi ( deseriere completi a stiri in care se afla un algoritm backtracking Ia un ‘moment dat se poate face prin precizarea urmatoarelor elemente: 1. componenta din vector Ia care s-a ajun: valoarea k; procesul de cdutare, avand 2. valorile v1,v2,-.-;Ue—1 care au fost atribuite primelor k — Ieomponente ale veetorului 2; 43, muljimile de valori C,, Ca, ..-,C care au fost consumate pentru com= ponentele v1,U2,-..,Uk-1 $i pentru componenta curentl, 21. nt 1.2. PREZENTAREA METODEL Aceasti descriere poate fi sintetizati tntr-un tabel numit configurayie, avand Thy Testy Tn ) ‘uemitoarea forma: ( Diyos ka CryresCer | Crrdsnd ‘Semnificayia unei astfel de configuratii este urmitoarea: 1. in incercarea de a construi un vector solujie a problemei, componentelor 4,2, set Hi S-aU atribuit valorle U1, 25---5 Ue 2. aceste valor satisfac conditile de continuare; 3. urmeazi si se atribuie o valoare componentei 24; deoarece valorile con- ssumate pind in prezent sunt cele din muljimea Cy, componenta xq va putea primi o valoare vy din Ve — Cys 4, valorile consumate pentru componentele 21, 2,..-, sunteele din mul- limile Cy, Cs, ..., Ck eu precizarea cd valorile eurente v1, 25--- Uk-1 sunt consumate, deci apar in mulfimile C1, 2... Chat! 5, pentru componentele 2441,-.-,n nu s-a incereat nici o atribuire, deci ru s-a consumat nici o valoare si, prin urmare, Cyy.15.--+On sunt Vi 6, pind in acest moment au fost construite eventualele solusii de forma: # (cover € CL = fork: © (v1se2).-.) eu 62 € Ce ~ {va}: © (1st, HB, Chats) CH CHa € Char — (oe cu eg € Ces © (Way tay thas eey Aceasti ultima afirmatie este mai dificil de incles si recomandim reluarea ei dup lectrarea exemplului de mai jos. {in construitea permutivilor mulfimii cu elementele (A, B,C, D} din Exe cemplul 2, pentru k = 4, configurajia c AaB 4 ( {A,B, 0} {A} {A,B} | (4, B} ) are, conform celor artate mai inainte, urmitoarea semnificayie: 1, componentele 21, 22,23 au primit respectiv valorile C, A, 12 12. PREZENTAREA METODEL 2. tripletul C, A, B satisface conditile de continuare; 43. urmeazii si se atribuie © valoare componentei x4. Componenta 24 ia valori din muljimea Vs ~ Cs, adic& una din valoile (C, D}; {A}, Cs = {A,B}, Ca = {A,B 5. k+1=5 >, deci acest subpunct nu are obiect in aceasta situa 6. pind in acest moment au fost deja construite solusile de forma (in ordinea in care au fost descrise Ia punetul 6 de mai sus) © (Ay...) adie’ (A,B,C.D), (A,B.D.©), (A.C.BD),(A.C.D.B), (AD.B.O).(AD.CB) si (B, ...) adic4 (B.A,C.D), (B,A.D.C), (B.C,A.D), (BCD.A), (BD.A.O),(BD.CA): « soluji de aceasté forma nu exists, deoarece C2 ~ {v2} ‘© solujii de forma (C, A, A,.- ‘© solujii de Forma (C,A,B,A), (C,A,B,B): nu exist solutii de aceasti forma, ‘nu exist solutii de aceast forma, Metoda backrracking incepe a fi aplicata in situajia in care nu s-a ficut nici o aribuire asupra componentelor lui x, deci nu s-a consumat nici o valoare, si se {ncearcé atribuirea unei valori primei componente. Acest hucru este specificat prin configuratiainifala, a cirei forma este (EF) tmcate toate mubjmile C sunt vide Un alt caz special est els configurator solute, avind forma (aca) AB c D ( {A} {A B}{A, B,C} {A, B,C, D} ) 113 ( . ( 1.2. PREZENTAREA METODEL are semmnificatia ci veetorul (A,B,C,D) constituie o solujie a probleme. ‘Metoda backtracking consti in a porni de la configuratia initial si ai aplica acesteia una dintre cele patru tipuri de transformiri prezentate in continuare, pind ce nu se mai poate aplica nici o transformare. Fiecare transformare se aplicd in anumite conditii bine precizate: la un moment dat doar o singuri ‘ransformare poate fi aplicati, Presupunem ci ne aflim in configurajia descrisi anterior, in care s-au atsibuitvalori primelor k — 1 componente. Transformiile care pot fi aplicate unei configura sunt: atribuie gi avanseaza, incercare egu> ati, revenire,revenire dup’ construirea unei soluji. Le vom prezenta pe fiecare pe rind, 11.2.1 Atribuie si avanseazi ‘Aces tip de modifcare are loc atunci cind mai exstévalorineconsumate pentru componenta caren, 24, (deci CC. Va) iar valoarca leas, vx, ae Dropritateac& (0,.--, 4) respects conljile de coninuare. fn acest caz ¥a- loarea uy se asic li zy si se adaug’ multimii Cy, dupa care se avanseazi la componenta urmatoare, 2441. Aceastt modifiare a configurajet poate fi reprecentaié in fell urmito: Thy The "* ost Ue | Teeny Cy bees J Ca Cu tn) | de De exemplu, la generarea permutirilor, avem urmitoarea schimbare de con- figurate pornind de la stare iia: Cea 2304) “ ( 646 6)—\ia 73%) 11.2.2 fincereare eguatd Acest tip de modificare are foc atunci end, ca gi in cazul anterior, mai ex- {std valori neconsumate pentru componenta curenti, 2g, dat valoarea vy aleasi ‘nu respect condifile de continuare, in acest caz, vg este adaugata multimii Ce (deci este consumata), dar nu se avanseazz la componenta urmatoare. Modifi- crea este notati prin: se Uann | Zee teers ) era 1 CG, % seat | ky eH Cnr | CyU {ved 12. PREZENTAREA METODEL fnexemplutnosir cu generarea permutirlor, urmatoarea transformare este: ( ‘ay 11.2.3. Revenire 2 t9 24 ooo (as [83% ‘Acest tip de transformare apare atunci cind toate valorile pentru compo- nenta 2 au fost consumate (Ci, = Vi), deci nu mai avem alte posbiltii de a da valor acestei componente. In acest caz se revine la componenta precedent, 24-1. incercindu-se atribuirea unei noi valor: acestei componente. Este impor- tant de remareat faptu c& revenirea la 4-1 implicd faptul c& pentru ze se vor incerca din nou toate variantle posible, deci muljimea Cy trebuie din now s& fie vid. Transformarea este notat prin: comes | ete seeptce | thts Diyos vrOet | Ch dh. JAA\ Cha | Chas 6 (0 situatie de revenive, in exemplul cu generarea permutiilor este data de configurajia: 3 1 2 4 301 ( {1,2,3} {1} {1,2} | n.zk9 } {1,23} {1} fais) 11.2.4 Revenire dupa construirea unei solutii ‘Acest tip de transformare se realizeaziatunc cind toate componentele vee- torulué au primit valri care satisfac condiileinteme, adic a fost gisiti 0 solute. in aceassituatie se revine din nou lacazul in care ultima component, 2q urmenz si primeasci o valore. ‘Transformarea se notea asf: (sa) = ( 1s 1.2. PREZENTAREA METODEL fn exemplu nostacu generareapermutisilor,revenrea dup gisirea primei soluji este dati de disgramaz 192 3 4 sol 1 023 4 ( aho.9 0.23} 0.209)2-( {1} {1,2} {1,2,3} | {1,2,3,4} Revenirea dupi construirea unei solutii poate fi considerati ca flind un caz particular al reveniri, daci adiugim vectorului solujie x 0 component supli- mentari 2,41, care nu poate lua nici o valoare (Vasa = 9). © problema importanti este cea a incheierii procesului de cutare a solusi- itor, sau, cu alte cuvinte, ne putem pune intrebarea: transformarile succesive aplicate configuragiei initiale se incheie vreodata sau continual la nesfarsit? Evident c& pentru ca metoda backtracking s& constituie un algoritm trebuie 8 respecte proprictajile unui algoritm, printre care se afl si proprietatea de fini- tudine. Demonstrarea finitudinii algoritmilor de tip backtracking se bazeaza pe "urmitoarea observajie simpl&: prin transformarile succesive de configurasie nu este posiil ea o configurajiesA se repete, iar numrul de elemente al produsului ceartezian Vi x Vo x... x Vq este finit, Prin urmare, la un moment dat se va ajunge Ia configurajia: (#323) sumitd coniguraje fnala. tn configurajia de mai sus ar trebui i aibi loc o revenire (deoarece tate valorile pent prima component au fost consumale), adicl o deplasare a bareivericae Ia stings. Acest cra este imposbi, gi al- goriumul se incheie deoarece nici una din cele patra transformari nu poate ft aplicatd, in practic, aceastdincereare de a deplasa bara de pe prima porifie (de = 1) pe o posite anteriart (k= 0) este ulizatd pe post de condije de terminare a algoritmulu fnaime de rece la implementareaefetivi a metodei backiracking in pseu- docod, si generim diagramele de configuraie pentru Exemplul 1: 116 TS cay 2)=( deh) 2( ald) (dott )—( a3) ~( uns )~( uy) 2( cle) ai) N ( catss | ativy )—( si — 1)—(eote)#(uSeldh )— © ow Nef o | as ey (ascrunsy)2(1a8.0)| arn )—(aacs 11.3 Implementarea metodei backtracking Procesul de objinere a soluyilr prin metoda backtracking este usor de pro- gramat, deoarece la fecare passe modifcd foarte pujine componente (indicele k, reprezentind pozitia barei, componenta zy si muljimea Cy). Algoritmul (eris in pseudocod) de mai jos construeste configurajia ini’, dupa care aplict una dintre cele patra transforma deserise in paragraful anterior, pana cand se ajunge la configurayia final (adied pind ednd se incearcéo revenire de pe prima pozite initializeazit (citeste) multimile de valori,Vi,...5Vn REL f/se construieste configurayia inigiala /Jacum incepe efectiv aplicarea celor 4 transformari, functie de caz cit timp k > 0 //k =Oinseamna terminarea eeiutirié dacik = n+ Latunci [/configurasia este tip solujie refine solufia U4,..-Un keR-1 /frevenire dupa solujie alifel daca Cy, # Vieatunci | {mai existe valori neconsumate 7 11.3. IMPLEMENTAREA METODEI BACKTRACKING alege 0 valoare ve din Cx — Ve Ch =CeUve //valoarea vg este consumatit dacatvs,...,ve respect conditile de continuare atunci 2%; //atribuie si keR+; /favanseazt sift [fincercare esuata, mu fac nimic Cee kER-1 timp alifet Algoritmul de mai sus functioneazi pentru cazul cel mai general, dar este estul de dificil de programat din cauza lucrului cu muljimile C si Va Din fericire, adeseori in practic’ muljimile Vs au forma Ve (2-088) deci fiecare multime Vj poate fi reprezentats foarte simplu prin numarul stu de elemente, sy. Pent a simplifia si mai mult ucruril, ia cadrul procesului de construire a unei solusii vom alege valorle pentru fiecare component 2 in ordine crescatoare, pornind de la. 1 si pana la sp. fn aceast situa, mul de valori consumate Cy va fide forma {1,2,..-,0s} si drept consecin, va putea fi reprezentati doar prin valoarea vy CConsiderajiile de mai sus permit inlocuirea algoritmului anterior, bazat pe ‘mulimi, eu un algoritm simpliicat care lureaz’i numai cu numere. aca in Exemplul 1 vom conveni si reprezentim pe A, B, C prin valorile 1, 2, 3, iar pe M si N prin I si 2, configuratile care se succed in procesul de cchutare pot fi reprezentatesimplifiatastel a a J—(1 I a)—(1 2 |)2(1 | m2) Particularizarea algoritmului pseudocod prezentat anterior se concretizeaza {in urmitoarea metoda Java: Listing 11.1: Metoda backtracking lie void backtracking O int white (k i 4. PROBLEME CLASICE REZOLVABILE RIN BACKTRACKING ‘ I (k ==) Ham gastro solurie , i ' retSol(): //afisam soluria : Kia //revenire dupa gesirea anei solutii * 1, E fi ® Ie (x{k] < S{k)) /7mai sunt vatori neconsumate 5 t " Alk]44; //se ia urmatoarea vatoare 5 if (continuare(k)) //respecta cond. de cont? ® i f ket /avenseaca Metoda backtracking () foloseste inca dou metode: # metoda ret Sol ()., care, aga cum sugereaza si numele ei, refine solutia, constind in valorle vectorului x. Cel mai adesea aceasti metods realizea- 2 0 simpla afigare a solufiei gi, eventual, o comparare cu solutile gasite anterior; © metoda cont inuare (i) verificd daci valorile primelor k componente ale vectorului x satisfac condigile de continuare; in cazul afirmativ este returnati valoarea true, iarin eaz contrar este returnati valoarea fase. 11.4 Probleme clasice rezolvabile prin backtrack- ing 11.4.1 Problema generarii permutirilor Se dé muljimea A cu elementele {a,425...,an). Sa se genereze toate permutirile elementelor acestei mulfmi. Se observii ci aceasth problema este © simpli generalizare a Exemplului 2 din acest capitol. Mai mult decat atit, problema poate fi redusi la a gene- ra permutirile muljimii de indici (1,2,...,n}. fn aceasta sitayie vom avea 119 REZOLVABILE PRIN BACKTRACKING Listing 11.2: Funetia de continuare pentru problema permutirilor ‘public Boolean continuare(int K) at } fer (int i= 0; F< ks #4) . ot é ie Gxt) up c return false: Vi = V2 =... = Va = {1,2,....n}, deci putem aplica varianta simplificati a rmetodei backtracking. Condi interne pe care trebuie si le respecte un vector solujie sunt: aif zs pentuVija tim i#j Condifile de continuare pentru componenta numiirul k sunt 0 simpli res- tricjie a condifilor interne: 4 # ae pentru Vi = 1,k-1. ‘Codul pentru funcjia de continuare este prin urmare foarte simplu, dupa cum reiese si din Listing 11.2 Metoda backrracking pentru generarea permutirilor se objine din metoda backiracking pentru cxzul general, inlocuind numarul de elemente al muljimi- lor Vs(notat cu 84) prin valoarea n, Solujia completa a generarit permutaritor este prezentata in Listing 11.4. Pentru a citi mulfimea de elemente care vor fi permutate am folosit clasa ajutitoare Reader, prezentati in volumul int capitolul 4, paragraful Variabila sistem CLASSPATH. Reamintim inca o dat ccodul sursi al aceste clase. Listing 11.3: Clasa Reader «package tor 2 Helasa va trebul salvata introun director cu numele “io > Mdirectorul in care se afla “lo” va trebul adaugar 1 71m CLASSPATH 5 import java. io.+; © import java util. StringTokenizer; > public class Reader Ht 120 A PROBLEME CLASICE REZOLVABILE PRIN BACKTRACKING public statle String reads: ing 0) BufferedReader in = new BufferedReader new InputStreamReader (System in)); try t return in. readLine (): ) ceateh (LOException ©) i Wignore 1 yublic state int readint() return Integer. parselnt(readString ()): public 5 i return Double. parseDouble( readString ()): ’ |e double readDouble () public statle char readChar() BufferedReader in = new BufferedReader new InputStreamReader (System .in)); try i return (char)in. read (): ) ceateh (LOException ©) i Mignore 1 return "\0": public statle Int] readintarray () t String s = readString Os StringTokenizer st = new StringTokenizer(s): Haloca memorie pentru sir Int [] a = new Int[st-countTokens ()}: for (int i = 0: i < aclength: #44) t ay Integer. parselat (st nextToken ()) 14, PROBLEME CLASICE REZOLVABILEPRIN BACKTRACKING. » ey od Prin rularea programului urmitor se vor genera permutirile mulfimii intro- dduse de Ia tastatr’, Listing 11.4: Rezolvarea problemei permutirilor Import lo Reader: Nee i+ Program care genereaza permutarile unei multini 13 introduse de la tastature > public ue + fae Testeaza daca elementul adaugat exista deja.+/ Public static boolean continvare(int{] x, Int k) wt jars Permutari fh for (int i = 0; 1 < ki sei) ot m8 ar ate) == xt) ®t “ return false: aD “4 a . D fas Construieste un string care contine solutia curenta.+/ % public’ statte void retSol(int(] ss int{) x, dat neSol) » System. out. priat("Permutarea * + arSol + 7: * ): > for (int i = 0; i ¢s.length: 144) » t 3 System. out. print(stxti] — 1) 4° >) y System.out. priatin () + a Mo fe Mt # Backiracking standard pentru determinarea MS permutaritor mutrimit & publle statle vold backtracking (Int (J s) » 122 A PROBLEME CLASICE REZOLVABILE PRIN BACKTRACKING Int k = 0: “aloca memorie pentru sirul de indict Int [] x = new Int[s. length }: int nrSol = 0; Winitializeaza ® for (int i = 0: } < x.length; 44) nl ati ) Uprocesul de backtracking white (k >= 0) i ine t retSol(s,x,tenrSol) ; //afiseaza soluria Liat i/revenire dupa ceo solutie a fost gasita ) clse fi It (xk) < x.length) //vatori neconsumate? t M180 ia urmatoares valoare neconsamate xk Kclength) //am gasit 0 solurie respecte valoarea ateata ‘iconditia te connvare? i Ceontinuarets. ‘ k ’ 1 A[k==] = 0; //revenire 1 ) 1 f+ Programul principal. +/ public statte vold main(String {] args) ( Ueitirea etementetor multinit System out. printin("Introduceti elementele multimii “(pe 0 linie, separate prin spatiu):"): int [) = Reader readlatArray 0): Ugenerarea permuraritor multimit 123 14, PRORLEME CL REZOLVABILE PRIN BACKTRACKING backtracking (8): 50 eT 11.4.2 Generarea aranjamentelor si a combindrilor ‘Vom vedea acum eat de simplu se poate adapta algoritmul de generare @ permutirilor unei muljimi pentru a genera aranjamentele si combinirile acelei ‘muljimi, Pentru a simplifica luerurile, vom presupune ci muljimea A este for- ‘mati din primele n numere naturale, adiei A = {1,2,...,n}. Reamintim faptul c& prin aranjamente de m Iuate cate m (n > m), notate Am se injeleg toate muljimile ordonate cu m elemente formate din elemente ale ‘muljimii A, cu alte cuvinte tofi veetori de forma: 1m (21y---5tm) unde 2 € {12-5}, tA ay, Vis ‘Se observa ci, din punet de vedere al reprezentirii formale, singura diferen- |¥4dintre aranjamente $i permuttr este c8 aranjamentele au lungime m in loc de zn. De altfel, pentru m=n aranjamentele gi permuttirile coincid. Exemplu: Aranjamentele de 3 luate cite 2 (43) sunt: 12),0,3), 2,0, 2.3), BD, 2). Condiiile interne si, in consecingi, condifile de continuare sunt identice cu cele de la generarea permutirilor, Prin urmare si funefia de continuare este identici cu cea de la permutiri, Unde este totusi diferenja?. Avénd in vedere lungimea vectorului este m si nu n, conditia de gisire a unei solujii trebuie adaptati, Prin urmare,in metoda backtracking () linia: ink n) va fi inocuitt cu: irk =) Desigur, aceeasi modificare este necesar’ si in metoda ret Sol (), tn care secvenja for (int i= 0; 1 0 && sik] i k= return false: return true: ‘Sa vedem acum modalitatea de generare a combinarilor, Reamintim c& prin combiniri de m luate céte m (notat C72) se injeleg toate submuljimile eu m elemente ale maltimit A = {1,2,...,n} Exemplu: Combinirle de 3 late ete 2 (C3) sunt: 1.2).1,3),2.3) Diferenja tntre combinisi si aranjamente este dat de faptul e¥, in cazul combinarilor, ordinea in care apar componentele nu conteazii (combinarea (1,2) este aceeasi cu combinarea (2,1) etc). Din acest motiv am optat in exemplul de ‘mai sus si aranjm componentele unei combinari in ordine crescatoare). Prin uurmare, combinarile unei mulfimi cu m elemente luate cfte m sunt definite de vector: 25 (21-25 tm) unde 2 < 22 <1. < tm. Condijia de continuare in cazul combinsrilor va fi pur si simplu: 4 > 4-1 pentru k > 1 Metodele backtracking() si retSo1 () sunt, in cazul combinatilor, tice cu cele de la aranjamente. Diferenja apare la fun descrisi in Listing 11.5. Listing 11.6 prezinta varianta mai cleganta a aceleiagi func Problema 3 de la finalul capitolului propune o variant mai eficienti de ge- nerare a combinisilor in care funcfia de continuare este complet eliminat’. 125 REZOLVABILE PRIN BACKTRACKING Listing 11.6: Funefia de continuare pentru combiniri (varianta elegant) public Boolean continuare(int ) at > return i a 011 xtk] > xk = 1) Figura 11.1: Solusie de agezare a damelor pe tabla de sah ¥ 11.43 Problema damelor Sa se aseze n dame pe o tablit de sah de dimensiune nxn astfel Inedt damele sd nu fie pe aceeasilinie, aceeasi coloand sau aceeasi diagonala (damele st nu se atace intre ele). Reamintim ci in jocul de sah, o dam& "atacd” pozitile alate pe aceeasi Tinie sau coloani si pe diagonal. O posibilii ayezare a damelor pe o tabla de gah de Figura 11.1 ‘Si vedem cum putem reformula problema damelor pentru a 0 aduce Ia 0 problemi de tip backtracking. Se observa cu usuringi cl pe o Tinie a tablei de sah se poate afla o singuri dam, prin urmare putem conveni c& prima dama se va ageza pe prima linie, a doua dam pe a doua linie etc. Rezulti c& pentru a ‘cunoaste pozitia damei numirul k este suficient si lim coloana pe care aceasta, se giseste. O solujie a problemei se poate astfel reprezenta printr-un vector dimensiuni 4x4 este dat B= (21422,..-,2n), te Ee {1,2,.-..0}, unde 2g reprezinti coloana pe care se piseste dama numarul k Cu aceasti notatie, vectonul solujie corespunzitor exemplului din Figura este: (2,4,1,3) ‘Si vedem acum care este conditia ca douti dame distincte, kg, si se atace: «in mod cert damele nu pot fi pe aceeasi linie; # damele sunt pe aceeasi coloani daci 2 126 4. PROBLEME CLASICE REZOLVABILEPRIN BACKTRAC Listing 11.7: Funetia de continuare pentra problema damelor public boolean continuare(int k) ‘ 2 for (int i= 05 Fe ks 44h) | : fe (x()] == 1k] 1 kei == Math abs (xtkd-x14 19) ‘ i : return false: ‘ ) an] "1 # damele sunt pe aceeasi diagonala daci se afl pe colfurile unui patra, adici lungimea (|z4 ~ 2|) este egal cu lijimea (k — a): tke bea — a Conditia de continuare este ca dama curenti, k, si nu atace nici una dintre damele care deja sunt agezate pe tabla, adica: 4 #251 [te — 24 # [| pentru Vi = 18-1, ‘Transpusi in Java, funcjia de continuare are forma din Listing 11.7. Modificirile care trebuie aduse metodelor retSol si backtracking sunt minime gi le lisim ca exerciti. Observarie: Problema damelor este primul exemplu de problem in care conditile de continuare sunt necesare, dar nu sunt suficiente. De exemplu (pen- tru n=4), a inceput, algoritmal va ageza prima dama pe prima coloand, a doua ddama pe a treiacoloana, iar cea de-a treia dama nu va putea fi agezats pe nici 0 pozic, find necesari o revenire. 11.4.4 Problema coloririi harfilor Se dat 0 hart ca cea din figura de mai jos, in care sunt reprezen- tate schematic 6 fri, dintre care unele au granife comune. Pre- supundnd cat dispunem doar de trei culori (rogu, galben, verde), se cere si se determine toate variantele de colorare a haiti ast- {fel incdt oricare doud piri vecine (care au frontier comund) a fie ‘olorate diferit. 127 14, PROBLEME CLASICE REZOLVABILEPRIN BACKTRACKING. Figura 11.2: Matricea de vecinatayi corespunzitoare hai din partea sting’ Te nimiminl ott att -- 10 dO t Pentru a memora relajia de vecinitate intre dousi firi vom utiliza o matrice de dimensiuni 6 x 6, numita vecin, definita prin: _{/ true daca sisile 7; $i Tj sunt vecine vecintisl={ jfite Se Figura 11.2 reprezinta matricea de vecinitgi pentru harta cu 6 fri in care sa ficut conventia eI reprezint&srue si 0 reprezint false. Problema se poate generalizausor si lao hart cun ri care trebue coloraté cu mculosi. Vom utiliza pentru usurarea expuneriiharta cu 6 fei de mai sus. fn aceast& problema, un vector solujie 2 = (21,24...) reprezintd 0 variant de colorare a hit avind semnificaia cara numarul iva fi colorata cu caloarea zi. In exemplul nostru, 24 poate fi 1,2 sau 3, corespunziind respectiv culorilor rogu,galben, verde Conditia de continuare este ca fara cireia urmarim sii atribuim o culoare, sh aiba o culoare distinct de rile cu care are granif. Cu alte cuvinte, trebuie siavem 2, #4 dacd Ali, K)=1, Vi=1,k—1. Functia de continuare care deserie conditia de mai sus este data in Listing 118. Pentru o mai bund infelegere a mecanismului merodei backtracking aplicat 1a problema coloriei higilor, putem si ne imaginim e& dispunem de 6 eutit identice Vi, Vo,-.., Vy ficeare dintre cutii confindnd trei creioane colorate no- tate eu r-rogu, g-galben, v- verde. Fiecare cutie Vz confine ereioanele care pot fi uilizate pentru coloraea fri Ty (© vizualizare a procesului de eSutare a soluilor poate fi objinuti dacé aran- jiim cele 6 eutii in ordine (fecdrei tari fi asociem o cutie) si punem un semn ‘naintea cutici din care urmeaza si se aleagi un creion (marcajul corespunde barei verticae de la configura); inijal acest seman este in stnga primei cui ‘Atunci cand se alege un creion dintro cutie corespunztoare unei fri el va fi agezat fie pe jara respectiv8, daci nu existi 0 jari vecind cu aceeasi culoare, 128 4. PROBLEME CLASICE REZOLVABILEPRIN BACKTRAC Listing 11.8: Funejia de continuare pentru problema coloriri hirjlor public boolean continuare(int k) ‘ 2 for (int i= 05 Fe ks 44h) | : te (x{i] == afk] && vein [K}LH) ‘ i : return false: ‘ ) so "1 fic Langa cutie in cxz contrar. Astfel, multimile C; de valori consumate la un ‘moment dat sunt alcituite din creioanele de ling’ cutia Vj si de pe tara Tj. Cu aceste preciziri, cele 4 modificiri de configurajie au urmatoarele semnificait concrete: «© atribuie si avanseaza: se ageazi creionul ales pe fara corespunzitoare gi se trece la cutia urmatoare; ‘© Incercare esuat creionul ales este aezatlangd cutia din care a fost scos: «© revenire: creioanele corespunzatoare fri curente sunt repuse in totalitate la loc in cutie gi se trece la cutia precedent: © revenire dupa gasirea unei solu: semnul este adus la stinga ulimet Procesul se incheie in momentul in care toate ereioanele ajung din nou in cutiile ‘care e afl ini Rezumat in acest capitol am prezentat metada bactrackng, care se reduce in eset la parcurgerea exhaustivi a spafilui de edutare, in care se elimini cu grit configuajie care nu pot condice lao soli. Metoda backtracking se aplici oricirei probleme a cirei soli se poate srie sub forma de gir, cu flecare e- Jement al siralui bund valor in cadrl net muljimi finite. Element estenial care determin eficienja cuts este reprezentat de condi de continuare care 129 14, PRORLEME CL REZOLVABILE PRIN BACKTRACKING suntuilizate pentru a reduce dimensiunile spaiuli de cdutare. in modetul teo- relic al acestei metode, se pomnegte de la o configura nia, ceia ise apc succesiv anumite transforms pnd in momentul in care se ajunge la configu- raja final in practic, rezolvarea unei probleme prin aceastA metods se reduce cel mai adesea ta sriereafunctiei de continuare (cate este o implementare a conditilr de continuare) penteu problema coneretd cite se apick Nofiuni fundamentale backtracking: metodi de elaborare a algoritmilor care consti in constru- irea solujiei component cu component, cu eventuale reveniri asupra compo- nentelor anterioare. condifie intern: condisia pentru ca un sir si reprezinte o solutie a proble- conditie de continuare: condijie necesar’ pentru ca un sir parial si poati conduce lao solujic. configurafie final: configurajie cfreia nu i se mai poate aplica nici una 4intre cele patru transformiri gi care indie’ incheierea procesului de cfutare, configuratie inifiali configurajia de la care se pomeste in procesul de celutare al soluiilor, dingramé de stare: diagram’ care sintetizeazA starea in care se afli proce- sal de efutare la un anumit moment. solutie: un sir care respect condigile interne. Erori freevente 1. Exist adescorisituafi in care solufia unei probleme nu se poate serie di- rect sub formii de vector, ci trebuie ficute anumite convengi pentru a ore ‘duce la un vector. Asadar, backtracking se poate aplica oricirei probleme 1 ciel soluyie se poate reduce sau transforma inte-un vector. Mulfi pro- ‘gramatori incepitori renunji la a incerca sit aplice aceasti metoda dact solufia ei nu este in mod evident structurati sub formi de vector, fri si pune problema de a transforma solusia intro astfel de forma (vezi problema damelor din paragraful 11.4.3, in care solujia se reduce de la 0 ‘matrice (tabla de gah) Ia un gir de numer), 2. Desi metoda backtracking se poate aplicaoricdrei probleme a cirei solugie se poate scrie sub forma de si, aceasta nu inseamn eX backtracking este si metoda cea mai eficienta de a 0 rezolva. De exemplu, si in cazul pro- blemei sortiii soluyia se scrie sub forma de sir, deci se poate aplica back tracking. Totusi aplicarea lui backtracking in aceast& situayie ar insemna 130 4. PROBLEME CLASICE REZOLVABILEPRIN BACKTRAC o © generare optimizati a permutirilor elementelor acelui gir, eeea ce ar cconduce Ia o solujie exponential, deci inutilizabili. O sit prezentiim in ‘capitolul urmitor metode eficiente de ordonare a unui si. 3. Adeseori functia de continuare nu este optim aleasd, in aga fel incét si climine eft mai multe configurajii nefezabile. 4, Se confundi adeseori dimensiunea spafiului de ctutare (notati de noi cu ‘n) cu dimensiunea individuald a fiecirei multimi V_ (notata de noi su s{k). Este adevirat ca la multe probleme (de exemplu, permutii) aces- tea sunt egale, dar la altele (cum ar fi colorarea hiilor, combing, aran- jamente) ele diferi Exereifii Teorie 1. Enumeraji problemele prezentate in cadral acestui capitol, pentru care cconditile de continuare sunt necesare, dar nu sunt suficiente, 2. Lusi o tabla de sah obisnuitd si incercajisA simulayi modul in care se ‘genereaz4 solutia problemei damelor pentru n = 8. 3. Gis toate soli de colorare cu te clon aha dn Fgura 11.2, tn practic 1. Si se afigeze toate modurile in care m persoane pot fi agezate In 0 masd rotund precum si numa acestora Indicayie: Exista doua posibilitati de rezolvare: (@) Se vor genera toate permutarile posibile, prin metoda backtracking, si se vor contoriza. Se va afisa apoi numarul lor. Va trebui insa sit fineti seama de faptul ci unele dispuneri sunt identice din cauza ‘mesei circulare; ‘Mult mai elegant, folosind o observayie simple. Asifel, cu n obiecte sse pot forma nt permutdiri. Cum, in cazul dispunerii lor circu- lave 1,2,...,n, respectiv 2,3,...,m, 13 ...37,1,2,....m— 1 sunt identice, rezultd c& din n asifel de permutari trebuie consideratas doar cea care incepe cu I. Numérul de permutari va fi asadar (n-1) © 131 14, PRORLEME CL REZOLVABILE PRIN BACKTRACKING 2. Idem problema I, cu precizarea ei anumite persoane nu se agreeazi deci ru pot fi agezate una langi cealalt, La intrare se mai furnizeazao matrice simetticd A, cu urmitoarea semnificaie: siya f 2. ack mu se aprenet aga={ 5 3, Si se modifice algoritmul de generare a combinisilor prezentat in para- graful 11.4.2 astfel neat functia de continuare si nu mai fie necesara Indicate: Pentru fiecare componenta z{K] se porneste cu valoarea z[k — atl. 4, Se dau n muljimi A1, Aa, ..yAn- Si se afigeze produsul lor eartezian, Indicayie: Generarea produsului cartezian inseamndt de fapt generarea Intregului spatiu de solutt, adicet un backtracking in care functia de con- tinuare lipseste. 5. Se di o muljime A = {1,2,...,n}. Si se afigeze toate submulfimile acestei mulfimi Indicajie: Se genereazittopi vectorié caracteristici de lungime n. Prin vector caracteristic se infelege un vector care are doar valorile I sau 0 pentru fiecare element cu semnificatia: ati 1 daca i apartine submultimii 0 califel Exista gio soluie care genereazi vectorii caracteristici de lungime n prin ‘adunarea in baza 2. Initial vectorul este nul, corespuncétor multimii vide, iar apoi prin adundri repetate se genereazi toate submuljimile. Atentie, ‘numdiralrotal de submultimi este 2"! 6, O firma dispune de n angajaji dintre care p sunt femei. Firma trebuie si ormeze 0 delegatie de m persoane, dintre care k sunt femei. Si se afgeze toate delegaile care se pot forma, Indicaie: Pentru a forma o delegayie de kfemei din p disponibile avem la dispocite C variane. Delegayia de m persoane poate fi completat 132 4. PROBLEME CLASICE REZOLVABILE PRIN BACKTRACKING cu oricare din variamtele de C™ de alegere a beirbasilor din delegatie. ‘Asadar nunciril total de variante este C « 0% Generarea efectivéi se bazeazi pe un vector caracteristic cu semnificatia: anya {3 st peame foi Functia de continuare va numira femeile din delegayie si nu va lisa ca rnumarul lor sil depageasea pe k. Se considera mulimea A = {1,2,-..,7}. SA se furnizeze toate partitile acestei muljimi. (O partie a unei muljimi este o scriete a muljimii ca reuniune de submultimi disjuncte. Indicatie: Vom genera paritia sub forma unui vector cu n componente in care z{i] = k are semnifcatia cd elementul i apartine submulfimii ka paritiei considerate. Ca exemplu, pentru n = 4 putem avea, la tun moment dat, vectorul + = (1,2,1,2) ceea ce corespunde partitii: A= {1,3}U{2,4}. Arfide remarcat ca vectorul earacteristie poate lua valori care vor avea aceeasiinterpretare, ca de exemplu x = (2,1,2,1) ceea ce corespunde pariiiei: A = {2,4} U {1,3}. Dar reuniunea e co- imutativa si partifa asiel objinutae identicdt cu cea anterioard. Pentru a evita acest lucru vo impune ca fecare componenti'a vectorului sd poati davea cel mult valoarea k, unde k este indicele elementului. Semnificatia ar fica elementul cu indicele 1 va putea face parte doar din submultimea 1, eel eu indicele 2 doar din submultimile 1 si 2 etc. O altérestritie ar fi ‘aceea cat un element nu poate lua 0 valoarea mai mare ca maz: +1, unde ‘max este valoare maximdi a elementelor de rang inferior. Acest lucru se Justified prin fapru ed = (1,1,3, 1) nw ar avea nici o semnificatie. Un comis-voigjor trebuie si viziteze un numir n de orase pornind din foragul numirul |. El trebuie si viziteze fiecare oras 0 singur dat, dup care si se intoarci in oragul 1, Cunosednd legiturile existente intre orase, se cere si se giseascd toate rutele posibile pe care le poate efectua comis- voiajorul Indicasie: Se va crea 0 matrice de adiaceng (cunoscutd din teoria gra- furilor), care este 0 matrice simetrica: 133 REZOLVABILE PRIN BACKTRACKING Alig 1 daca exista legaturd intre orasele i si j 0 alyfel Functia de continuare va testa daca la elementul actual se poate ajunge din anteriorul, in vectorul x. Ca observatie trebuie spus cd pentru a obtine solugile distinct trebuie facut un ariificiu asemdnator cu cel de la problema anterioard 9. Idem problema anterioar, cu precizarea cd pent fiecare drum intre dou’ ‘orase se cunoaste distanja care trehuie parcurs. Se cere si se giseasci ruta de Iungime minima. Indicatie: In momentulretinerit solutei se va calcula lungimea drumului parcurs. Se va compara aceast' lungime cu lungimea anterioard con- siderata minima gi se va rejine valoarea actuala minim impreund cu "! atunei inversare | char a; a a=Reader-readChar(); if (ale?) { inversare(); } ‘System.out.print(a); } Reamintim c& Reader este 0 clas’ ajutitoare pentru citirea de date de la tastatura gi a fost definita in cadrul primului volum, fiind reluaté gi in cadrul acest volum, la paragraful 11.4.1. Este important de notatc& pentni ca metoda si functioneze corect, variabila a trebuie declaratica variabila local astfel, toate valorilecitite vor fi salvate pe stiva, de unde vor fi extrase succesiv (in ordinea inversa citiril) dup8 intilnirea caractenului Exemplu: Transformarea unui numar din baza 10 intr-o baz’, mai mick decit 10, ‘ne reamintim algoritml clasic de trecere din baza 10 in baza b. Numarul se impare lab ise refine restl. Citul se imparte din nov lab se reine resto si se continu acest procedeu pan’ cand cétul devine mai mic decat b, Rezultatul se objine prin serierea in ordine inversi a resturilor objinute. Formularea recursivi @ acestei rezolviri pentru trecerea unui numa n in baza b este: oe ie Trans f(n div) + Scrie(nmod) pens nzb ‘Transpunerea recursivi a formulei anterioare este: funetie transform(n:integer) public static void transform(int n) rest = n mod b { daci n> b atunei transform(ndivb) | int rest=n%b; serie rest ifn >= b) rum { transform(nfb); } System.out print(rest); + 2. PREZENTAREA METODEL DIVIDE ET IMPERA De remarcat ci in aceast functie variabila rest trebuie si fie declarati local, pentru a fi salvati pe stivi, in timp ce variabila b este bine si fie declarati global, deoarece valoarea ei nu se modifici, salvarea ei pe stivi ocupdind spagiu inuti, Odati ce am injeles mecanismul recursivititi, suntem pregitii pentru a jelege cea de-a doua metodi de elaborare a algoritmilor, Divide et Impera 12.2 Prezentarea metodei Divide et Impera Divide et Impera este 0 metoda special prin care se pot aborda anumite ca- tegorii de probleme, Ca sicelelalte metode de elaborare a algoritmilor, Divide et Impera se bazeazi pe un principiu extrem se simplu: se descompune problema inifiala in doua (sau mai multe) subprobleme de dimensiune mai mic, dupa care solutia probleme’ initiale se objine combindnd solutile subproblemelor in care a fost descompusi. Procedeul de descompunere se repeti pind cAnd, dup’ “eauta in prima jumatate a subsirului ” return search(s, el, low, mid ~ 1): » ’ S else * i 2 Veauta in a doua jumatate a subsirulul > return search(s, el, mid + 1, high): = , a , sy > fh fee Programul principal +/ fb publle statte vold main(String [] args) of fh Hettirea etementelor sirutut 4% System-out, printia("Introduceti clementele sirului in + tM “ordine crescatoare (pe aceeasilinie ):"): © int] s'= Reader readiatArray Os ® Heltirea elementutut caurat 5 System-out. print("Introduceti elemental cautat: *); Simtel = Reader. readin () Meautarea elementului % Ime poz = search(s. el, 0, s.lengih — 1): %— Hafisarea rezultarului caurarti © AF (por > =1) cn % System. out. printin ("Elemental * + el + G “a fost gasit ia sir pe pozitia "+ . poz): A. SORTAREA PRIN INTERCLASARE (MERGESORT) ea Slee ot % Systemout. printin ("Elemental " + el + “ Sinw a fost gasit in sir"): sy “4 o 12.4 Sortarea prin interclasare (MergeSort) Sortarea prin interclasare este, alituri de sortarea rapidai (QuickSort) si sortarea cu ansamble (HeapSort), una dintre metodele eficiente de ordonare a clementelor unui sir. Enunful problemei este urmitorul: ‘tse ordoneze crescator un sir cu n componente intreg. Principiul de rezolvare consti in aimpiirj sirul care trebuie ordonat in dowd piri egale gi a ordona flecare jumitate, dup’ care se interclaseazii cele dou’ jumitiji, Descompunerea in dou’ jumitigi se realizeaza pind cind se ajunge la siruricu un singur element, care nu mai necesiti sortare. Algoritmul de sortare prin interclasare urmeazit indeaproape conceptul Divide et Impera. Pe scurt, ‘modu! lui de operate este urmatorul: 1. Divide: imparte sirul de n elemente care urmeazi afi sortat in dous siruri cu n/2 elemente; 2. Staipaneste: Sorteazi recursiv cele doud subsiruti uilizand sortarea prin interclasare; 3. Combing: Interclaseaza subsirusile sortate pentru a objine rezultatul final MetodamergeSort () din Listing 12.3 implementeaza algoritmul de sortare prin interclasare, Apel initial al funcjici este: mergeSort(s, 0, s.length — 1): Listing 12.3: Metoda care ordoneaza sirul s folosind sortarea prin public statte vold mergeSort(Int{] 5, Int low, Int high) af terclasare 1 Af Clow < high) sot ; int mid = (low + high) £25 ‘ mergeSort(s, low, mid) ; mergeSort(s, mid'+ 1, high): 149 124. SORTAREA PRIN INTERCLASARE (MERGESORT) : interels(s, low, mid, high): " ‘Metoda de interclasare in acest caz este analoagi cu metoda de interclasare obisnuita a doua siruri, diferenja constind in faptul c& acum se interclaseaza dot jumatiti ale aceluiagi sir, iar rezultatul se va depune in final tot in sirul interclasat. Listing 12.4 prezinti implementarea complet a sortrii prin inter- clasare, aplicati pe un gir care este preluat de la tastatur. Listing 12.4: Solutia algoritmuh Import java.io. simport io. Reader: 1 Program ce ordoncaza un sir de numere intregi ft folosind metoda MergeSort de sortare Mergesort {public class MergeSort st fas Metoda de interclasare a celor 2 subsiruri./ hh public statie void intercls(imt low, ime mid. * int high, att] 8) bt HS amt t= tows int j= mid + 1s Ame) inter = mew int thigh + Ls hint k= lows > Hinterctasarea elementetor while ((i c= mid) && (j 150 124. SORTAREA PRIN INTERCLASARE (MERGESORT) Han mai ramas elemente din cet denal dollea subsir? for (int Fa jy 1 ce high; 144) fi 1 intertke#] = sts Ucopierea elementelor din siral inter in sirul s for (i= low; i <= highs 144) inter Lik: (es Metoda de sortare.+/ Public static void mergeSort(Int{] s, Int low, int high) t it (low < high) //swbsirul are cel putin 2 elemente i int mid = (low + high) 1-2 mergeSort(s, low, mid) mergeSort(s, mid +1, high): interels (low, mid, high, $): ’ 1 Jes Programul principal. +/ public statle void main(String {) args) ‘ Ucitirea elementelor siruluit System. out. printin("Introduceti elementele sirului T(pe access linie):")e Int[] = Reader readiatArray (): Usortarea elementelor sirului prin metoda "MergeSort mergeSort(s, 0. s.length — 1): WUafisarea rerultatului sortarii System out. printia( “Sirul ordonat prin metoda MergeSort este:*) for (int i= 0: i s.length; i++) t System. out. print(stil +" 151 SORTAREA RAPIDA (QUICKSORT) 12.5 Sortarea rapida (QuickSort) Sortarea rapidal este, asa cum fi spune si numele, cea mai rapida metod’ de sortare prin comparaji cunoscuti in prezent. Existl foarte multe variante ale acestei metode, o parte dintre ele aviind doar rolul de a micsora timpul de execute in cazul eel mai nefavorabil. Vom prezenta aici varianta clasic’, despre care veli remarca eu surprindere ci este neasteptat de simpli. Enungul proble- ‘mei este identic cu cel de la sortarea prin interclasare, si anume: ‘Sat se ordoneze crescitor un sir de numere intregi. Metoda de sortare rapid prezentata in acest paragraf este, dintr-un anumit punct de vedere, complementara metodei Mergesort. Diferenta mmetode este dati de faptul ca, in timp ce la Mergesort mai Prjea in dow’ parji dupa care se sorta fiecare parte si apoi oui jumatay, la Quicksort implrjirea se face in aga fel incat cele dous giruri SH nu mai necesite a fi interclasate dupa sortare, adica primul sir si congina doar elemente mai mici (nu neaparat ordonate) decat elementele celui de-al doilea sir. Rezulti de aici cd in cazul lui Quicksort, etapa de recombinare este ‘deoarece problema este astfelimpartiti in subprobleme ined si nu mai fie necesari interclasarea girurilor. Etapele lui Divide et Impera pot fi deserise in aceasta situajie astfel: 1, Divide: Imparte seu de melemente care urmeazsa fi sorta in dou sur, ‘sie incdtelementle din primal gir sie mai mici decd elementele din al doilea sr: 2 ‘Stdpaneste: Sorteaz’ recursiv cele dou’ subsiruriuilizand sortarea rapids 3. Combind: Sirul sortat este obsinut din concatenarea celor dour subsiruti sortate. Functia care realizeazatimpargirea in subprobleme (astelincét clementele primu- lui sir si fie mai mici decat elementele celui de-al doilea) se datoreaza lui C. A. Hoare, care a gisit 0 metoda de a realiza aceasta impart (numiti partijionare) in timp liniar. “Metoda de partgionare rearanjeazi elementele tabloului fn funcjie de primul element, numit pivot, astfel incat elementele mai mici decat primul element sunt ‘recute in stanga lui, iar elementele mai mari decat primul element sunt trecute {in dreapta lui, De exemplu, dact avem vectorul: (7,8,5,2,3), 152 125. SORTAREA RAPIDA (QUICKSORT) atunci procedura de patifionare va muta elementele 5, 2 si 3 fn stinga lui 7, iar 8 va fi in dreapta lui. Cum se realizeari acest lucru? Sirul este parcurs simultan de doi indici: primal indice, low, pleac& de la primal element si este incrementat succesiy, iar al doilea indice, high, porneste de la ultimal element si este decrementat succesiv. in situatia in care allow] este mai mare decat afhigh], elementcle se interschimba. Partitionarea este incheiati in momentul {n care cei doi indici se inténesc (devin egali) undeva in interiorl siratui. La fiecare pas al algoritmului fie se incrementeaza low. fie se decrementeazi high; Intotdeauna unul dintre cei doi indici low sau high, este pozitionat pe pivot ‘Atunei cand low indic& pivotul, se decrementeaza high, iar atunci cand high Wicd pivotul se incrementeaza low. Iaté cum functioneaza parttionarea pe exemplul de mai sus. La inceput, low indic& primul element, iar high indica ultimal element: a= (7,8,5,2,3) t t low high Deoarece allow] > alhigh] elementele 7 si 3 se vor interschimba. Dupi interschimbare, pivotul va fi indicat de high, deci low va fl inerementat: a= (3,8,5,2,7) tot low high Din now avem allo] > afhigh], elementele 8 si 7 se vor interschimba. Dupi interschimbare, pivotal va fi indicat de low, deci high va fi decrementat: (3, 7,5, 2,8) tT low. high Din now avem aflou] > afhigh, elementele 7 Dupa interschimbare, pivotal va fi indicat de high, de se vor interschimba. low va fi inerementat: (3,2,5,7,8) De data aceasta avem allow] <= alhigh], deci low va fi incrementat din nou, flr ase realiza interschimbi 153

You might also like