elibrary.ceiti.md+_poo(cerchez).pdf · orice functie din algebra booleana poate fi impjementatii...

126
----, ". m ;;: » z c m o m :n o I m 1" ;;: » :n z m r- .(f) m g ! + + - o' 3 (!) C" t: Q) ...... t:

Upload: others

Post on 30-Aug-2019

8 views

Category:

Documents


3 download

TRANSCRIPT

Page 1: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

----,".

m;;:»zcm~om:noIm1";;:»:nzmr­

.(f)m

g !++

-o' 3(!) C"t: Q)......

t:

••••

Page 2: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

POll ROM2013

[1

flU

r'U

C'lI ,U

u

u

nu

u

r-1I '

U

o

Ui

,-I, I

Ui

,I.,

r Iy'U,

f1w

I,

j= I:-.. ~l't':=(""'~ir~i" ~.,." r" "'T_i!: _~ ,- ~~ f!¥ {§'f;}( j]TlrY; r,"'~,;- f:<i rt1tLk[ii~ ¢,:,~, ~!Je:, iiS'JiJ

£J!IltIff

ii§1:'",,/iF

I',f:"~

fin" ~,F~£, f "'t(Fr~J

~tl'~ it~~{1] ~ ~

Emanuela Cerchez, Marinel ~erban

PRDGRAMAREA

••••Programare orientata pe obiectesi programare generica cu BTLL· ,

.-.

IN LIMBAJUL

'-

Aceasra cane este protejata prin copyright. Reproducerea unegrala sau pania1a, multiplicarea prin oricemijleace ~i sub orice forma, cum ar fi xeroxarea, scanarea, transpunerea in formal electronic sau audio,punerea la dlspozijia publica, inclusiv prin internet sau prin rejele de ca1culatoarc, srccarea permanents sautemporara pe dispozitive sau sistcmc cu posibiltratea recuperarf infcnnatiilor, cu scop eomercial sau gratuit,preeum ~i alte faple simiJ<lre s1ivar~ite tara pcrmisiunca scris1i a de{in1ilorului copyrightului reprezilll1i 0

inca1care a legislaliei eu privire Ia proteqia proprietatii imelectuale ~i se pedepsese penal ~i/sau civil inconformitate eu Iegile in vigoare.

Autorii au 0 bogata expcriema in pregsorea de performanjn a elevilor : sustin cursuri la Ccntrul de Pregntirc aTinerilor CapabiJi de Performanta din Iasi. propun probleme pentru olimpiadelc si ccncursurile nationalc ~i

judejcnc de iufonnaoca. susttn activitatea de prcgatirc a lotului national de informatica, precum ~i programul depreganre de pcrformanja in informatica .campion,

Vol. 4. Progmmare orielllari'i pe obiecte $i progmmare generidi CI/ STL. - 2013. - Bibliogr.ISBN 978-973-46-4081-2

Editura POLIROM1a.>11, B-dul Carol I ilL 4, P.O. BOX 266, 700506Bucure.>1ti, Splaiul Unirii nr. 6, bl. B3A, sc. 1. ct. 1,sector 4,040031, O.P. 53, c.P. 15-728

Descrierea CIP a Bibliotecji Na\ionale a Romalliei :CERCHEZ, EMANUELA

Programaren fnlimbajul CIC+ + pellfm liceu I Emanuela Cerchez, Marine! ~erball. - Ia~i:

Polirom, 2005-2013

4 vol.

ISBN 978-973-46-0109-7

© 2013 by Editura POLIROM

MARINEL-PAUL sERBAN (n. 1950, Arad) este absolvent al Facultalii de Matcmauca-Mecanicg , Universitatesdin Timisoara (1973); specializare postuuiversitara in informatica (974), profesor de informatica (graddidactic I}, mcrnbru in Comisia NalionaIll de Informatica. De acelasi aurar, la Editura Polirom au apllrut :Informatica, Manual pemru ctoso a X-a (coautoare Emanuele Cerchez, 2000, avizat MEN), Pc. Pas cu pas(coautoare Emanuele Cerchez. 2001; ed. a Il-a, 2005), informatica pentru gimnatiu (coautoarc EmanueleCerchez, 2002, avizat MEC), Programoreo ill limbajul CIC+ + pentm liceu (vel. I. coauroare EmanueleCerchea, 2005), Pragramarea ill limbajul CIC++ pemru liceu, Metode ~i tehnici de progroml1re (vel. 11,coautoare Emanucla Cerehez, 2(05), Progromaroa ill limvajul CIC++ peuuu ticen (vol. III, coautoarcEmanuela Cerchez, 20(6).

EMANUELA CERCHEZ (n. 1968, la~i) cstc absolventa a Facult2tii de Matematica, scotia Informatica (J990),~i a Seminarului pedagogic postunivcrsitar (1997). prctesoara de informatica (grad didactic J), membra illComisia Nationala de luforrnatich. Autonrea a mai publicat la Editura Polirom: Internet. Mallilal pcntru liceu(2000, avizat MEN), Informatica. Mrl/lual penuu ctoso a X-n (coauror Marinel-Paul Serban, 2000, nvizaiMEN), Pc. Pas ell pas (coautor Marinel-Paul Serba». 2001; ed..» 1I-a, 2005), Illformaricn peutru ginmaeiu(coautor Marinel-Paul Serban, 2002. avizat MEC), lnformatico. Culegere de proutcme pcntru ticcu (2002),Programarea in timbajul cle+ + pemru uccu (vel. I, coautor Marinel-Paul Scrban, 2005), Programarea tulimbajul GIC++ pentruIiccu, Metode $i tehnici de programore{vel. Il , coautor Marinc1-Paul Scrban, 2005),Progratnarea in fimlJajul CIC+ + pentruliceu (vel. III, coactor Marinel-Paul Scrban, 2006).

"WWI1J.polirom.ro

Printed itl ROMANIA

1. ~erball, Marillcl

004.42(075.35)004.43 C(075,35)004.43 C++(075.35)

Page 3: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

. 7

............. ..9

········ 9121314

............

...............

. 15

IS]6181819

.W. .. 21

.n..~

26.~

.292932

. ~

··· 3536

················48. '" 51

.Mm76....':::::::::.':::'::::: .... .. .. .. :77

······ 8].......... . ~

CUPRINS

............................ . .

I. Principiile programarii orientate pe obiecte

1.1. Evolupa jimbajelor de programare ...1.2. Principiile POQ .1.3. AvantajeJe PDQ .1.4. lntrebari recapirularive

CUVGm tnatrue .

2. Programarea oriematii pe obiects in C+ + .

2.1. Clasele §i obiectele .. , .2.2. ComroJuJ accesului la membrii unei clase _, .2.3. Arhitecrura unei aplicatii POD .2.4. Definirea funqiiJormembre in exteriorul clasei2.5. Punctille inline .. , _.. " .2.6. Funcuile eli parametri implicijj "2.7. Supraincarcarea funqiiJor .2.8. Conslrucrorii .2.9. Destmctorul.. .2.10. ModeluJ logic aJ vietii unui obiecr .2?~ 1. Constructorul de copiere .2.12. Pointerul this .2.13. Mcmbrii statici ai unci clase ..2.14. SpecificatoruJ cons r ..2. J5. Functiile friend

2.16. Clasele friend ..2. J7. Suprafncarcarea operatorilor .2.18. Tratarea erorilor ..2.19. Aplicatie. Numere naturale mari2.20. Clasa string ..2.21. Mostenirea ..2.22. Includerea conditionala .2.23. PoJimorfiSl1lul ..2.24. Tratarea eroriJor utilizand clasa excec r s.onr25. Exercilii §i problcme propuse .

Page 4: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

Conraincrelc asociative sortate set §i mu\ t Ls e t;

Containerele asociative sortate map ~i muI t LmapContainerele asociative nesortate .. .. . .Exercitii ~i probleme propuse ..

7. Containerc asociative .

8. Soluri! §i indicatii ..

no

oo

oo

oo

o

u

ooo

I{. ,LJ

IfU

Cuvant inainte

Volumul al IV-lea al lucrarii Prograinarea in limbajul CIC + + pentru liceu repre­zinta 0 continuare fireascs a celor anterioare, cel de fata cuprinzand prezentarea adoua noi paradigme de programare: programarca oricnrara pe obiecte ~i progra­marea generica, Prezentarea concisa, clara si operationala a conceptelor programariiorientate pe obiecte a reprezentat 0 adevarata provocare. Suntem convinsi insa ca amreusit sa punem la dispozitie un instrument eficient de invatare, datorita numeroaselorexemple explicate ~i apllcatiilor de facture algoritmica incluse , utile atat eJevilor deliceu, cat ~j srudentilor care se initiaza in programare.

Cea de-a doua sectiune a lucrarii este axata pe programarea generics si ilustrareaacestui nou stil de programare, utilizand biblioteca STL (Standard Template Library) .Nu ne-am propus sa inlocuim in acest volum documenratia STL, care este excelentstructurata §i poate fi accesata online, ci am urmarit ilustrarea principalelor functiiprmtr-o abordare algoritmica. Am integrar cuncstinte §i deprinderi pe care eievii ~i

Ie-au format deja prin studiul volumelor precedente, dar am schirnbat perspecriva inceea ce priveste modul de implernentare, valorificand facilitiltile oferite de STL.

Prefata pe care Alexander Stepenov. ,principalu! aurar al bibliotecii STL, a scris-oin 2001 pentru lucrarea STL Tutorial and Reference Guide se incheie astfel : "STLpresupune un mod diferit de a preda informatica. 99 % din ceea ce un programatortrebuie sa stie nu este cum sa construiasca 0 components software, ci cum sa 0

foloseasca". Ca profesori cu zeci de ani de expericnja in formarea programatorilorde perforrnanta, am dori sa nuantam aceasta afirmatie, deoarece suntem convinsi dipentru a utiliza eficient si productiv 0 componenta software trebuie sa ai 0 bunatntelegerc a modului de funcdonare a acesteia. Din acest motiv nu am putut prezenrabiblioteca STL fara a ilustra principiile programarii orientate pe obiecte si aleprogramarfi generice, precum si modul de implementare a aces tor doua stiluri deprogramare in limbajul C++. Si suntem convinsi in egala masura ca "invlitaceii"nostri, care stapanesc deja structurile de date, vor intelege perfect containerelestandard din STL sl vor sri sa Ie utilizeze optim in implcmcntanle lor.

Speram ca prin acest volum sa oferhn un punct de sprijin in construirea unuiraspuns afirmativ la intrebarea pc atunci retorica a lui Alexander Stepanov: "Putemmuta vrcodata software-ul in era industriala ?":

. n9

. ..... 207

207........ 220

231.....n4

. 246

..247

133

. 100

1m. 108

. .. 100

. .. 110.... 112. .. 114.. 115

...... 115........... 121. 123

........... In...... 131

............ 96

. 96. ... 99

....... 104

. .. 170

.. ]70..... 181

........ 188............ 200

... 133.... 1~

............ 12................ 159

..... 1~............... 163

Clasa vector .Clasa deque ..Clasa list .Clasa forward_list ..Clasa arra:y .Exercitii ~i probleme propuse .

5.1.5.2.5.3.5.4.5.5.5.6.

7.1.7.2.7.3.7.4.

3. Elemente de programare generica

3.1. Punctiile sablon .3.2. ClaseIe sablon .3.3. Exercitii si probleme propuse

6.1. Clasa adaptor queue (coada) ..6.2. Clasa adaptor stack (stiva) ..6.3. Clasa adaptor priority_queue .6.4. Exercitii sl probleme propuse .

4. STL. Concepte generale .

4.1. Ce esre STL? .4.2. Clasele container.4.3. ClaseIe adaptor pentru containere .4.4. lteratorii .4.5. Clasele adaptor pentru iteratori4.6. Functor'ii . .4.7. Clasele adaptor pentru functor!4.8. Algoritmii .......4.9. Clasa sablon pair4.10. Alocatorii ......4.11. Aplica!ii......... . .4.12. Exercitii §i probleme recapirulative .

5'. Comainere secventiale .

6. Clasele adaptor .

Anexa. Carocieristtct ale principalelor containere ....

Bibliografie .

Page 5: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

r-

.-

r-

r-:

~

~

~

~

1. Principiile programarii orientate pe obiecte

1.1. Evolutia limbajelor de programare

Programarea orientata pe obiecte (pe scurt, POD) rcprezinta un stil de a dezvoltaaplicatii (sau, mai elegant spus, 0 paradigrna de programare). Ca sa tntelegem cums-a ajuns la PDQ, aT fi utila 0 scurta incursiune istonca in evolutia calculatoareJor ~j

a limbajelor de programare.Prima masina de calcul prcgramabila a fast conceputa de matematicianul englez

Charles Babbage, in perioada 1830-] 840. Interesant esre ca modelul propus deBabbage se apropie de strucrura conceptuala a unui calculator actual (avea 0 unitaiearitmetico-logica, 0 unitate de control, 0 unitate de memorie). Ada Lovelace (mai exact,Augusta Ada King, Conresa de Lovelace, nascuta Augusta Ada Byron, fiind singurulcopil legitim al poetului George Gordon Byron) a fast prirnul programmar din lume.Ea acanceput un .Jimbe] de programme" pentru masina lui Babbage $i a creat primulprogram din lume. Din pacate, unele probleme tehnice si financiare nu i-au perrnislui Babbage sa finalizeze constructia rnasinii sale de calcu1, astfel incat programuJAdei Lovelace nu a fost niciodata testat.

o sum de ani rnai tarziu, tnrrc anii 1940 si 1950, au fost create primele calculatoareelectronice. Cele mai importante teorii care au stat la baza constructiei calculatoarelorle apartin lui Alan Turing (care in 1936 a descris un model matematic de functionarea unei masini de calcul programabile), Claude Shannon (care in 1937 a demonstrat caorice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unorcircuire Jogice electronice) ~i John von Neumann (care a descris schema structuralede baza a calculatoarelor, denumita arhitectura von Neumann); calculatoarele modernesunt construite din circuite logice, se bazeaza pe arhitecrura von Neumann si imple­menteaza functional modelul masinii Turing. La titlul de "primul calculator modern"candideaza masina Atanasoff-Berry (primul calculator electronic), calculatorul britanicColossus (prirnul calculator electronic programabiJ prin conexiuniJe cablurilor sicomutatoare), masinile inginerului german Konrad Zuse (prima masina Turingcomplete) ~'i ENIAC (primul calculator generic; programul trebuia introdus manual,modificand concxiunile cablurilor si comutatoarcle sale). Primul calculator functionalcu program stocat a 1'05t Manchester .,Baby" dczvoltat de Frederic C. Williams siTom Kilburn Ia University of Manchester in 1948. Odara eli dczvoltarea calcula­toarelor ell programc stocate s-au dezvolrate ~i limbajclc de programare.

Page 6: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

10 PROGRAMAREA iN L1MBAJUL C/C++ PENTRU LIeEl! rm'~''''''''''TT''' ........OGRAMARIJ ORIENTATE PE OBIECTE

'-'

~

'~

~

Mai mult, aplicatia a fost Iivrara inainte de termen si cheltuielile au fest mai mici "'---J

decat cele bugetate. Acest succes a fast un $OC in comunitatea programatoriJor (deexernplu, aplicatia precedenta dczvoltata de IBM, sistemul de operare penrruSystem/360, a costat sute de milioane de dolari, a fast finalizat eu un an intarziere sicontinea Ia Jansare mil de erori). Programarea structurata a consriruit 0 .aevolune" in wdomeniu.

In esenta, programarea structurata are la baza trei principii pentru dezvoltareaaplicatiilor :

L analiza TOP-DOWN: problema de rezolvat este impartita in subproblerne relativindependente ; fiecare subproblems este analizata in acelasi mod;

2. modularizarea : programul este irnpartit in mai multe sectiuni (denumite module,subprograme, procedurl sau functii}, fiecare modul rezolvand 0 subproblems aproblemel date (in concordanta cu analiza TOP-DOWN a probJemei);

3. codul structural: fiecare modul consta in compunerea celor trei structuri decontrol fundamentale: secventiala, alternariva, repetitiva.

Interesant este ca principiile care stau la baza programani orientate pe obiectedateaza tot din anii '60. Ccrcctarorn de la Uuiversiratea din Oslo au dezvoltat unlimbaj de programare denumit Simula, care introducea notiunile de clasii, object,

functie virtuala etc. Simula fiind primul Iimbaj de programarc orientata pe obiecte.Inspirati de acest limbaj, cercetatorii de la XEROX Palo Alto au dezvoltat in perioada1970-1980 un alt limbaj de programare orientata pe obiecte "pur", SmallTalk, in caremate prelucrarije se realizeaza in cadrul claselor. 0 incercare de a crea un limbaj deprogramare orientara pe obiecte "pur", eficient de utilizat in industria software, afost limbajuJ Eiffel, creat de Bertrand Meyer. Programarca orientata pe obiecte adevel1it insa populara odata cu aparitia Hmbajului C+ +. Limbajul C+ + creat laincepuml anilor '80 de Bjarne Stroustrup de la AT&T Labs era un limbaj hibrid, carepastra compatibilitatea cu limbajul C. Limbajul estc considcrat hibrid deoarcceprogramatorul poate scrie un cod ~i in afara claselor. Ulterior, la inceputul anilor'90. Sun MicroSystems a dezvoltat un all limbaj'de prograinare orientara pe obiecte,denumit Java. Java a menIinur 0 sintaxa asemanatoare cu a limbajuJui C+ +, dar aeliminat caracteristici potential periculoase (cum ar fi posibilitalea de a utilizapointeri) §i a simplificat anumite aspecte (de exemplu, are un sistem denumit garbagecollectiOlI, care elibereaza automat memoria ncutilizaUi).

La ora aetuaHi, programarea orientata pe obiecte este paradigma general acceptat5.pentru dezvoltarea de aplicaIii softwore.

Initial, calcularoare!e erau programate in limbaj masina (programatori i cunosteaucodurile numerice ale instructiunilor speciflce masinii de calcul utilizate ~i ie intro­duceau "de mana", proces, evident, lent §i supus frecvent erorilor). 0 idee majora.care a schimbat acest sti! de programare, a Iost accca de a crea un program care' satraduca un aIt program. Astfel au aparut limbajele de asamblare. Accstea sunt deasemenea specifice masinii pe care ruleaza, asambiorul traducand instructiunilelimbajului de asamblare in cod masma. Instructiunile scrise in limbaj de asamblare auo codificare mai usor de retinut (mnemonic) pentru operatia executata si operanzi(date sau adrese de mcmonc). De exemplu, MOV AL 61h determina rnemorareavalorii hexazecimale 61 in registrul de memorie AL.

Ideea care a facut trecerea de Ia Iunbajele de asamblare (dificil de utilizat sispecifice masinii de calcul) la limbajele de nivel inalt a fost introdusa in 1952 deGrace Hopper: utilizarea unui Iimbaj de programare independent de masina si a unuiprogram (pe care ea l-a denumit compilator) prin care sa fie tradus codul-sursa(codul scrls in limbajul de programarc respectiv) in cod obiect (cod scris in limbajmasina). De altfel, Grace Hopper a si dezvoltar primul compilator pentru limbajulA-O, desi acest merit este atribuit frecvem echipei conduse de John Backus de 1a IBM,care a dezvoltat in 1957 compilatorul pentru limbajul FORTRAN. Din acest moments-au dezvoltat numeroase limbaje de nivel inalt. Dlnrre acestea, unele au rezistar intimp ~i au fost utilizate pe scars Jarga : FORTRAN (Iimbaj de uz general, in specialpentru oameni de §tiinta §i ingineri, care in timp a avur nurneroase versiuni), COBOL(Iimbaj proiectat pentru aplicatii econornice), LISP (care a introdus concepteleprogramarii functional e) §i ALGOL (care nu a avut irnportanta cornerciaia, dar aintrodus concepre-cheie pentru dezvoltarea limbajelor de programare actuale).

Perioada urrnaroare a fost extrem de prolifica , ata: in ceea ce prlvestc Iimbajelede programare dezvoltate, cat $i in privinta concepteior care au influentat evolulialimbajelor de programare. Un prim concept-chcie a fost natatia BNF (Backus-Naur­Form), introdusa in 1959, reprezentand 0 modalitate matematidi de a descrie rigurossintaxa unui limbaj de programare.

Principala paradigma de programare dezvoltata In aceasrn perioada a fost pro­gramarea structurara, ca raspuns la necc.sitatea_de a scrie programc mai clare, -in rimpmai scurr ~i a CarOl' corectimdil1e sa poata fi demonstrata. Sratisticile demonstrau cala vrcmea respectiva un programator scria in medie imre 5 $i 10 linii de cod corectepe zj. Extrem de pUlin, avand in vedere dezvoltarea hardware-ului §i cerinp. pentrusoftware existenta. PUl1ctul de plecare al programarii structurate este consideratarticolul "Go To Statement Considered Harmful", scris in 1968 de Edsger Dijkstra,precum ~i lucrarile lui Bohm $i Jacopini. Ace$tia au formulat ~i demonstrat in 1966Teorema programarii structurate: "orice program poate fi descris cu ajutorul a treistructuri de control: structura secventiaHi, structura alternativa ~i structura repeti­tiva". Timp de 20 de ani, Dijkstra a promovat programarea s(ructurarn, dar probabilmomentul de cotitura, prin care industria software a cOIl$tientizat beneficiile acesteiparadigme de programare, a fost lal1sarea, 111 1972, a unci aplicalii de indexare aarticolelor din ziare, realiza(a de IBM pentru New York Times. Dezvoltarea apJiea~ici

a dura( 22 de luni, echivaHind ell l1lunca unui 0111 ill 1J Clni, constand in aproximativ83.000 de linii de cod. Dupa cinei saptamani de testare a aplicatiei au fost identiticatedoar 21 de erori, urmand ca in uTmatoru! an de u(ilizare sa mai fie identificate inca 25.

f

~I;;;r

~:

li[

I

'!,~:

Page 7: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

,. urare

Abstrecrizarea datelor este procesul prin care sunt definite de catre utilizarortipuri de date abstracre (ADT = Abstract Dam Types). In C+ +, tipurile de dateabstracte se implementeaza utilizand close.

Un tip de date este definit de domeniul de vaJori pe care Ie pot iua datele de tipulrespectiv, setul de operatii permise asupra valorilor respective si modul de reprezen­tare in memorie.

Un tip de date abstract este definit doar de domeniul de valori ~j setul de operatiiasupra valorilor respective, modul de reprezentare in memorie nefiind specificat pentruutilizator ,

De exempJu, stiva, ca tip de date abstract, este 0 structura de date care penniredoua operatii : push (inserarea unui element 1a varful stivei) si pop (extragereaclementului din varful stivei). Madul de implementare a stivei (Ca vector? Ca listssimplu inlantuna") nu este specificat. ci doar setul de operatii pennise.

Un tip de date abstract practic functioueaza ca 0 "cutie neagra?: interiorul este"opac", poate fi studiat/utilizat pc baza de intrart/icsiri.

,.....

I

rl ,

I"l ,

r

nir

i-

l' PROGRAM AREA iN L1MBAJUL C/C+-t PE1'\TRU LlCEU

1.2. Principiile POO

Abstractizarea datelor

------- .- --.oGRAMARJI ORIENTATE PC OBIECTE .

Mostenirea

Conceptul de mostenire (inheritance, in limba engtcza) este inspirai din domeniulbiologiei. De exemplu, putem considera ca tip de date abstract clasa Animal. Toateanimalele trebuie sa aiba functie de hranlre , functie de reproduccre etc. Acestea suntfunctii comune tuturor animalclor. in cadrul c1asei Animal putem diferentia diferitetipuri de animale , de exemplu , pasari si mamifere. Atat pasarilc, cat §i mamiferele auin comun eIementele specificc animalclor, dar au ~i caracrcnsrici specifiec. DeexempIu, pasarile au pene.

La POO, prin mostenire, 0 clasa poate mosteni toare elementele altei cJase. ProcesuIprin care 0 clasa mcsteueste eIcmentele aItei clase mai esre cunoscur si sub denumireade derivare . Prin derivare, 0 clasa (denumita clasa derivata sau subclasa) mostenesretoate elementele unei alte clase, cea din care este derivata (aceasta se numeste clasade baza sau supraclasa). Clasa derivata va avea si alte clemente specifice ei, care adiferentiaza de clasa de baza, De exemplu, clasa Pasare poate fi derivatf din clasaAnimal si adaugam la caracteristici specifice faptul ca pasarile au pene. Clasa dertvataeste mai spccializata decat clasa de baza.

o clasa derivata poate fi, la randul ei, clasa de baza pentru a alta class. Se obtinastfel ierarhii de clase, clasele derivate avand in eomun toate elementele mostcnite dela stramosul lor eomun.

In eoncluzie, in proeesul de proiectare a unci aplicatii POO, trebuie saidcntificam "modulele" aplicatiei (clasele), dar si elementele pe care Ie au aces tea incomun, construind, prin derivare, ierarhii de clase. Prin mostenire eluninam codulredundant si putem extinde aplicatia, adaugand noi functionalitan.

I'

Ii..

;;,u,

.(

Ii

,....:...

'I'i"

incapsularea datelor

Incapsularea datclor (encapsutcuton, in limba engleza) cste 0 consecinta imediataa principiului abstractizarii dateJor, proces in care reprezemarca inrerna este"ascunsa" utilizatorului.

Procesul de dczvoltarc a aplicatiilor pana Ia POD poate fi dcscris in modul eelmai concis prin ce1ebra ecuatic lansara in 1976 de Niklaus Wirth :

Structuri de date + Algorittn = Program

Accasta ecuatie evidentiaza faptul di efortul de proiectare a unei aplicatii se concen­treaza pc 0 buna structurare a datelor, apoi pe dezvoltarea eclar mai eficien~i aIga­ritmi de prelucrare a acestora.

Efortul de proiectare a unei aplicatii POO eonsta in primuJ rand in identificarea"modulelor" apJicatiei, datele fiind "ascllnse" in cadrul fiecarui modul. ModuluI trebuicsa contina funetii "de interfata", care sa permita accesuJ la datele "ascunse" in modul.Utilizatorul moduluJui nu are acces direct 13 date, accsta -fiind permis daar prinintcrmediul funqiilor de "interfala". Chiar dadi reprezentarea datelor se schimba ~i,

in consecinta, ~i impIementarca funqiilor de prelucrare a datclor, acest lucru nu estctransparent pemru utilizator, fijnddi accesul se rcalizcaz:1 prill aceeasi iJlterfa~a. illplus, acccsul la date fiind limitat, crc:;;tc securitatca aplica~iei.

Polimorfismul

Etimologic,' cuvanrul polimorfism provine din limba grcaca. de Ja polys (multe) simorphos (forma). In POD, prin polimorfism se intclege posibilitatea ca , prin apelareaunei functii , sa obtinem efccre diferite, in functie de contextu l apelului. Reluandanalbgia cu lumea vie, mentionam ca toate anirnalele trcbuie sa alba functia "dereproducere; dar accasta functie "se executa" diferit in functie de context (Intr-unmod are Ioe, de exemplu, reproducerea la pasan, in alt mod la mamifere).

In C++, polimorfismul se poate obtine prin supraincarcarea functiilor (overloadin.g)sau, in cazul claselor derivate, prill redefmirea unei funqii a clasei de baza (overriding).

1.3. Avantajele POO

Principiile care stau la baza POD eonduc la 0 serie de avantaje in ceca ce privc~tc

dezvoltarea aplicatiilor. Aplicaliile au a structura modulara. Moduleie :pot ti dezvoltate separat ;

- pot fi modificate separal (tara a afecta functionalitatea intregii aplicarii) ;poth reutilizate in alte "aplicarii;pot fi extinse ulterior.

Page 8: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

II

-'

14 PROGRAMAREA iN LIMBAJUL etc++ PENTRU LICEU

Toate acestea conduc la cresterea productivitatii (timpul necesar pentru dezvoltareeste mai scurt. costurile suru reduse, mentenanta aplicatiei este mai usoara).

1.4. Intrebari recapitulative

i-'

J

b. mostenire ;d. multitasking.

2.1. Clasele ~i obiectele

2. Programarea orientata pe obiecte in C+ +

In dictional', termenul claslieste definit ca 0 multirne de elemente ell insusiricomune. Prin insusiri comune putem intelege atribute comune sau comportamentecornune. Sa considerarn clasa cainilor. Toti cainii au atribute si comportamenrecomune. De exemplu, toti cainii au blana, deci un atribut interesant ar putea fi.lungimea parului. Tori cainii Jarra - acesta este un comportament comun.

In esenta, 0 clasa reprezinta exact acelasl lucru 1;'i in cazul PDQ. Clasa dcfinesrecaracteristicile comune (arribure, comportamente) ale obieetelor c1asei. Mai exact, ellajutorul claselor putem defini propriile noastre tipuri de date.

, Din punct de vedere sintactic , declaratia unei clase este :

Iclass NumeClasa

: {lista_declaratii_membri} j

unde:

• NurneCLa s a = numele tipului clasa declarat• Ll s t aLdec Lar-ar ni.__membri = secventa de declarant ale mernbrilor clasei

(contine declaraji! de date membrc, precum si declarant sau definitii de functii..membre).

Datele -membre corespund atributelor, iar functiile membre corespund cornporta­mentelor. Functiile membre ale unei clase mai sunt denumite metode.

Ca prim exemplu, sa deciaram clasa Caine:

class Caine

JJ

J

J

J

J

J

J:1.J

Iidata membruIlfunctie membru

int Lurrq-imepar- j

void La t r-a () {c o u t c c vHam l v i )

1. Care dintre urmatoarele afirmatu sunt corectc ?a. Limbajul c++ permite mostenirea, dar aceasta nu este recoruandata, deoarecc

este consumatoare de limp.b. Principiul tncapsularf dateJor presupune ca datele sa fie toate impreune in

aceeasi srructura de date, fiind permis accesul 1a datele din structura.c. Abstractizarea datelor inseamna sa definim sumar structura de date.d. In Iimbajele care permit programarea orientate pe obiecte nu se mai utilizeaza

programarea strucrurata.e. Niciuna dintre variantele precedente.

2. Principiul care permite ca aceeas! actiune sa fie executata in mod diferit in functiede context se numeste :a." poligamie;c. polimorfism;

3. Dati exemple din viata cotidiana care ilustreaza mostenirea.

4. Dati exemple din viata cotidiana care ilustreaza polimorfismul.,g~Yi

f!t

,~

1

'1IP

Un obiect este 0 variabila _de tip clasa sau, mai elegant forrnu lat, 0 instantiere aunei clase.

De exemplu :

Caine Gri v e a. Az o r e I

Gri v e.i si Az o r-e I sunr doua instante ale clase i Cein e (doua obiectc j.

JJ1

Page 9: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

De exemplu :

Accesul Ja un membru al unui obiect se realizeaza in mod similar eli accesuJ la uncamp al unei variabile de tip s t r-uc t , utilizand operatorul de selectie directa :

obiect.membru

o analogie relevanta pentru a intelege mai bine conceptele de ctasa ~i obiect estecea ell forma de pr-ajituri . Forma de prajituri cste clasa ; ea defineste aspecrul ruturorprajiturilor care VOT fl taiare ell forma respcctiva. Prajuurile pe care lc taiem ellforma respectiva reprczmta obiecrele clasei.

'7PROGRAMAREA ORIENTATA PI: OBIECTE jN C-:-.-'----

Observatii

1. Un specificator de acces ramane valabil p,1na 13 aparitia unui alt specificator,

2. Conform principiului Incapsularli datelor, datelc mcmbre ale unci clase ar trebuisa fie "ascunse" in interlorul clasei. Cu aite cuvinte, nu trebuie sa fie publice.Clasa ar trebui sa cantina metode speciale publice, prin care putem 55 aflam valoareadatei mernbre sau sa 0 modificam. Aeeste funcui se numesc accesori, Este frecvenrutilizat prefixul Get pentru numeJe unui accesor care rcturueaza valoarea. rcspectivpreflxul Set pentru numelc unui accesor care modi fica valoarca darei membre.

3. in general, este de dorh sa minimizam numarul de mernbri publici ai unei clase;mcmbrii publici vor corrstitui partea de "interfata", prin intermedtul caret elasainteracnoneaza cu exteriorul.

4. 0 analogie relevanta pentru tnjelegerca modului de proiectare si de utilizare aunei clase este cea eu aparatul de radio. Un utilizator obisnuit al unui aparar deradio obrine efectele dorite actionand butoancle de pe carcasa aparatului de radio(pentru a deschide aparatul, apasa pe un buton, pentru a modifies volumul ,roteste un alt buton etc.). Butoanele acestea reprezinta de fapr metodele publiceale clasei. In mod normal, un utilizaror al aparatului de radio nu va desfacecarcasa aparatulul pentru a avea acces direct la ceea ce cste in interior (interiorulaparatului reprezentand membrii privati ai clasei).

_', _~c]asa

,~?

••."'>J

PROGRAMAREA iN UMBAJUL C'/('+-f PENTRU UCEU

Obiecte

16

\1r~I,'i

~,,~

,:~

I

I,t

If -,I'-

cout<:<Grivei.GetLungimepar();

{ c ou t.c cvHeml v:{ .return Luriqi.rne Par :{ LungimePar = Xi

iI _

r,, -

lr, ,

;,IiI-,

Grivei.Lungirnepar=10i//pentru obiectul Grivei am atribuit datei membru//Lungimepar valoarea 10Grivei.Latra() ;flam apelat funct;ia membru Latra() pentru obiec'[.ul Grivei

2.2. ControluI accesului Ia membrii unei cIase

in procesul de pr'oiectare a unci clasc, 0 atentie specials trebuie acordatacontrolului modului de acces pentru mernbrii unci clase, in acest scop pot fi utilizatitrei specificatori de control al accesului :

• public = membrul poate fi accesat din or-ice functie din domeniul de declaratie

al clasei ;• private = membrul poate fi accesat doar din functiile rnembre ale clasei,

precurn si din functiile pnetene (friend) ale clasei;• protected = ca efect, este similar cu private, dar, in plus, accesul este

permis ~i pentru functiile mernbre sf fuuctiile prietene ale claselor derivate din

clasa respectiva.

Specificatorul implicit este priva teoDin pUllct de vedere sintactic, un specificator de control 31 accesului sc prccizeaza

astfcl :

t specif:'lcator:

Exemplu

Sa rescriem cIasa Caine, controland accesul 1£1 data membra Lu.nq LmePa r :

class Caine{private:

int LungimePar;public:

void La t.r-e ( )int qetLungimePar(}int SetLungirnePar(int x)

Data membra LuriqLmePa r- este privata, in timp de merodele La tra' (') ,Oet.Lunqi.mePar () ~i Se t LunqamePar () sunt publice (ultimele doua fiind acccsorl).

Pentru a stabili lungimca parului lui Grivci, vom apela accesorul Ser.Luriq.ime.Par- ( )

Grivei.SetLungimepar(lO) i

Daca dorim sa aflsam lungimea parului lui Grivei :

o incercare de a acccsa direct data membra Lurrq i.rne Pe r () suh forma:

~9ut«Grivei.LungimeP2r;

va genera un mesaj de eroare la compiJare.

Page 10: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

18 PROGRAMAREA iN LIMBAJUL C/C -+--I PENTR li LiCEU

2.3. Arhitectura unei aplicatii POO

u

Difereute dinrre 0 functie inline ,o;;i una uzuala consra in faptul ca fiecare apel alfunctiei inline este inlocuit de compilator cu codul funcnei.

Avantajul consta In cresterea virezei de executie a codului, fiind evirate operatiileaferente 'apelului de functie (de exemplu, alocarea pc suva a mentone! necesareapeJului, copierea valoriJor parametrilor, returnarea valorii calculate de functic).DezavantajuJ consra in faptul ca va creste dimensiunea codului sursa.

I~

Ii

Pentru fiecare clasa se gcnereaza doua fisiere :• un fisier care conjine declaratia c1asei; acesta va fi un Fisler antct (header), care

va avea numele clasei si extensia . h ;• un fisier care contine implementarea clasei; in acesr fisier sursa (fisier ell numele

clasei $i ell extensia . cpp) se afM. definitiile functiilor clasei.

in or-ice fisier sursa este necesar sa utilizam clasa si vain include fislcrul antet :

#include "NumeClasa.h"

o aplicatie va consta dintr-un project care va contine mai multe fislere sursa. doarunul dintre acestea continand functia main ( ). Grice functie va fl defirnta 0 smguradata (in fisierul sursa in cafe apare implementarea sa), dar va fi declarata ori de careori este necesar (pr-in includerea fisierului antet ccrespunzaror).

2.4. Definirea functiilor membre in exteriorul clasei

Cand definim 0 functie membra a unei clase in exteriorul clasei trebuie saprecizarn sl clasa careia ii apartine. Pentru aceasta vom preceda numele functiei denumele clasei, utilizand operatorul de rezolutie : : astfel :

~ NumeClasa: : NumeFunctieMembra

Este destul -de firesc, avand in vedere ca in clase diferite pot exista functi i euacelasi nume.

Exemplu

Vom incepe sa construirn pas eu pas 0 clasa pentru ·luerul ·ell fractii, - Pentru aspecifiea 0 fractie trebuie sa retinern numitorul !?i numaratorul fractiei (aeestea vor fidatele membre private). Pentru inceput, vom defini accesori ,o;;i 0 functie de simplifi­care. Declaratia clasei se va afla in flsierul antet fractie. h :

c~ass fractie{private:

int a; //numaratorint b; //numitor

publ.ic:int GetNumarator() { return a;int GetNumitor() {return b;void SetNumitor(int);void SetNumarator{int)void Simplifica();

} ;

void fractie: ; SetNumi tor (int y)( b=y; )

void fractie: :Simplifica(){int X, y, r;

//ealculez emmdc eu algoritmul lui Euclidx=a; y=b;while (y) { r=x%y; x=y; y=r;a/=x; b/=x; //simplifie

}

Ca sa ilustrarn modul de utilizare a c1asei fractie, in functia main ()declara un obiect de tip fraetie, vom inltializa numitorul si numararoru},simplifiea fractia, apoi 0 vom afisa simplificata.

#include <iostream>#inelude "fractie.h"

using namespace std;

int main ()

fraetie f;f.SetNumitor{12)jf.SetNumarator(8} ;f.Simplifiea() ;eout«f.GetNumarator()«'/'«f.GetNumitor();return 0;

Evident, executand acest program, se va afisa pe ecran 2/3

2.5. Functlile inline

J1

-I

Jvom Jvom

JJJJJ1

'--'

J

Page 11: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

2.6. Functiile ell parametri impliciti

Dinpunct de vedere sintactic, definitia unei functii inline este similara ell definitiaunci fUI1CIii uzuale, nurnai ca este precedara de cuvantul-cheie inline.

Exemplu

inline int max(int a, int b){ return a > b ? a : bi }

Pentru a corespunde unei varietan cat mai man de situatii, functiile sumproiectate de obicei eu un nuruar foarte mare de parametri, chiar daca pentru uni iparametri se utilizeaza frecvent la apel aceeasi valoare.

Pentru ca functiile respective sa fie mai user de utilizat , limbajul C+ + a introduso facilitate suplimentara, prin care programarorul poate declara in antetul functieivalori irnplicite ,

21PROGRAMAREA ORIENTATA PE Ol3IECTE iN C++

Exemplu

Functia precedents f () definite mai sus 0 putem apela eli un parametru :

f (9) ;

2.7. Supraincarcarea functiilor

in acest caz se utilizcaza valorile implicite ale parametrilor b ~i c si se afiscaza 9J.2.Sau 0 putem apela cu doi parametri :

f (9,8) i

in acest caz se utillzcaza valoarea implicita a parametru1ui c ~i se afiseaza 982.Sau 0 putem apela ell trei parametri :

f (9,8,7) ;

in acest caz nu se utilizeaza valorile implicite ale paramctriJor si se afiseaza 987.

Exemplu

Un exernplu dcfunctie cu parametri implicit] pe care l-ati utilizat deja este functiagetline (), functie membra a clasei istrearn:

Prototip :

istream & getline(signed char*, int, char = '\n') i

Puncpa citeste caracterele de la intrare si Ie plaseaza III sirul deseris de primulparametru. Operatia se termlna fie cand s-au extras atatea caracrere care specifics eelde-al doilea parametru, fie Ja intalnirea marcajului de sfarsit, specificat de eel de-a!treilea parametru, Observati ca eel de-al trcilea parametru are ca vatoarc implicitacaracteru1 newline (deci, implicit, citirea se terrnina 1a sfarsltul liniei).

PROGRAMAREA iN LIMBAJUL C/C ++ PENTRU LICEU

Observatii

1. Functiile inline trebuie sa fie foarte seurte.2. Functiile recursive nu pot fi functii inline.3. Compilatorul poate ignora declaratia inline.4. Functiile lnline combine avantajele macrourilor eli cele ale functiilor , in acest

mod, ca si in cazul macrourilor, se elimina operatiile aferente apelului, darpastreaza toate proprietatile fuuctiilor in ceca ce priveste validitatea apeluJui,transferul parametrilor, declaratiilc.

Functiile membre definite in declaratia clasei sunt implicit tuncpf inline,

in exemplul precedent, functiile GetNumi tor () ~i Getnumarator () sunt, prinurmare, functii inline,

20

~

~,

~

-

~

Exemplu

void f(int a, int b=l, int c=2){cout « a « b « c;}

Functia f () are trei parametri, dintre care doi ell valori implicite (b are valoareaimplicita 1, iar care valoarea implicita 2).

La apelul functiei se pot omite parametrii actuali corespunzaton parametrilorformali cu valori implicite, ill acest caz utilizandu-se valorile implicitc ale acestora.Pentru ca la apel corespondents parametru actual - parametru formal sa se executecorecr, parametrii eu valori implicite sunt intotdcauna ultimii declarati in lista deparametri a functiei.

Valorile implicite se specifica 0 singura data (fie in definitia funcriei. fie in decla­raria acesteia ; uzual sunt specificati in declaratie, deoarece compilatoru1 valldeazaapelul de functie In conforrnirate cu declaratia acesteia).

Cea mai puternica facilitate introdusa de limbajul C -+ -1- referitor la functii constain posibilitatea de supraincarcare' a functiilor.

Supraincarcarea ofera programatorului posibilitatea de a defini mai multe functiicu acelasi nume, dar care diferii prin uumarul si/seu tipul paramctrilor,

Exemplu

Definim 0 functie surna () care calculcazll suma a doua nuruere intregi :

int surna (int a, int b){return a+bi}

J. Tcrmenul ,.supraindircarc" cstc 0 truduccre a tenucnului cngtczesc ovcrtoaaing, in uncle diqiputeti intaln i si tcrmcnul "sllpradcfinirc", ell acecasi scmnificatic.

Page 12: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

22 PROGRAMAREA iN LIMBAJUL C/C ++ PENTRU LICEl] PROGRAMAREA ORJENTATA. PE OBIECTE IN C+ + '3

int surna (int * a, int nl

Un apel de tipul :

2.8. Constructorii

for (int i=O, 5=0; i<ni i++) s+=a[iJreturn S·

w

e-

u

'-'

e-

int y)

fractie rz . £2(5), f3(S,12);

cout<-:fl.GetNumarator{)«'/'«fl.GetNumitor()«'\n'cout«f2.GetNumarator()«'j'«f2.GetNumitor()«'\n'cout«f3.GetNumarator()«'j'«f3.GetNumitor{)«'\n'

#include <iostream>#include "fractie.h~

using namespace sto;int main ()(

} ;

Vom defini acest constructor in extenorul clasei astfel :

• numeJe constructorilor coincide cu numele clasei ;• in declaratia/definitia unui constructor NU se spectfica tipul rezultatului.

a class poate avea mai multi constructori, prin supratncarcare. Daca in cadruldeclaratiei clasei nu am specificat niciun constructor, compilatorul va genera automatun constructor implicit (constructor fara parametri).

Pentru a putea crea obiecre ale clasei, construcroru trebuie sa fie publici ..

Exernplu

Yom completa dcclarajia clasei fractie ell un constructor. astfel :

class fractie{private;

int a; //numaratorint bi //numitor

public:int GetNumarator{) { return a;int GetNumitor() {return bivoid SetNumitor(int);void SetNurnarator(int);void Sirnplifica(};fractie(int x=O, int y=l)

folosind constructorul fara parametri pentru obieetul f 1 (In acest caz s-au folosuvalorile implicite ale parametrilor , adica f 1. rcprcznna fractia 0/1) ;folosind .constructorul cu un singur parametru pentru obicctul £:2 (in acest cazpcntru al doilea parametru s-a folosir valoarea implictta, dcci £2 reprczlma fracua511) ;

folosind constructorul eli doi parametri pentru obiectul f3 (f3 reprczinra fractia8/12).

.1; f r ac t Le : : fractie (int x ,, { avx • b~y; }

Observati ea am ales sa definim un singur constructor, cu valori implicite (valorileirnplicite le-arn specificat la dec1ararea constructorului). Pentru excmplificare, infunctia main () a111 creat trei obiecteale clasei (f L, £2, £3), in trei moduri diferite :

III

int get();istream& get (char &);istream& get (char * int 19, char = '\n'listream& get(streambuf &, char =. '\n'};

Forma 1;Forma 2:Forma 3:Forma 4:

Desi nu am discutat explicit despre aceasta, am folosit deja supraincarcareafuncjtilor. De exemplu, functia get (), functie membru a clasei istre.am, este 0

functie suprajncarcata, avand urmaroarele prototipuri :

Putem supralncarca functia surna ( ), astfel iucat sa calculeze suma elementelorunui vector:

Cornpilatorul este eel care selecteaza la apel functia adecvata 'in functie de Iistaparametrilor acruali. in primul rand, se cauta 0 corespondenta exacta (0 functie pentrucare tipurile parametrilor forrnali sa coincida eu parametrii actuali ai apelului respectiv).

Daca nu este gas ita. 0 corespoudenta exacta, se fac conversii de tip implicite (deexemplu, tipul float este convertit Ia double; .char este convertit la int etc.).in acesr caz pot aparea ambiguitati (compilatorul nu poatc identifica in mod unicfunctia pe care trebuie sa 0 apeleze).

Exernplu

Probabil eel mai frecvent caz de ambiguitate apare din cauza functiei sqrt ( ) . inc+ + functia sqrt () este supraincarcata astfel :

long double sqrt(long double);float sqrt{float);double sqrt{douh1e)

int Xi

sqrt tx ) ...

va genera la compilare un mesaj de eroare, deoarece compilatorul nu stie la caredintre eele trei tipuri reale sa-! convcrtcasca pe x.

Utilizarea functiilor supraincarcate reprezinta unul dintre cele mai imporrantemecanisme ale programarii orientate object.

Constructorfi sunt functi i membre ale clasci care au caracteristici speciale :

CI se apeleaza automat la crearea fiecann object al clasei ;

Page 13: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

,.

r,

24 PROGRAMAREA iN LlMBAJUL etc: ++ PENTRU L1CEU

f3.Sirnplifica();

cout«f3 . GetNumara.tor ()« I / '«£3. GetNumitor ()« I \n' ;return 0;

PROGRAMAREA ORIENTA'fA PE OBlECTE iN C+-I-

sir= new char[lg);Iialoc dinamic memorie pentru vectorul care retineIlcaracterele mesajuluifor (i=O; i<lg; i-r+) sir[i]=s[iJIlcopiez caractere1e mesajului

)

25

Evident, executand aces! program, obtinern pe ecran :0/15/18/122/3

Exemplu

Clasa fractie putea fi urilizata ~i fa,ra a declara un constructor. S-ar fi gene ratautomat un constructor implicit si am fi purut utiliza clasa in madul prezentat laprima forma de dcclarare a clasei ,

Pentru a exemplifica sl 0 situatie in care declararea unui constructor este obli­gatorie, vom dec1ara sl vern implementa 0 clasa denumita mesaj. Datelc membrusunt lungirnea mesajului ~i un vector care va contine caracterele mesajului. Pentru eamemoria alocata vectorului sa fie exact eea nccesara, vom aloea dinamic memoriepemru mesaj. in concluzie , la erearea unui obiect al clasei trebuie sa alocam dinamicmemoria nccesara (evident, III consrrucrori).

Declaratia clasei mesaj (stocata III fisierul mesaj . h) va arata astfel:

~

,...,

class mesaj{private:

char * sir;int 19;

public:mesaj ();mesaj (char *);int GeLLg ( ) ;voi.d Sc:rie();

Ilconstructor fara parametriIlconstructor supraincarcat

int mesaj::GetLg(){ return 19;

void mesaj: :Scrie()if (sir)

for (int i=O; i<lg; i++) coutc c s Lr jijelseCout«"Mesajul es t e vid";

cout«' vn ' ;

Pentru exemplificare, III functia main () am creat doua obiecte de tip mesaj ;pentru obiectul m1 am utilizat constructorul tara parametri, iar pentru obiectul m2,constructorul care primeste ca parametru un sir de caractere :

#include <iostream>#include "mesaj.h"using namespace std;int main (){

mesaj ml , m2 ( "Ana are mere.") ;cout«m1.GetLg()«' '; ml.Scrie()cou t c-emz . Get,Lg () -cc ' '; m2. Scrie ()return OJ

)

Executand acest program, se afiseaza pe ecran :

o Mesajul este vid13 Ana are mere.

2.9. Destructorul

DestructoruI este de asemenea 0 functie membra specials a unei clasc, datortracaracteristicilor sale:

(Ja Incheierea ciclului deatunci cand este util izat

unui obiect al claseiobiectelor dinamice ,

declarat un destructor,

este apelat automat Ja eliminareaviata a] obiecrului sau, III cazuloperatoruI delete) ;trebuie sa existe ; daca 111 cadrul cJasci nil este explicitcompilatorul genereaza automat un destructor implicit;destructorul nu poate fi supraincarcat (esre unic) ;

mesaj : : me s a j ( ){ 19=0; sir=NULL;

mesaj: :mesaj (char * s){int i;19;=;strlen(s) I/determin lungimea siru1ui

) ;

Declaratia estc incompleta, urmand sa 0 completam 111 sectiunile urmaroare.Observap ca am declarat doi constructori : un constructor flira parametri si unul carepnmeste ca paramctru un sir de caractere.

In fisierul sursa mesaj . cpp vom defini construcrorii si functiile membre GetLg ( )st Scri e () asrfel :

~

Page 14: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

'6 PROGRAM AREA IN LIMI3AJUL C/C+-+ PENTRU LJCEU PROGRAMAREA ORIENTATA. PE OBIECTE IN C+ + 27

'-'

• are acelasi nume ca si clasa, precedat de caracterul - ;• nu arc argumente sl nici tip rezultat.

Exemplu

In clasa fractie nu Yom dec1ara Ull destructor, pentru ca nu este necesar(cornpilatorul va genera automat un destructor). Dar, in clase mesaj, un destructoreste obligatoriu, pentru ca arunci cand un obiect a1 clasei este eliminat, trebuie sa fieeliberata si memoria alocata dinamic pentru vectorul de caractere.

Declaratia destructorului in cadrul dcclaratiei clasei va fi :

-mesaj ();

Iar definitia destructorului in exteriorul clasei va fi :

mesaj : : -mesaj ()[

delete sir; //eliberez memoria alocata

2.10. Modelullogic al vietii unui obiect

Modelul logic al vietii unui obiect poate fi ilustrat astfel :

Se creeaza un.obiectEste apelat un constructor

Obiectul ,,·traie~te"

Este apelat destructorul

Exemplu

In exemplul urmator am declarat a clasa denumita fie t iv, ln care am inclus unconstructor, un destructor §i -funetia membra Scrie (). Toate cele trei functiimembre nu fac decat sa afiseze pe ecran cate un mesaj care are rolul de a evidentiamomentul executiei functiei.

Plsierul f i.c t i v . h :

cl.ass fictiv(

publ.ic:fictiv()

-ficti-v() ;void Scrie ( )

} ;

Fisierut fictiv.cpp:

#include "fictiv.h"#include <iostream>using namespace std;fictiv: :fictiv() Ilconstructor{ cout«" Am creat un obiect! \n" ;fictiv: :-fictiv() Iidestructor{ c ou t.«-c " Am eliminat un obiect! \n" ;void fictiv: :Scrie(){ cout«"ObiecLul traieste!\n";

in fisierul main. cpp ilustram ciclul de viata al unui obiect in doua moduri :

in functia f () am declarat 0 variabila locale ob, de tip fieti v; acest obiect vafi creat in momentul apelarii functiei f ( ), va "trai" pc durata executiei functieif () si va fi eliminat la terminarea functiei f () ;in functia main () am declarat un pointer la un obiect de tip fictiv denumitp_ob, cu scopul de a retine adresa unui obiect alocat dinamic; la alocareadinamica a obiectului se apeleaza automat constructorul ; acest obiect va "traj"pana la eliberarea sa dinamica, folosind operatorul delete.

#include <iostream>#include "fictiv.h"using namespace std;void f (){fietiv Obicout«"Suntem in functia f: "; ob.Serie(};

int main (){ f ( ) ;

fictiv * p_ob=new fietiv;cout« ,. Suntem in functia main: "; p_ob->Scrie ( )delete p_..ob;return 0; }

Executand acest program, .pe ecran se va aflsa :

Am creac un obiecc!Suntem in functia f: Obieccul traies~e!

Am eliminat. un obiect!Am creat un obiecL!Suntem in functia main: Obiectul traieste!Am eliminat un obiect!

Observatie

In functia ma i n (), pentru a acccsa functia mcmbru Scrie () a obiccwlui alocatdinamic, am utilizat opcratorul de selcctic indirccta -;'. intrucat am acccsat obiccrul

~

..J

-'

w

j

Page 15: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

2R PROGRAMAREA IN LJMBAJUL C/C++ PENTRU LlCELJ PROGRAMAREA ORIENTATA PE QBlECTE iN c t -+ :!9

,~

~

.'-..,

indirect. pr-iu intermediul pointeruJui care conrlne adresa sa. Reamintim ca cfectulconsrructiei p_ob->rnembru este echivalent ell (*p_ob) .membru.

2.11. Constructorul de copiere

o alta funcrie membra specials este coustructorul de copierc. Coustructorul decopiere se apeleaza automat ori de cntc or! este necesara copierea unui obicct a] easelrespective (de exemplu, Ja transferul unui obiect ca parametru sau rczultat aI uncifunctii , Ia crearea un or obiecte temporare).

Grice class trebuie sa aiba un constructor de copiere. Daca nu este declaratexplicit unul, compilatorul va genera automar un constructor de copiere implicit, careccpiaza obiectuJ mcmbru ell membru.

NumeJe constructorului de copiere coincidccu numele clasei, nil arc tip rezultat,iar ca parametru rrebuie sa primeasca a referinja la Ull obiect al clasci respective.

numeclasa (numeclasa & obci e c t.) j

Exemplu

Sa revenim Ia clasa mesaj, pc care 0 vom completa ell un constructor de ccplere.Declaratia constructorului din cadrul clasci mesaj va fi :

mesaj (mesaj&) ;

Definitia constructorului de copiere din cxteriorul clasei va fi :

mesaj: :mesaj(mesaj& m){ int i;

19=m.lg; //copiez lungirneasir=new char[lg]j I/aloc memorie pen~ru vectorfor (i=O; i<lgj i+~-) sir[iJ=m.sir[iJ;Ilcopiez carac~erele din mesajul m in mesajul curent

Daca nu am fi declarat un constructor de copiere 111 clasa mesa j, compilatorul arfi generat un constructor de copiere. Dar acest constructor nu ar fi functional coreet inacest caz, dcoarece unul dinrre membrii clasei este un pointer, iar 110i nu mtenrlonamsa copiem pointerul , ci conrinutul zonei de mernorie a carei adrcsa se aOa inpointerul respccriv. Ca urmare a copierii pointerului vor aparea doua problemc :

daca intentionarn sa modificam zona de mcmoric a carci adrcsa sc afla ill pointerpentru obicctul copie, va fi afectara de fapt zona de mernorie illdicat<l de poimeruldin obiecml copiat (sunt doi pointeri diferili, dar care indica aceca~i zona dememorie) ;cand obiectul copie este elimimn (eJ fiind Ull obiect tcmporar) estc apelatdestructorul; destructorul va inccrca sa elibereze zona de mCl110rie alocau1dinamic pentru obicctul copie; poimcrul copie ~i painteruJ .dill obiectul copialindidind 0 aceea;;i zona de mCl110rie, se cJibcrcaz3 0 zona de mcmoric care nu nrtrcbui elibcrara.

in concluzie, atunci cand membri i unci clase sunt pointeri catre zone de memoriece urmeaza sa fie alocate dinarnic, construcrorul de copiere general automat decompilator 11U cste suficicnt, trebuie sa definim explicit uu constructor de copiere.

2.12. Pointerul this

in fiecare functie membra nestatica a unci clase este automat declarat un pointerconstant, denumit this, care are ca valoare adresa obiectului curent.

Uneori este necesar sa urilizam si noi explicit pointerul this. De exemplu, atune!cand 0 functie trebuie sa rctumezc ca rczultat obicctul iususi :

I: recurn *this;

2.13. Membrii statici ai unei c1ase

o clasa poate contine membri statici (date si functii).Din punct de vcderc sintactic, specific este faptul ca dcclararca membrilor starici

este precedata de cuvantul-cheie static.Referirea 1a un membru static al unei clase din exteriorul clasei se poate real iza in

doua moduri :

t· NumeObiect.NumeMembruStatic

NumeClasa: :NumeMembruScatic

eel de-al doilea mod de referire este posibil datot-ica faptului ca mernbr'ii staticisunt aceiasi pentru toate obiectele clasei (deci nu caracterizeaza un anumit obiect, c!

mrreaga clasa).

Datele membre statice

Pentru datele mcmbre nestatice exlsta copii distinctc in fiecare obiect al clasei.DateIe rnembre statice au 0 valoare unica, comulla pentru reate obiectele clasei. Dinacest motiv. datcle membre statice sunt supranumite variabilele ctasei, dcoarecc sccomports ca variabileJe globale.

Membrii static! repreaima 0 solutie optima in cazul 111 care ansamblul obiectelorclasei utilizeaza date 111 comun , deoarece :

se reduce numarul de variabile globale :se asociaza explicit datcle starlee eu 0 anumita clasa ;spre deosebire de variabilcle globale, in cazul membrilor statici cste posibil

comroluJ accesului.

Deoarecc pemru 0 data memhri:! statica sc asociaza 0 singura zonu de mcmoriepemru Intreaga clasa, trehuie sa existc 0 dcfini\jc J datci mcmbrc statiee ill afaraclasei. Sintaxa unci 3stfel de definilii este:

l tip NumeClasa: : NumoMernb:o.-uStat:i.c;

Page 16: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

r

30 PROGRAMAREA iN LTMBAJUL C/C +-1 PENTRV LlCEU PROGRAMAREA ORIENTATA. PE OBIECTE iN C+ + 31

Clasa ExStatic are 0 data membra statica (n). un constructor (careincrementcaza pe n la crearea unui obiecr) ~i un destructor (care decrementeaza pe nIa eliminarea unui obiect). Sa utllizam aceasta class in diferirc rnoduri :

La definire este posibila .!?i ininalizarea datei membre (implicit compijatorul vainitializa ell 0 datele membre statice).

Exemplu

Pentru exernplificarea modului de functionare a unei date mernbre statice, vomdeclara 0 class flctiva denumita ExStatic astfeJ :

}; Ilconstructor}; Ildestructor

class ExStatic{ public:

static int n;Ex.St.e t.Lc () { n++;

-ExStatic () { n--;} ;

int ExStatic::n=O;

void f (){ ExStatic Obi

cout « ob.n «'

//definire 8i initializare

lise creeaza obiectul local ob//scrie 7

Functiile membre staticeFunctiile membre statice efecrueaza operatii care nu sunt asociare obiectelor

individuale, ci intregii clase. Functlile membre statice se refers numai 1a date stance~i nu .se pot referi la this (deoarece this este definit daar in cadrul obiecrelor,reprezentand adresa obiectului curent).

Exemplu

Pentru exempJificare, vom adapta clasa ftctiva preccdenra EXStatic. Mai exact,vern transforma data mcrnbru statica din membru public in membru privat si vomadauga functii publice de acces (0 functie statica ~i a functie ncstatica). Vom adauga~j 0 data membru nestatica, pentru a evidcntia potentiale erori.

class ExStatic{private:

static int n;int m;

public:ExStatic () { n++i }; //constructor

-ExStatic () { n--; }; //destructorvoid Set (int a, int b) { n=ai m=bistatic void Scrie () {ccu t.e cn-c c ' "r J

) ;

,.~

,-,'

'--'

Executand programul , se va afisa : 1 6 7 6 7 6

Observajii

1. La mernbrul static nne-am referit in doua modun diferite (Ex S't a t aci en ~i prininrermediul unui obiect a. n sau ob. n). Indiferem de modul de referire, vaJoareala care De referim este aceeasi.

2. Deflnirea si inijializarea membrului static n s-a realizar in afara clasei.

3. Datele stance exisra, chiar daca nu exisra obiecte ale clasei respective.

;

..

Pentru a afisa valoarea membrului static privat n, se va utilize functia statica Scrie () .Aceasta functie acceseaza dear membrul static n (fiind 0 funcpe starica). Functia Seteste nestatica, deci poate accesa atat mernbri static! cat §i membri nestatici ai cJasei.

int ExStatic::n=Oi //definirea datei membre statice

~

~

~

~

//creez un obiect//scrie 1//creez un vector eu 5 obiecte//scrie 6//creez dinamic un obiect/Iscrie 7

//scrie 6

//scr::e 6

/ /scrie 100

//scrie 7

int main (){ExStatic aj

ExStatic::Scrie()iExStatie b [5] ;ExStatic::Scrie()iExStatic* c=new ExStaticia.Scrie()idelete Ci

ExStatic: :Scrie()if I) ;ExStatic: :Scrie()ia.SetllOO. 200);ExStatic: :Scrie~) ;return 0 i

void f (){ EXStatic Obi

ob.Scrie() i

//creez un obiect//scrie 1/ /creez un vector eu .5 obiecte//scrie 6//creez dinamic un obiect//scrie 7//eliberez dinamic obiectul c//scrie 6//apelez functia f//scrie 6

int main (){ExStatic aj

cout« EXStatic::n «' 'j

ExStatic b[5]jcout « ExStatic::n «'ExStatic* c=new ExStaticjcout«a.n«'delete Cj

cout « ExStatic::n «'f ();cout « ExStatic::n «'return OJ

Page 17: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

32 PROGRAMAREA IN UMBAJUL C/C+-1 PENTRU L1CEli PROGRAMAREA ORIENTATA PE OBIECTE iN Ci 33

Executand programul, se va afisa : 1 6 7 6 7 6 100

Observatii

1. La functia stanca Scrie () ne-am refer-it in doua moduri diferite(ExSt.atic: :Scrie() §i prin intermediul unui object a.Scrie() sauob . Scrie ()). 0 functie membra nesratica se utllizeaza doar prin intermediulunui obiect.

2. Daca in functia Scrie () am fl incercat sa afisam si valoarea membrului nestaticm, am fi obtinut 0 eroare la compilare.

Ca urmare, toti mcmbrii dare ai obiectului nu mai pot f modificati. Din acestmotiv, este obligatoriu ca la declararea obiectului sa fie utilizat un constructor care saillitializeze toate datele membre.

Obiectele dcclaratc const nil pot f trausmise pr-in referinte care nil sunt deasemenea cons t.

Exemplu

Pentru exemplificare, vom crea 0 clasa fictiva, dcnurnita Ex.Coris t; , care are 0

singura datil membra (x), un constructor care initializeaza pe x , precum ~i functii deacces 1a x :

2.14. Specificatorul canst

Specificatorul canst poatc f utilizat ~i Ja declararee unui obiecr. sub forma:

~t const NumeClasa NumeObiectj

:-- Specificatorul const poate fi utilizat in diferite contexte, dar efeetul este similarin orice context: elemenrul asupra caruia actioneaza canst nu mai poate fimodificat ulterior.

...... SpecificatoruI canst poate preceda declararea parametriJor functiilor rransmist, prin adresa (poinreri sau referinte) sub forma:

r: tip numefunctie (const tip& numeparametru, ...);

:i!

i1,IJ111,I:'il'i\

::iin

ii'l';:1.;:

'·MII',,!I

i:i;;II:II

'I:!rI'

;!

~\;'Ii:l

const

Ilconstr'l.:lctorx - a;x. = 0;X :::: Yireturn X;

class ExConst{pub~ic:

int Xj

ExConst(int a=O}void ResetValue(}void SetValue(int y)int GetValue() canst

} ;

Sa consideram obiectul ob declarat astfeJ :

Specificatorul cons t aplicat functiilor membre ale claselor

canst ExConst ob(7) i

Urmatoarele trei instructiuni reprezinta tentative i1egale de a mcdifica valoarea luix, prin urmare, vor genera erori la compilare :

ob.x = 5;ob.ResetValue();ob.SetValue(5);

cat ~i in definitia functici :

~ tip NumeClasa: : NumeFunctie (lista-!)arametri)f { ... }

Specificatorul canst asigura compilatorul ca functia nu va rnodifica datelemembre ale clasei. Cu obiectele declarate const se pot utilize dear functii declarateconst.

Constructorii nu trebuie declarati c onet .

Specificatorul const poate fi apltcar functiilor membre ale claselor , mentio­nandu-l irnediat dupa anterul functiei, atat in declaratia functiei :

Ii tip NurneFunct;.ie (lista-parametri) const;

Specijicatorul cons t aplicat variabilelor

Drepr urmare, valoarea variabilei var nu se poare modifica ulterior.

Specijicatorul cons t aplicat parametrilor funcjiilor

Specificatorul const poate fi utilizat 1a declararea variabllelor astfel :

const tip var=valoare;

Specijicatorul cons t aplicat obiectelor

Drcpt urmare, in interlorul functiei valoarea parametrului respccnv nu poate fimodificata. Udlizand specificatorul canst, compilatorul verifies faptul ca valorilecare nu rrebuie sa fie modificate nu vor fi modificate, iar programatorul este asigurat ca.prin apelarea funcjlei , valoarea parametrului respectiv nu se modifica. Prin urmare,ca regula generala, intordeauna .este bine sa' utilizati canst penrru un parametru detip refcrinta a carui valoare nu doriti sa fie modificata.

~,

r-:

~

~

Page 18: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

34 PROGRAMAREA IN LIMBAJUL C/C-t-'-j- PENTRU L1CEU

2.15. Functiile friend

T

PROGRAMAREA ORIENTATA PE OBIECTE IN C+ +

.2.16. Clasele friend

35

'-'

o functie friend poate accesa membrii private si protected ai claseipentru care functia este declarata friend. Pot fi declarate friend arat functi!obisnuite , cat si functii membre ale altar clase.

Pentru a declara faptul di 0 functie este functie prietena (friend) a unci clase,trebuie sa includem in imeriorul clasei declaratia funcjiei, precedata de cuvantul­cheie friend. Functille friend nefiind functii membre ale clasei, specificatorii deacces nu au niciun efect.

Cuvantul-cheie friend se specifica dear la declaratia functiei in interiorul clasei,nu si la definirea acesteia.

,0 aceeasi functie poate fi funcpe friend pentru mai mulre clase si aceeast clasapoate avea mai multe functil friend.

Exemplu

Pentru exempIificare, vom declara 0 clasa fictiva denumita ExvEr Lerrd. in aceastaclasa vom declara 0 data membra privata x si doua functii de acces publice (Setx ( )§.i Getx (). Functia Inc este declarata functie pnercna a clasei EXFFriend.

cJ.ass ExFFriend{private:

int X;

pub1.ic:int Getx() { return. x; }void Setx(int a) { x=aj}

friend void Inc(ExFFriend &);) ;

Funcjia Inc va incrementa valoarea datei membru x. Acest Iueru este po sibtldeoarece functia fiind declarara friend, are acces si Ja membr'ii privati ai cIasei.

Ii void Inc(ExFFriend & ob)~ { ob.x++j }

Observati ca functiile prietene, nefiind fuuctii membre, trebuie sa primeascaobiectul ca parametru. lata cum putem utiliza functia Inc:

ExFFriend a;a.Setx(7) ;Inc (al;

cout«a.Getx{);

Evident, se va afisa pe ecran valoarea 8.

in mod similar eu functiile friend, putern decIara clase friend. Pentru adeclara faptul ca 0 clasa A este prietena (friend) eli 0 clasa B, Yom include in cIasaB 0 declaratie de forma:

~ friend c1.ass A;

Ca urmare, cIasa A va avea acces la membrii private ~i protected ai clasei B.Cu alte euvime, toate functiile membre ale clasei A sunt prietene eu clasa B.

Exemplu

. Yom declara 0 class A ~i 0 clasa B. Clasa A va fi declarata clasa prierena a clasei B.in clasa A se aflf 0 functie membra publica, denumita Suma () care va accesa 0 datilmembru privata a elasei B.

class B;

class A{private:

int y;public:

A(int b=O) { y=b;void Suma (B &) ;

}, j

class B{private:

int X;public:

int Getx() { return Xi }

void Setx(int a) { x=a;}friend class A;

} ;

void A: :Suma (B & ob){ ob.x+=y; }

Observati ca am utilizat 0 declaratie forward a clasei B tnainte de a decIara clasa A.

Aceesra declaratte anunja compiIatoruI ca exista clasa B ~i va fi definica ulterior.lata ~i un exemplu de utilizare a celor doug clase :

A a (10) ;B b;b. Setx (7) ;a c Sume (b);

c out.c cb . Ce t x ( ) ;

Evident, accasta sccventa de instructiuni va aflsa pe ccran va loa rea 1'7.

~

'u

, ;c~

~

--J

-'

:-J

-'

Page 19: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

.,., _ l l~ l!' ,_ -t- ---< :::.7PROGRAM AREA ORJENTATA. PE OB1~I"'''- ;" -PROGRAMAREA IN LIMBAJUL C/C ++ PENTRU LICEU36

2.17. Supraincarcarea operatorilor Utilizarea operatorilor supraincarcati

r--:

r-'

r

; i

r

Supralncarcarea operatorilor este un concept similar ell supraincarcarca functiilor.Pentru a supraincarca un operator, vom defini 0 functie ell numele operator simbal,unde operator este un cuvant-cheie, iar simbal este simboluJ asociat operatorului.

Pot fi supraincarcati doar operatorii existenti in limbajul C+ + si dear pentru a fiutilizati ell clase. Aproape toti operatorii Iimbajului pot fi supraincarcati, exceptiilefiind . (operatorul de selectie directa), * (operatoruJ unar de dereferentiere), : ,:(operatorul de rezolutie}, ?: (operatorii conditionali) ~i operatorul sizeof. Prinsupraincarcare , nici prioritatea, nici asociativitatea operatorilor nu se schimba.

Daca operatoruJ de atribuire = nu este explicit supratncarcat. compilatorulgencreaza automat un operator de atribuire care va copia in obieerul din stangaoperatorului = valorile datelor membre din obieetuJ aflat in dreapta operatoruJui =.

Operatorii pot fi supraincarcati fie ca functii membre ale clasei, fie ca funcjiifriend. Un operator unar poate fi supraincarcat ca functie membra fara niciunparametru (el actionand asupra obiectului curent) sau ca functie friend cu WIparametru. Un operator binar poate fi supraincarcat ca functie membra eu un singurparametru (primul operand fiind eonsiderat obiectul curent, iar al doilea operand esteparametrul) sau ca funcpe friend ell doi parametri.

Operatorii de atribuire (= += = *= /= %= A= &= 1= «= »=),operatorul de selectie indirecta - > si operatorul de indexare [] pot fi supraincarcatidoar ca functii membre ale clasei.

Operatorul de citire » si operatorul de scriere « pot fi supraincarcati doar cafunctii prietene.

Ceilalti opcratori pot fi supraincarcati fie ca functii membre, fie ca fuuctiiprietene, dar in general se respects urrnatoarele reguli :

- operatorii unari sunt supraincarcat! ca funcpi rnembre ;- operatorii binari care nu modifies niciunul dintre operanzi sunt supraincarcati ca

functii prietene ;- un operator binar care modi fica unuJ dintre operanzi e preferabil sa fie functie

membra.

Operatorii supraincarcati pot fi utilizati in doua modur i (uzual, ca un operator sauca apel de functie). Pentru a explica, vom nota cu 0: un operator unar , eu b unoperator binar, iar ell ob si obl doua obiecte. Uzual, operatorul unar 0: poate fiutilizat in forma prcflxata cco'b. Doar operatorii ++ si - - supraincarcati pot fi utilizatisi in forma postfixata (ob++ sau ob--). Operatorul binar 13 poatc fi utilizat uzual ob

il obl.Operatorn supralncarcati pot fi utilize]! §i printr-un apel de functie. Daca

operatorii sunt functii membre ale clasei, apelul se va realiza astfel: ob . opera tor

0: ( ), respectiv ob. operator 13 (obl). Daca operatorii sunt functii prietene aleclasei, atunci apelul functiei se realizeaza astfel: operator ex (ob) sau operator

il lob, ob2).

Exemplul 1. Supraincdrcarea operatorilor ca functii membrepentru clasa mesaj

Peutru a exemplifica supraincarcarea operatorilor ca functii membre vom reluaclasa mesaj, prezentata 1a inceputul accstui capitol, si vern supraincarca urmatorii'operaton pentru aceasta :

• operatorul unar - (care va inversa mcsajul)• operatorul de atribuire ==

• operatorul + (care va avea rolul de a concatena doua mesaje, obtinand rezuJratuJintr-un alt mesaj)

• operatorul +== (care va concatena doua mesaje, obtinand rczultatul in prirnuldintre acestea)

• operatorul == (care vcrifica daca doua mesaje sunt egale)• operatorul : == (care verifica daca doua mesaje sunt difcritc)• operatorul de indexare [)

Declaratia clasei mesaj (in fisierul mesaj . h)

, ,

~

~

Observatii

1. Cand supratncarcam un operator este bine ca prin aceasta sa mentinem semni­ficatia sa initiala, in caz contrar, ar fi mai bine sa definim 0 funqie membra cu unnume sugestiv care sa realizeze prelucrarile dorite.

2. Este bine sa venim in intampiuarea asteptartlor utilizatorilor. Mai exact, sasupralncarcam toti operatorii similari: daca am supraincarcat operatorii aritmeticisau pe biti,. supraincarcarn si operatorii de atribuire compusi corespunzarori (deexemplu, daca am supraincarcat operatorul +, supraindircam $i +=); dacasupraindirdim operatorii relationali ~i de egalitate, ii supraincarcam pe toti (~i ===~i ! =; ~i < ~i > §i >== §i <=); dadi supratncardim ++ §i -- in forma prefixata,atullci ii suprainearcam -5i in forma postfixata.

c1ass mesaj{private:

char "* sir;int 19;

public:me s a j () ;mesaj (char "*)-mesaj () ;mesaj (mesaj&) ;

int GetI,g () ;void Scrie();

//constructor fara pararnetri//constructor supraincarca~

//destructor/ /co:nstruct:or de copieye

Page 20: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

38 PROGRAM AREA IN LIMBAJUL C/C++ PENTRU LlCEU

r

PROGRAMAREP. ORIENTATA PE OBlECTE IN C+ + 39

vo~d Majuscule() i

/Iopera.tori' supraincarcatimesaj operator-();rnesaj& operator=(const mesaj &};canst mesaj operatoy+(const mesaj&) canst;canst mesaj& operator+=(const mesaj&) i

boel operator ==(const mesaj&) canst;inline boal operator !=(const mesaj&) canst;char operator[] (canst int) const;

) ;

Implementarea operatorilor ca functii membre (in fisierul mesaj . cpp)

• Definirea operatorului unar - :

mesaj mesaj: :operator-(){int st, dr;char aux;for (st=O, dr=lg-l; st<dr; st++, dr--)

{aux=sir[st]; sir[st]=sir[dr]; sir[dr]=aux;return *this;

Ii )

Operatorul - poate fi utilizat ~oar in forma prefixata, De exemplu :

mesaj m("12345ABC"1-m;m. scrie () ;

Executand aceasta secventa de instructiuni, pe ecrau se va afisa :

CBA54321

Ca apel de functie, operatorul - ar putca fi utilizat (eu acelasi efect) astfel:

m.operator-() ;

Operatorul de atribuire poatc fi supraincarcat doar ca functie membra si prororipulsall va fi intotdeauna :

NumeClasa& NumeClasa: :operator=(const NumeClasa &}i

Observati ca tipul rezultatului este 0 referinta la un obiect al clasei, Acest lucrueste necesar pentru a putea utiliza operatorul de atribuire in mod inlantuit, subforma: obLeobZ> ... e obk, Din acest motiv, functia trebuie sa returneze la finalobiecrul curent (return *this;).

Deoarece pentru clasa rnesaj constructorii aloca dinamic memorie, iardestructorul elibereaza dinamie memoria alocata, mai sunt doua aspecte la caretrebuie sa acordam atentie cand implementam operatorul de atribuire.

Un prim aspect consul in alocarea memoriei pentru rezultat. Rezultatul trebuie safie stocat in obiectul curent, care esre posibil sa aiba deja memorie alocata. De aceea,trebuiemaiintaisaeliberammemoriadejaalocata.sa alocam 0 alta zona dememorie, suficienta pentru a retine rezultatul atribuirii, apoi sa realizarn copierea.

eel de-al doilea aspect se rcfera la atribuirile de forma obe ob. Accasta este 0

atr-ibuire legala s! operatorul nostru ar trebui sa functioneze. Dar acest caz trebuicrratat separat (if (this == &m) return *this;); in caz contrar, vom eliberamemoria alocata obiectului curent (care de data aceasta coincide eu obicctul care secopiaza si, drept urmare, obiectul de copiat va fi distrus).

• Definirea operatorului de concatenare + :

const mesaj mesaj::operator+(const mesaj& m) const(mesaj temp;int ii'temp.lg=lg+m.1g;temp.sir=new char [temp.lg]ifor (i=O; i<lg; i++) temp.sir[i]=sir[i]for (i=O; i<m.lg; i++) temp.sir[i+lg]=m.sir[i];return temp;

~

, ,

Observati ca am creat un obiect temporar temp in care construim rezultatulconcatenarii ; mai intai alocam dinamic memoria necesara, apoi copiem caractereledin mesajul curent, apoi in continuare caractcrele din mesajul transmis ca parametru.La final rerurnam ca rezultat obiectul temporar.

Explicatii suplimentare sunt necesare referitor la utilizarea specificatoruluicanst. Aplicat parametrului (const mesaj & m), indica faprul ca operatoru! numodiflca parametrul m, transmis prin referinta. Aplicat operatorului (canst dupa antet)indica faptul ca functia nu modiflca datele membre ale obiectului curent. Aplicatrezultatului functie! (const mesaj), irnpiedica scrierea unor constructii ciudate detipul : ml +m2 =m3 .

Operatorul + poate fi utilizat, de exemplu, astfel ;

• Definirea operatorului de atribuire = :

mesaj& mesaj: :operator=(const mesaj & m)(

Ilverificam daca este autoatribuireif {this == &m} return *this;Ileliberam eventuala zona de mernorie alocata dejaif (sir) delete sir;Iialocam 0 naua zona de memorie pentru obiectul curentsir = new char[m.lg];Ilcopiem in obiectul curent obiectul m19=m.lg;for (int i=Oi i<19; .1.++) sir[i]=m.sir[i]return *this;

Ime~aj m~: ml ( "Ana

, mO-ml+ffiL"mO.Scrie{)

" }, m2 ( "are mere")

, '.

i~

, 'I

,

~

~

Page 21: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

40 l'ROGRAMAREA iN UMBAJlJL CIC++ PENTRU LICEU PROGRAMAREA ORIENTATA PE OBIECTE IN C+ + 41

ana are mere buneare mere bune

Pentru ca doua mesaje sa fie considerate egale, elc trebuie sa contina exactaceleasi caractere.

• Definirea operatorului de inegalitate ! 0:: •

inline bool mesaj: :aperatar !=(const mesaj& m) const{

• Definirea operatoru1ui de egalitate =-= :

baal mesaj: :operatar ==(const mesaj& m) const{int i;if (lg!=m.lg) return false;for (i=O; i<lg && sir[iJ==m.sir[i); i++)return (i=-==lg)

Odata supraincarcat operatorul de indexare, putem accesa orice caraeter din vecto­rul de caractere din mesaj :

mesaj rnO ( "ana.poda" )caut«mO [3 J ;

Pe ecran se va afisa litera p. Dar orice incercare de a modifies un caracter dinvector va genera eroare la compilare.

Pentru

Un exempJu de utilizarc a operatorului += :

me s a j rnO ( "ana" ), ml (" are mere"), m2 (" bune");mO+=ml+='m2 ;mO.Scrie() ;nil.Scrie();

Asociativitatea operatorilor de atribuire este de la dreapta la stanga. Prin urmare,rnai intai se concateneaza m2 la ml , apoi noul rnj. Ia mO. Dupa cxecutarea atribuiriJor,pe ecran se va aflsa : .

return (*this == m)

Observati ca pentru a implementa operatorul !:= am util izat operatoruleficienta, am dec1arat operatorul ! = drept functie inline.

• Definirea operatorului de indexare [J :

char mesaj: :aperatar[] (canst int paz) const{

return sir (paz] ;)

Diferenta dintre operatorul + si operatoruJ += consta in faptul ca rezultatulconcarcnarf trebuie sa fie plasat In obiectul curent. Din nou, pentru a putea utilizaacest operator lnlantuit, am rerurnat 0 refeninja la rezultat (return * this;).Functia modifica obiectul curent, din acest motiv nu apare specificatorul canst dupaantetul functiei.

Observatie

in cazul operatoruiui +, tipul rezultatului este un obiect. Returnarea unei copii aobicctului rezultat este obligatorie, deoarece rezultarul a fast obtinut intr-o variabilalocala, care s-ar f distrus la iesirea din functie. In cazul operatoruiui +=, tipulrezultatului este 0 referinja la un obiecr. Nu a fost necesara copierea obiectului.dcoarece rezultatul se afla in obiectul curent, care nu este distrus Ja termiuareaexecutiei functiei, dec! a fost suficienta transmiterea ca rezultar a unei rcferinte Iaobiectul curent (mai eficient).

este ilegala $i va genera 0 eroare la compilare. Irnplementand operatorul + ca functiemembra, el nu mai este cornutativ, primul sau operand fiind obligatoriu un obiect.Din acest motiv, este reccmandabil ca operatorul + sa fie irnplementai ca functie prietena,

• Definirea operarorului de atribuire compus += :

const rnesaj& mesaj: :operator+=(const mesaj& m){mesaj temp;int i;temp.lg=lg+m ..lg;temp.sir=new char [temp.lgJifor (i=O; i<lg; i++) temp.sir[i]=sir[i];for (i=O; i<m:lg; i++) temp.sir[i+lg]=m.sir[i];*this=temp;return * thi s ;

)

Dupa executia acestor instructiuni, pe ecran se va afisa : Ana ~re mereCa ape I de functie , operatorul poate f ytilizat (ell acelasi efect) si astfel :

mO=rnl. operator + (rn2) i

Operatorul + poate f utilizat ~i astfel :

mesaj rnO, ml ("Ana");mO=ml +" are mere" i

mO.Scrie() ;

La 0 astfeJ de utilizare, se rcalizeaza 0 conversie impliclta. Sirul de caractere"are mere" este convertit intr-un obiecr temporal', prin apelarea automata a construe­torului corespunzator. Dar - atentie ! - aceasta conversie este posibila deoarece exisraun constructor care creeaza un obiect de tip mesaj pe baza unui sir de caractere. Practic,constructia ml+"are mere" este echivalenta ell ml+mesaj ("are mere").

[nsa 0 utilizare de forma:

mO=" are rner-e vs-mrr :

~

~

~

r-r­,

,

Page 22: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

42 PROGRAMAREA TN LIMBATUL CIC ++ PENTRLJ L1CEU PROGRAMAREA ORJENTATA PE OBIECTE iN C+-r

"

IinumaratorIinumitor

Ilconstructorul claseiOperarorii arirmetici irnplementeaza operatiile cu fractii binecunoscute de la

matematica :

Operatorul - unar returneaza a fractie ell semnul algebric schimbat.Atentie ! Obieetul transmis ca parametru nu trebuie sa se modifice l Prin urmare

utilizilm un obiect de tip fractie temporar in care construim fractia cu semn -....J

schlmbat ~i returnam acest obiect ca rezultat. Rezulrarul functiei este de tip fractiesi nu fractie & (refcrinta), deoarece este necesara copierea obiectului ternporarcare conune rezultatul (la terminarea executiei funcpei obiecrul temporar este distrussi transmiterea unei referinte catre acesta nu ar avea -sens).

fractie operator-(const fractie & f)(

fractie temp(-f.a,f.b) j

return temp;}

c...

fractie &);

canst fractie &)

Definijiile operatorilor supraincdrcati

friend bool operator«const fractie &, const fractie &);friend bool operator>(const fractie &, canst fractie &);friend bool operator<=(canst fractie &, canst fractie &)friend boo1 operator>=(const fractie &, canst fractie &)

Iloperatorii de citire si scrierefriend istream & operator»(istream &,friend ostream & operator«(ostream &,

Iloperatori supraincarcati ca functii membrefractie& operator++(); Ilforma prefixata

II fractie ope r-a t o r-e--i-(int fictiv); I I forma postfixatafractie& operator--(); Ilforma prefixatafractie operator--(int fictiv}; II forma postfixa~a

operator double(} const; /Iconversie explicita Ia double} ;

class fractie{private:

int a;int b;

public:int GetNumarator() { return a;int GetNumitor() {return b·void SetNumitor(int);void SetNumarator(int)jvoid Simplifica()jfractie(int x~O, int y=lJ

Exemplul2. Supraincarcarea operatorilor pentru clasa fractie

Pentru a exemplifica supraincarcarea operatorilor ca funcjii friend vom reluaclasa fractie, adaugand declaranl friend pentru urmarorli operator! :• operatorul >- unar (schimba semnul algebric a] Iractiei)• operatori aritmetici (+, -, *, /)

• operatori de atrfbuire compusl ell operatorii aritrnetici (+=, -= -;;= 1=)

• operator! de egalitate (==, ! =)• operator! relationali «, >, -ce , >=)

• operarorul de citire »

• operatorul de afisare <

De asernenea, vom supraincarca drept funcjil membre ale clasei operarcrii deincrementare/decrementare, in forma prefixata §i in forma postfixata (++, ---),precum §i operatorul de conversie explicita din fractie ill numar real de tip double.

Nu vom supraincarca operarorul de atribuire =, intrucat acesta va fi automatsupraincarcat (realizandu-se copierea membru eu membru, ceea ce este suficient inacest caz).

Declararea clasei fractie

canst f.r a c t Le &) j

fractie &,) jconst

canstcanstcanstcanst

~

al a2 al . b2 + bl . a2- + - = --_,:-,:-bl b2 bl·a2al a2 al . b2 - bl . a2---=bJ b2 bJ ·a2al a2 aLaZ_._=--bJ b2 bl· b2aJ a2 aJ . b2bl : b2 = bl . a2

Toti cei patru operatori primesc drept paramctri doua obiecte de tip f .ra c t i Eo:

(care nu se modifica, de aceea este utilizat specificaiorul canst), calculeaza irnr-o varia­biHi tcrnporara rez rezultarul operatiei , shnpl iflca fractia rczulrara si returneaza rez

&)&)&)&) ;

&) ;

&) ;

&) ;

&) ;

fractiefractiefractiefractie

fract efract efract efract e

constcanstcanstcanst

Iloperatori aritrneticifriend fractie operator-(const (ractie &)friend fractie operator+(const fractie &,

friend fractie operator-(const fractie &,friend fractie operator*(canst fractie &,friend fractie operator/(const fractie &,

Iloperatorii de atribuire compusifriend fractie& operator+=(fractie &,friend fractie& operator-~(fractie&,friend fractie& operator*=(fractie &,friend fractie& operator/=(fracLie &,

Iloperatorii de egalitatefriend bool operator==(canst fractie &,

friend boo1 operator!=(canst rractfe &,

Iloperatorii relationali

Page 23: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

~

44 PROGRAM AREA IN LlMBi\JUL etc ++ PENTRU LlCEU ~,,~~~. ~,. ~EA ORlENTATA. PE OBIECTE iN C+-j

r-'

ca rczultat aJ functiei . Justificarea faptului ca operator» aritmetici returncaza un obiectca rezultat, nu 0 referlrita la acesta, este aceeasi ca in cazul operatorului unar -.

fractie operator+(const fractie &f1, canst iractie &[2){fractie rez;rez.a=fl.a*f2.b+fl.b*f2.airez.b=fl.b*f2.b;rez. Simplifica ()return rez;

iraetie operator-(const fractie & f1, const fractie & £2){fractie 'r-ez :rez.a=fl.a*f2.b-fl.b*f2.a;rez.b=fl.b*f2.b;rez. Simplifica ()return rez;

fractie operator*(const fractie & fl, const fractie & f2){fractie rez;rez.a=fl.a*f2.a;rez.b=fl.b*f2.b;rez. Simplifica ()return rez;

fractie operator/(const fractie & fl, canst fractie & £2){fractie reZi

rez.a=fl.a*f2.birez.b=fl.b*f2.a;rez. Simplifica ()return r-ez :

Operatorii de atribuire compusi eu operatori aritmctici sunt similari operarortloraritmetici, numai ca in acesr caz rezultatul se obtine in prirnul parametru (acosta numai are specificatorul ccns t. deoarece se modifica). Rezultatul returnat este 0 i

referinta la primul paramerru, pentru a putca utiliza operatorii de atribuire lnlantuit.

fractie& operator+=(fractie &f1, const fractie &f2){fl.a=f1.a*f2.b+fl.b*f2.a;fl.b=fl.b*f2.b;fl. Simplifica ()return £1;

fractie& operator-~(fractie&f2, const fractie &£2)(fl.a~£1.a+f2.b-fl.b*£2.a;

f1.b:::-fl.b*f2.b;

fl. Simplifica ()return £1;

fractie& operator*=(fractie & fl, const fractie & f2}{f1.a=f1.a*f2.a;fl. bv f L. b*f2 . b;fl. Simplifica ()return fl;

fractie& operator/=(fractie & fl, const fractie & £2){f1.a=f1.a*f2.b;fl.b=fl.b*f2. a;

fl.Simplifica();return fl;

Operatorii de egalitate si operatorii relationali primesc ca parametri referinte ladoua obiccte de tip fractie (care nu se modifica, din acest motiv am utilizatspecificatorul const) §i rerurneaza un rezultat logic (true daca relatia esteindeplinita si false In caz contrar). Observati ca in implementarea operatorilor > ~i

'>= am utilizat operarorul deja definit <, tar pentru a implemema operatorul <= amutilizat operatorul deja definit >.

bool operator==(const fractie & fl, const fractie & £2){ return fl.a*f2.b-fl.b*f2.a==O; }

bool operator!=(const fractie & f+, const fractie & f2){ return fl.a*f2.b-f1.b*f2.a; }

bool operator«const fractie &f1, canst fractie &,£2){ return fl.a*f2.b<f1.b*f2.a; }

bool operator> (const fractie & fl, const fractie & £2){ return £2<fl; }

bool operator<= (const" fractie & £1, canst fractie &f2){ return! (f1>£2); }

boo1 operator>=(const fractie &£1, const fractie &f2){ return! (£1<£2); }

Operatorul de cmre » poate fi supraincarcat pentru a chi nuruaratorul §inumitorul unei fractii. Acest operator are intotdeauna doi parametri: 0 rcfermta laun obiect de tip istream (fiuxul de intrare) ~i 0 referinta Ia obiectul care va f citit.Ambii parametri sc modifica in urma citirii. Rezultatu] este de tip a s t.z-eams,(referinta la fluxul de intrare), pentru a putea utiliza inlantuit acest operator.

Page 24: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

r,46 PROGRAMAREA iN ·LIMBAJUL CIC++ PENTRU LICEU PROGRAMAREA ORIENTATA PE OBIECTE iN C+-1 47

out«f.a«'/'«f.b;return out;

)

Operatorul de incrementare in forma prefixata va marl ell 1 valoarea fractiei dinobiectul curent §i va returna 0 rcferinja la obiecrul curent, care retine fractiaincrementata :

fractie& fractie::operator++{) Ilforma prefixata(

a+=bjreturn *this;

Operatorul de scrtcre « va fl supraincarcat in mod similar, pentru a afisa fractiaintr-un mod convenabiI. Acesr operator are tntordeauua doi parametri : referinracarre fluxul de lesire (ostream&) si referinta 1a obiectul care se afiseaza (acesta nuse modifica). Rezultatul este de tip ostream& (se rerurncaza fluxul de iesire), pentrua putea utiliza inlantuit acest operator.

ostream & operator«(ostream &out, const fractie '&f)(

Pentru a exemplifica modul de funcjionare a operatorului + + in forma prefixata,sa analizam urmatorul exempJu :

1, fractie fO, f1(3,4)j

£0=++f1;: c ou t c-c f O.<«" "«£1;

Se mareste mai intai eu 1 valoarea fractiei memorate in obiectul £1 (3 14), apoiaceasta valoare se atribuie variabilei f 0, Ca urmare, pe ecran se va afisa : 7 I 4 7 14

Operatorul de incrememare in forma pcsrfixata rrebuie sa adune 1 ia fracjia dinobiectul curenr, dar trebuie sa returneze ca rezultat fractia dinainte de modificare.Prill urmare, este necesara 0 variabila locala temp in care se retine fractia curentainainte de modificarc. se incrementeaza fractia curenta, apoi se rerurneaza ea rezultatfractia memcrata in temp. Pentru a face distincjia intre .forma prefixata &i formaposrfixata. in forma postfixata se transmite un parametru suplimentar de tip int(f ic t Lv), care nu esre utilizat. ~

, ,~

! ,

! :

~

-'

w

~

Pe ecran se va afisa : 3 14"" 0 . 7 5

fractie fractie: :operator++(int fictiv) II forma postfixata(fractie temp(a,b)++ (*this);return tempi"

)

Sa exemplificam modul de fuucponare a acesrui operator:

fract.ie fO, f1(3,4)fO=£l++jcout«fO«" "<x f L j

Pe ecran se va afisa 3/4 '714 deoarece £1 este incrementat, dar lui fa i searribuie valoarea dinaintea incrcmentarn.

in mod similar se implementeaza operatorul de decrementare in forma postfixata :

fractie fractie: :operator--(int fictivl II forma postfixata{fractie temp{a,bl--(*this)jreturn tempi

Observati di la implementare am utilizat operatorul ++, respectiv -- in formaprefixata, deja definit.

Analizand comparativ cele doua implementart (pentru forma prefixata ~i pentrucea postfixata), deducem ca forma preflxata este mai eficicnta. Prin urrnare , atuncicand putem utilize oricare dintre cele doua forme, este convenabiJ sa alegem formaprefixara. Aceasta observatie este general valabila.

Am. vazut in exemplul precedent (clasa mesaj) ca se rcalizeaza conversllimplicite de Ia un tip predefinit aJ Iirnbajulu i catre un obiect, utilizandu-seconstructorii definiti ai cJasei. Pentru a realiza tnsa conversii "de la un obiect al claseicatre un rip predefinit a1 limbajului trebuie sa supraincarcilm operatori de convcrsiccxplicita (cast). Operatorii de conversie explicita au 0 scrie de particularitati :

- au ca nume un tip;- nu au tip rezultat (acesta fiind implicit acel asi eli numele operatorului) ~

- nu au pararnetri ; ~

trebuie sa fie functii membre ale clasei.

Vom implementa ea functie membra un operator de eonversie explicua, carerransforma U11 object de tip fractie I11tr-u11 numar real de tip double:

fractie: :operato~ doublet) const{ return (double) al bj )

Un exemplu de utilizarc a acestui operator:

fractie £1(3,4) icout«f1«"="«(double)f1i·

in forma

istream & operator»{isr:ream & in, fractie & f){

.i.nc-c-f .a»f .b;return in;

)

in .mod similar se implcmenteaza si operatorul de dccremenrareprefixata :

fractie& f r-a c t Le: :·operator-- () Ilforma prefixata(

a-=bjreturn *this;

Page 25: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

4948 PROGRAMAREA iN LlMBAJUL CIC++ PENTRU LICEU

PROGRAMAREA ORJENTATA PE GaJEeTE iN C+ +

r

r

r

,.

~

r-'

r

~

r

2.18. Tratarea erorilor

La scoaja Invatam di "dateJe de intrare sum corecte", prin urrnare. nu estenecesar sa validam ca datele de intrare respecta rcstnculle problemei. Din pacate , inrealitate nu e deloe 3$3. De cxemplu, daca lucrarn la 0 aplicatietn care utilizatorultrebuie sa introduca numarul de telefon, chiar daca Ii explicati printr-un rnesaj cumtrebuie sa introduca numarul de telefon, ii oferiti chiar si un exemplu, este extrem deprobabil sa existe utilizatori care sa inrroduca numarul de telefon in cele mai variatemoduri: 0740-J23-456 sau 0740.123.456 sau 0740 123 456 sau oricum altcumva. inviata reala rrebuie sa validam datele §i sa ne asiguram ca .sunt respectate restricdilenecesare unci bune functionari a aplicatiei. Daca dorim sa citim dintr-un fisier , trebuiesa ne asiguram ca fisierul exista ; daca dorim sa citirn un numar pozitiv, trebuie sane asiguram ca utilizatorul a introdus un numar §i ca numarul este pozitiv etc.

Astfel de erori, care pot aparea in timpul executiei unui program, sunr denumitede programatori cxccptti (deoarece acestea sunt cazuri particulare, ce nu ar trebui saapara in mod normal).

a varianra posibila de tratare a erorilor ar arata astfel :

secventa de instructiuni 1;daca a aparut 0 eroare atunci trateaza eroarea 1

altfelsecventa de instructiuni 2;daca a aparut 0 eroare, trateaza eroarea 2

a astfel de abordare este posibila, dar nerecomandabila. Codul devine extrern destufos, greu de inteles, greu de intrcjinut, deoarece codul de executat este intrejesurcu codul de rratare a erorilor.

Experienja programatorilor POO recornanda 0 abordare diferira in tratareaerorflcr : codul de executat trebuie sa fie separat de codul de tratare a erorilor.

Cand se identlflca 0 eroare se "arunea" (throw) 0 valoare corespunzatoare croriirespective. "Aruncarea" unei valori pentru 0 exceptio se realizeaza astfel :

Ii throw (valoare_except;:ie) ;

Valoarea "aruneata" pentru 0 exccpjie poate fi de orice tip (numar, §ir deearaetere). De exernplu, sa seriem 0 fuuctle care citeste nurnarul de telefon a1 unuiutilizator :

int NrTelefon ( ){int 19, i;char s(100J;cout«" Introduceti numarul de telefon! "; cin»s;Lqv s t.r-Lerij s) i

if Ilg!dO)

throw("Nr invalid: trebuie sa cantina 10 cifre!");if (s[OJ !~'O')

throw{"Nr invalid: prima cifra trebuie sa fie 0");

for (i=O; i<lg; i++)

if (! Is[iJ>~'O' && s[iJ<~'9'))

thraw( "Nr invalid: trebuie sa cantina doar cifre");return atoi (s) ;

Observati ca 1a cmrea numarului de telefon identificam erorile posibile si"aruneam" 0 cxccptie pentru fiecare dintre ele. Valoarea aruncata este de fiecaredata un sir de caractere, contiuand un mesaj specific. Esre posibil ca valorile"aruneate" sa fie de tip uri diferite.

Cand se "arundi" 0 exceptie , executia programului este automat intrerupra.Pentru a evita acest lucru, trebuie sa "capturmn" erorile. in acest seop, arunci cand 0

secventa de cod este susceptibila sa genereze erori, ea va fi "incereata", adica va fiinclusa intr-un bloc try, astfel:

try{secventa de instructiuni de executat}

Acolade1e sum obligatorii inbloeul try, ehiar daca secventa consta dintr-oslngura instructiune.

Dupa bloeul try putem eaptura erorile ell ajutorul unui blocurilor catch. Dupatry trebuie sa apara un bloc .cetch pentru fieeare tip de eroare "aruncatii". Sintaxaunui bloc catch este :

catch (tip valoare){

secventa de instruct;:iune care se executa daca estecapturata 0 eroare

De exemplu, iata 0 incercare de a citi un numar de telefon, utilizand funcuaNrTelefon () prccedenta :

int nrt;try

(

nrt=NrTelefon();}

catch (canst char * s){

cout«"Eroare 1a introducerea numarului de telefon: ";cout«s«' vn ' ;

Daca secvema de instructluni de executat arunca erorl de tipuri diferite, atuncitrebuie sa exisre 0 scctiunc catch pentru fiecare tip de eroa~e. In acest eaz, toareerorile aruncateau fost de acelasi tip (sir de caractere), deci a fast ncccsara doar 0

singura sectiune ca tch pentru a captura eroarea.

Page 26: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

50 PROGRAMAREA IN LIMBAJUL C/C++ PENTRU LICEU

r!

PROGRAMAREA ORIENTATA PE OBIECTE IN C+ + 51

Dace exista mai multe sectiuni catch, atunci ele .sunt parcurse in ordine, pana seidentifidi prima sectiune pentru care tipuI parametrului corespunde ell tipul crorii"aruncate" .

De exemplu, vom face 0 functie de citire a varstei, care "arundi" erori de tipuridiferite (un sir de caractere, daca varsta nu este numerica, respectiv un numar intregreprezentand varsta, daca varsta nu este in intervalul [18, 99] ) :

int Varsta (){int V, ijchar 5[100J;cout«"Introduceti varsta! (0-99)"; cin»s;for (i=O; s j a j , i++)

if (! (s [i) >= '0' && s l L J <=' 9 ' ) )throw ("Varsta trebuie sa cantina doar c Lf r-ev )

v=atoi (5);

if (v<18 I I v>99) throw (v) ;return Vi

Putem "lncerca" Sa citim varsta astfel :

int V;

try(

v=Varsta () i

}

catch (canst char * s)(

CQut«"A aparut 0 eroare la introducerea varstei: ...couu-c-e s e I \n I ;

)catch (canst int val)(cout«"Pentru permis varsta este intre 18 $i 99 ani, nu ".cout«val«" ani \n" j

)

Observati ca s-a utilizat 0 'sectiune catch ell parametrul slr de caractere §i 0sectiune catch ell parametrul numar intreg.

Exista posibilitateade a utiliza si 0 sectiune catch implicita, aceasta se plaseazaultima si se va executa daca niciuna dintre sectiunile catch precedente nu se"potrive§te" ell eroarea "aruncata". Secjiunea catch lmplicita nu are pararnetruintre paranteze, ci puncte de suspensie: catch ( ... ) .

2.19. Aplicatie, Numere naturale mari

Datele membre

Vom proiecta 0 clasa denumita BigIn t pentru IucruI cu numere naturale mariserise in baza 10. Numarul maxim de cifre ale numarului va fi 0 constanta simbolicaLGMAX, defiuita in fisierul antet bigint. h.

Vorn reprezenta un numar mare ca un vector cifre, in care vom retine cifrelenumarului incepand ell unitatile (in acest mod, pozitia cifrei in vector va coincide eupurerea corespunzatoare a bazei). Vern retine de asemenea ~i numarul de cifre in datamembra Ig.

Functiile membre

Constructori

Vom implementa:

-: un constructor care construieste un numar mare pe baza unui numar mic (numarce poate fi memorat intr-o variabila de tip int); acest constructor va primi unparametru de tip int, parametru care are valoarea implicita 0;

- un constructor care va construi un numar mare pe baza unui numar memoratintr-un sir de caractere ;

- un constructor de copiere.

Constructorii vor initializa vectorul de cifre cuO, pentru a usura implementareaoperatorilor.

Destructor

Nu este necesar sa implementam un destructor, compilatorul va genera automatun destructor.

Operatori

Yom implementa ca functii membre operatorul de atribuire , operatorul deindexare, operatorii de incrementare si dccrementare (in forma preflxata si In formaprefixata) si operatori de conversie dintr-un numar mare intr-un numar mic (de tipint sau long long int).

Ca functi! prietene ale clasei vom irnplementa operatorii aritmetici , operatorii deatribuire compusi eu operatorii aritmetici, operatori relationali, operatori de egalitate ,opera tori de citire/scriere.

~

~!

, ,

, I

Page 27: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

52 PROGRAMAREA iN LIMBAJUL C/C ++ PENTRU LlCEU PROGRAMAREA ORIENTATA PE OBIECTE IN C+ + 53

friend bool eO(const Biglnt &);

friend Biglnt operator +(const Biglnt &, const Biglnt &)friend Biglnt& operator +=(Biglnt &, const Biglnt &) i

//operatorul de atribuireBigInt& operator = (canst Biglnt &)

friend Biglnt opera~or * (const Biglnt &, canst Biglnt &)friend Biglnt& operator ~=(BigInt &, const Biglnt ~) i

Iidetermin lungirneathrow ( "OVERFLOW" )

i=lg-1; i>=O; i--)(s[i]>='O'&&s[i]<='9')eifre[l~~i-l)=s[i]-'O';

else throw ( "INVALID NUMBER")

Iloperatori de citire/serierefriend ostream & operator «(ostream &, canst Biglnt &);friend istream & operator »(istream &, Biglnt &);

Iloperatori relationalifriend boo1 operator < (canst Biglnt &, canst Biglnt &);

friend beel operator <= (const Biglnt &, canst BigInt &)friend beol operator> (canst BigInt &, canst Biglnt &);friend boo1 operator >= (const BigInt &, canst BigInt &)

friend boo1 operator != (canst Biglnt &, canst Biglnt &)

Definitiile functiilor

} ;

Biglnt:: Biglnt{const char* s)( Ilinitializez eu 0 veetorul de eifre

memset{eifre,O, LGMAX);Lq e s t r Len rs : ;if (lg>LGMAX)if (lg)

for (int{ if

}else 19=1; Iisirul vid il transform in valoarea 0

Constructori

Constructorul care creeaza un obiect de tip Biglnt pe baza unui numar de lipint.. transmis ca parametru :

Biglnt: :Biglnt(int n){Ilinitializez eu 0 veetorul de cifrememset(eifre,O, LGMAX);Ilextrag eifrele lui n si Ie rnemorez ineepand eu unitatile19=O; do (cifrellgJ=n%lO; n/=lO; 19++;) while(n);

}

Constructorul care creeaza un obiect de tip BigInt pe baza unui numar stocatintr-un sir de caractere, transmis ca .parametru :

int) canst;//forma prefixata

fictiv}; II forma postfixataIlforma prefixata

fietiv); II forma postfixata

//vectorul de cifre/Ilungirnea numarului

//operator de indexareint operator [J (canstBiglnt& operator++(}jBiglnt operator++(intBiglnt& operator--(}iBiglnt operator--(int

friend BigInt operator -(const BJglnt &, const BigIn~ &)friend BigInt& operator -=(Biglnt &, c~nst Biglnt &);

publ.ic:I/constructoriBiglnt (int n=O);I/constructor care creeaza numarul mare dintr-un nr. intBiglnt(const char * 5) i

//constructor care cre~aza numarul mare dintr-un sirBiglnt(Biglnt&) ;I/constructorul de copiere

int GetLg{) { return 19; }

Declaratia clasei BigInt

#define LGMAX 1000class Biglnt{

private:char cifre[LGMAX]i,int 19;

~ i

r

r-e-

I ,

r

I'

~

friend Biglnt operator I (const Biglnt &, const Biglnt &)friend Biglnt& operator 1=(Biglnt &, const Biglnt &);

friend Biglnt operator %(const Biglnt &, const Biglnt &);friend Biglnt& operator %={Biglnt &, const Biglnt &};

Observati di, in cazul in care lungimea sirului este mai mare dedit numarulmaxim de cifre ale unui numar mare (LGMAX), "arundim" eroarea OVERFLOW, iardaca sirul confine alte caractcre dedit cifrele zecimale. "aruncam" eroarea INVALIDtJuMBER.

r-r- Iloperatori de egalitatefriend bool operator == (const Biglnt &, const Biglnt &)

Page 28: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

54 PROGRAMAREA IN LIMBAJUL etc ++ PENTRU LIeDU

r··1

.......................... n •• n~A ORIENTATA PE OBIECTE IN C+ + 55

Constructorul de copiere

Biglnt: :Biglnt(Biglnt& ob){int i;19=ob.lg;mernset(cifre, 0, LGr~);

for (i=O;i<lgji++) cifre[i]=ob.cifre[iJ;)

Functia e O ( )

Functia prletena eO () verifica daca numarul mare transmls ca parametru este nul:

boal eO(const Biglnt & ob){ return ob.lg==l && ob.cifre[OJ==Oi

Operatorul de atribuire

EigInt& Biglnt: : operator = (canst Biglnt & ob){int ijif (this != &ob) Iinu este autoatribuire

{Lqeob .lg;

memset (cifre, O,LGMAX) j

for (i=O; i<lg; i++) cifre(i)=ob.cifre[iJ;)

return *this;

Operatorul de indexare

int Biglnt: : operator l j (canst int paz) canst{ if (poz<O II poz>LGMAX-l) t hxcw.t -'RANGE ERROR");

return cifre[poz]; }

Observati di operatorul de indexare "arunca" 0 eroare in cazul In care indicele nuse 1l.fHi in intervalul [0, LGMAX) .

Operatorii de incremeruare/decrementare

BigInt& BigInt: :operator++() I/forma prefixal:a{int i; . .for (i=O; .i c Lq && cifreliJ=:::9; i++) cifre[i]=O;if (i ==LGMAX) throw ( "OVERFLOW" ) ;cifre[i]++;if (i===lg) 19++;

BigInt Biglnt:;operator++(int fictiv) II forma postfixata{Biglnt temp;temp == *this;++ ("-this) ;return temp;

BigInt& Biglnt: :operator--() Ilforma prefixata{int i;if (lg::::=l && cifrelO]==O) throw ("UNDERFLOW'!);for (i=O; cifre[i]==O; i++) cifre[iJ=9;cifre[i]--;if (lg>l && cifre[J.g-1]==O) 19--;

Biglnt Biglnt: :operator--(int fictiv) II forma postfixata{Biglnt temp;temp::: *this;-- (*this);return temp; )

in cazul In care numarul este nul, operatorul de decrementare "arundi" eroareaUNDERFLOW.

Operatori de egalitate

bool operator == (const Biglnt & obi, const BigInt & ob2){int i;if (obl.lg!=ob2.1g) return false;for (i=O; i<ob1.lg && ob1.cifre[iJ==ob2.cifre[i]; i++);return i==ob1.lg; )

boo1 operator != (const Biglnt & obi, const Biglnt & ob2){ return ! (obl==ob2); }

Operatori relationali

bool operator < (const BigInt &obl, const BigInt &ob2){int i;if (obl.1g < ob2.1g) return true;if (obl.1g >'ob2.1g)· return false;for (i=obl.1g-1; i>=O && obl.cifre[i]~=ob2.cifre[i];i--);

if (i==-l) return false;if (obl.cifre[i] < ob2.cifre[i] }return true;return false;

bool opera cor > (const BigInL'&obl, const Biglnt &ob2){ return ob2 <obi; }

bool operator <= (const Biglnt &ob1, const Biglnt &ob2){ return! (ob1>ob2l; )

bool operator >= (const BigInt &ob1, canst BigInt &ob2){ return! {obl<ob2l; }

....i

: !

!.J

i~

:~

Page 29: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

56 PROGRAM AREA IN LJMBAJUL C/C ++ PENTRU LICEU PROGRAMAREA ORIENTATA PE OBIECTE iN C+ + 57

}

while (ob1.1g>1 && obl.cifre[obl.1g-1]==O) ob1.1g--;return ob i .

s=obl.ci.fre[i)-ob2.cifre[i]+tiif 15<0) {5+=10; t~-l;}

e~se t=O;obl.cifre[i]=Si

Biglnt& operator-=(Biglnt &ob1, const Biglnt &ob2}{int i, t=O, s :if (ob1<ob2) throw ("UNDERFLOW") i

for (i=O; i<obl.lgi i++)(

Operatori aritmetici 11 de atribuire compusi cu operau!ri aritmetici

Toti operatorii aritmetici sunt implernentati utilizand operatorul de atribuirecampus corespunzator.

Biglnt& operator+= (Biglnt &ob1, const Biglnt &ob2){int t=O, 5, i;if lob2.1g > obl.lg) obl.lg=ob2.1g;for (i=O; i<obl.lg; i++)

{s=obl.cifre[i]+ob2.cifre[i]+tjt=s/10;obl.cifre[iJ=s%10;

}if It)

(if lobl.lg==LGMAX) throw I "OVERFLOW")obl.cifre[obl.lg++]=t;}

return obl; }Biglnt operator +(const Biglnt &ob1, canst Biglnt &ob2){Biglnt temp;temp=obl; temp+=ob2;return tempi

j"

j

h",'

"

'ii,

IIij;I'I "

I"":!1'"

IIi

I

': :'

i,::1,1:::: '

f'!

I:!-)iIi,

Biglnt operator *{const Biglnt & obl, const Biglnt & ob2)Biglnt l:.empitemp=ob1i temp*=ob2ireturn temp;

for (i=Oi i<obl.lg; i+-r)for (j=Oi j<ob2.1g; j++)

{if (i + j > =LGMAX) throw (" OVERFLOW" ) i

v[i+j]+=obl.cifre[iJ*ob2.cifre[j];}

for (t=i=O; i<LGMAXi i+-t-){s=t-rv[iJ

v[i]=s%10it.es 11 0;

if (t) throw ("OVERFLOVJ")//determin 1ungimea si copiez in obl cifre1efor (obl.1g=LGMAX; ob1.1g>1 && !v[obl.1g-1l; ob1.1g--)for (i=O; i<obl.1gi i++) obl.cifre[il=v[i]i

. return obl i

Biglnt& operator /= (Biglnt & ob1, canst Biglnt & ob2){int cat [LGMAX], i, 19cat=O, CCi

if (eO(ob2}) throw("Division by 0");i.f (ob1<ob2) { ob1=Biglnt()i return ob1i } //catul este 0i.f" (obl==ob2) { obl=Biglnt(l) i return obl; }//catul este 1Biglnt t;for (i=ob1.1g-1i t*lO+obl.cifre[~J<ob2; i--)

{ t*=10i t+=obl.cifre[iJi//calculez cifrele catului·for (i i>=Oi i--)

{t=t*lO+obl.cifre[iJ;for (CC=9i cc*ob2>t; cc--);t-=cc*ob2;~cat[1gcat++]=cCi

}

obl.1g=lgcat: i

for (i=O; Lc Lq c a t : i++) obl.cifre[iJ:=.:cat[lgcat-J.-ilireturn obl i }

const Biglnt &ob2)BigInt operator-{const BigInt &ob1,{Biglnt tempitemp=obli temp-=ob2ireturn temp;

~

c-~

-,

;--.

.~

Biglnt& operator *= (Biglnt & obI, canst Biglnt & ob2){int v [LGMAX] ;int i, j, t . S;

memset(v, 0, sizeof(int)*LGMAX};if leO (obI) II eO lob2)

{ cbl=Biglnt();return obl;} //rezu1tatul este 0

Biglnt operator /(const BigInt & obI, const BigInt & ob2){ Biglnt tempi

temp~obl; temp/=ob2;return t.empi

Biglnt& operator '1;::- (Biglnt & obI, const BigInt & ob7.)

,.~

Page 30: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

l'""'F""-­'f'I

58 PROGRAMAREA iN LlMBAJUL C/C++ PENTRU LlCEU PROGRAMAREA ORIENTATA PI: OBlECTE i'" C! -I 59

(int cat [LGMAXJ, i, Igcat=O, cc;if (eO(ob2)) throw("Division by 0");if (obl<ob2) { return obI; } Ilrestul este ob ;if (obl==ob2) ( obl=Biglnt(); return obI; }I/restul este 0Biglnt t;for (i=obl.lg-l; t*10+obl.cifre(i]<ob2; i--)

{ t*=lO; t+=obl.cifre[i]; }//calculez cifrele catuluifor (; i>=O; i--)

{t=t*10+obl.cifre[i);for (CC=9i cc*ob2>t; cc--);t-=cc*ob2;cat[lgcat++J=cc;

)

while (t.lg>l && t.cifre[t.lg-1]==O) t.lg--;obl=t;return obI; }

Problema 1. Descompunere Fibonacci

Consideram sirul lui Fibonacci: 0,1, I, 2,3,5,8,13,21,

. Dat fiind un nuruar natura] (nEN), scrieti acest nurnar sub forma de suma declemente neconsecutive din sirul Fibonacci, fiecare element putand sa apara eel mulro data, astfel incat numarul de termeni ai sumei sa fie minim.

Date de intrare

Din fisierul de intrare fib. in se citeste de pe prima linie numarul natural ri.

Acesta poate avea maximum 100 de cifre.

Date de iesire

In fisierul de iesrre fib. out se vor afisa termeni ai sirului Fibonacci, dire unulpe linie, care respectg restrictiile din cnunt.

~..~

L

Biglnt operator %(const Biglnt & obI, canst Biglnt & ob2){ Biglnt temp;

temp=obl; temp%=ob2;return temp;

Exemplu

Pentru n=20 flsierul de iesire poate contine 2 5 13.

(Olimpiada Nationala de Informatica. Constanta, 2000)

~

~

Solutie

Metoda utillzara este Greedy: la fieeare pas selecram ca terrnen In suma eel maimare numar Fibonacci .s.n, apoi scadem din n numarul selectat, Procedeul se repetacat timp n> o.

Sa demonstram ca acest algoritm genereaza 0 solujie care respects restr ictiile din.enunt. In primul rand, 'algoritmul se termina : la fiecare pas, n se micsoreaza, deoareceexista tntordeauna un numar Fibonacci Sn (macar 1), deci dupa un numar finir depasi va deveni nul.

In al doilea rand, niciodata nu vor fi selectati doi termeni consecutivi ai siruluiFibonacci. Sa presupunem prin reducere la absurd ca in sums am selectat doi termeni ....-J

consecutivi din sirul Fibonacci. Fie fib [ i +1] !?i fib [ i ] cei mai mari termeniFibonacci consecutivi selectati : S= ... +fib[i]+fib[i+l]+ ... Deoarece fib[i]+fib(i+1J=fibli+2], iar fib[i+2]>fib[i+l]>fib[i], deducem ca algo­ritmul Greedy va selccta fib [i-;-2J, nu pe fib [i+l] (deoarece acesta este cel maimare termen al sirului Fibonacci :S:n la pasul .respecriv).

Matematiciauul belgian Edouard Zeckendorf a demonstrar prin inductie ca scriereaunu! numar natural ca suma de termeni Fibonacci neconsecurivi este unica. flicfmdabstractie de ordinea termenilor (vezi Teorema lui Zeckendorf http://cn.wikipcdia.org/wiki/Zeckendorfs theorem)

Pentru a implementa algoritmul Greedy deserts, am utilizat 0 funqic·CenerayC:"Fibonacci care genercaza ton tcrmcnii Fibonacci <n §i ii memoreaza in vcctorulfib. in functia main () parcurgem vecrorul f in de la srar~it due ihcepur (astfelincar la fiecare pas sa fim pozitionatl pe cel mai marc tcrrnen Fibonacci . r-), llselccram in sums (Il afisam) -51 Il scadcm din n.

istream & operator » (istream &in, Biglnt & ob)(char s[LGMAX+IJ;in»s;ob .lg=strlen (5) ;

if (ob.lg>LGMAX) throw ("OVERFLOW");for (int i=ob.lg-~i i>=O; i--)ob.cifrelob.lg-i-1J=s[iJ_'O';

return in;

Afisam vectorul de cifre in ordinc inversa :

ostream & operator « (ostream & out, const Biglnt & ob)(

for (int i=ob.lg-1; i>=O; i--)out«(int)ob.cifre[i];

return .ou t.:

Operatorii de citirelscriere

La citire utilizgm un sir de caractere temporar, in care citim numarul , apoi reti­nem cifrele numarului in vectorul de cifre, 'in ordine inversa, transformand caracterelein cifre :

Page 31: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

void Generare_Fibonacci{);

ifstream fin(lIfib.in");of stream fout( ltfib.out"};

)

fout.close{);return 0;

Biglnt n;int nr;Biglnt fib[NRMAX);

61

pavaj.in pavaj.out5 3 132 1 3

PROGRAMAREA ORIENTATA PE OBIECTE iN C-I--t

(.campion 2006)

CerinJa

Deterrninati in care moduri se poate realiza pavarea aleii eli dalele existente.

Date de intrare

pisierul de intrare pavaj. in contine pe prima linie doua numere naturaleseparate printr-un spatiu : L n , unde L este jungimca aleii , iar n este HUmaTUl deripuri de dale. Pe eea de-a doua linie se afla n uumere naturale nenule distincteseparate prin care un spatiu d 1 d 2 •.• d», unde d, reprezmta lungimea dalelor detipul i, pentru orice i =1, n.

Date de iesire

Fisierul de iesire pavaj .out va contine 0 singura linie pe care vafi scris unsingur nurnar natural, reprczentand numarul de moduri in care se poate realizapavarea aleii cu dalele cxtstente.

Restrictii ~~i precizari

• 0 < L .::;: 700• 0 < n S; 250• 0 < d , < 1000, pentru or ice i=l, n

• d j:;t.:dj , pemru orice i.=l , n.. Rezultatul va avea maximum 300 de cifre.

Exemple

PROGRAMAREA II\' LIMBAJUL C/C++ PENTRU L1CEU

int main (){ int paz;

fin»n;Generare_Fibonacci()poz=nr-l;while (! e O (n))

{I/caut eel mai mare termen din sirul fibonacci <=nfor ( ; n<fib[pozJ; poz--);fout«fib[poz)«'\n';n-=fib [paz] ;

#include <fstream>#include "bigint.h"#define NRMAX 10000using namespace std;

Atat n , cal §i vectorul fib sunt nuruere mari. Observati cit de ctcgama, simpla §iclara devine implementarea acestui algoritm, utilizand. clasa Biglnt $i operatoriisupratncarcad de lucru cu numere mari :

60

r-t

r-:

r-r-

,..,

,..,

,.., Soltqie

Vom rezoJva problema prin metoda programarii dinalni~e.

SubproblemdSa se determine nr lx l = numarul de posibilitati de a pava 0 alee de lungime x ,

utilizand dalele existente.

Relatia de recurentiiPentru a pava a alee de lungime x incepem prin a pIasa 0 dala. Dala poate fi de

orice tip 1. (i=l, n). Dupa plasarea unei dale de tipul i, mai ramane de pavat 0 aleede lungime x- d [i] (desigur, daca xed [ i ] ) _ Relatia de recurcnta devine:

I,nr [xl <n.r [x-d [lJ ] +nr [x-d [2 l J + ... +nr [x-drnl J (da.ca x-d [1. J >=0, .i.eL. n ).nr[O]=l

Tinand cont de dimensiunea datelor de inrrare. este ncccsara utilizarea numerelorrnari.

~

i j

,..,

"

void Generare_Fibonacci()int i;fibIO]=BigInt();fib[l]=BigInt(l);for (i=l; fib(iJ<=n; i++l

fib[i+l]=fib[i]+fibli-l);nr=ii

" ]

Problema 2. Pavaj

Aleea din fata scolii are lungimea L si trebuie sa fie pavata eu dale de formadreptunghiulara, avand lanmea egala eli latimea aleii , dar de diferitc Jungirni. Extsran tipuri de dale, numerotare de la 1 la n, din fiecare tip existand UII numar suficientde marc de exernplarc.

I·.:il,incl u de, #include

<fstrearn>"bigint.h"

~,

Page 32: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

r62 PROGRAMAREA iN UMBAJUL CIC+t PE!\TRU LlCEU PROGRAM AREA ORIENTATA PEOI3IECTE iN C\ + 63

#derine NMAX 251#define LMAX 701using namespace std;ifstream fin ("pavaj. in") ;of stream tout ("pavaj. out")

Restrictii

• 0 < n :s:;- 1000• 0 < ai ~ 100000, pentru l:S:;-i~n

• Rezultatul va avea maxim 1000 de cifre.

Sa se scrie un program care sa determine eel mai mic numar ell care ar putea finmultit produsul al *a2* ... '"an astfeJ incat Sa se obtina un patrat perfect nenul.

Pisierul de intrare sqr. in contine pe prima linie nuruarul natural n. Pe cea de-adoua linie se afla nurnerele naturale al. a2' .• an> separate prin care un spatiu,

Date de iesire

Fisierul de iesfre s qr . au t va contine 0 stngura linie pe care va fi scris un numarnatural, care reprezinta numarul minim cu care ar putca fi inrnuljit produsulal *a2 * ... *an astfeJ incar sa se obpna un patrat perfect nenul.

Date de intrare

-.J

--'

L...;

'!

--'

, 1

I '

I

'-"

. * ar. pentru a

apar la puteri

(.campion 2005)

produsul al *a2 * ..factorti primi care

sqr.in sqr.out Exnlicatic3 5 12*3*5 18012 180*5=900=30*3035

Exemple

Solutie

Pentru ea un numar sa fie patrar perfect nenuI, dcscompunerea sa in factori primirrebuie sa cantina doar factori la puteri pare. Prin urmare. u-ebuie sa determinamdescornpunerea in factori primi a produsului al * a2 * ... * a l,. 0 idee ar fi sa calculamprodusul, apoi sa-l descompunern In facrori primi (ceea ce ar f cam cornplicat,descompunerea unui numar mare in factor! primi nefiind fcarte simpla).

o alta idee se obtine plecand de la obscrvatia ca daca in al apare factorul prim dla puterea PI, iar in a:>. factorul prim d apare la puterea P2, in produsul a~ *a2 fac­torul prim P apare la puterea Pl +P2. Prin urmare , este suflcienr sa descompuncmfiecare numar a , (l.-:::'i~n) 1n factori primi sl sa rennem intr-un vector p suma puterilorfactorilor primi (p l d ] = suma purerilor factorului prim d din descompunerea infactori primi a numerelor ai, l.:o;iS",n).

eel mai mic numar cu care poate -f lnmulurobtine un patrar perfect se determina lrunultindimpare. Acesta va fi, evident, un numar mare.

int nj

int a [NMAX] j

int P [DMAX] ;

Biglnt nr (1)

int main (){int i, dj//c.itirefin»nifor (i=l; Lc e n : i++) f i nc-c-e Li L:

#include <fstream>#include "bigint.h"#define NMAX 1001"define DMAX 100000using namespace stdjif'stream fin (" sqr. in") j

of stream faut Lveq.r co u t v )

an 0 secventa de n valoria, ,

Problema 3. SQR

Cerinta

int il, L;int d [NMAXj ;Biglnt nr [LMAX] ;

int main (){ int i, Xi

//citirefin»L»D;for (i=l; i<=n; i++) fin»d[i];I/programare dinamicanr[O]=Biglnt{l);for ex=].; x<=L; x++)

for (i==l; i<=n; i++)

if (d[iJ<=x) nr[x]+=nr[x-d[iJJ;//afisarefout«nr[L]«'\n'fout.close{);return 0;

Sa consideram n un Hilmar natural si aI,naturale nenule.

Page 33: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

2.20. Clasa string

//descompunerea in factori primifor (i=l; i<=n; i++)

for (d=2; a[iJ>l; d++)while (a[i]%d==O) (++p[dJ; a[iJ/=di}

//determin nrfor (d=2i d<DMAXi d++)

if (p[dJ%2) nr*=d;//afisarefout«nr«' \n' ;fout.close();return o.

Operatiile ell siruri de caractere in C necesita 0 buna cunoastere a modului dereprezentare si 0 buna injelegere a operatiilor ell pointeri. Din acest motiv, lucrul ell

siruri in C ("C-like") are un niveJ relativ inalt de dificultate. Din acest motiv, inbiblioreca standard a limbajului C+ + a fast implernentata clasa string, pentru afacilita operatiile ell siruri de caractere. Pentru a utiliza aceasta clasa, trebuie saincludeji fisierul antet string:

!: #include <string>

65PRQGRAMAREA ORIENTATA PE OBIECTE IN C+ +

Destructorul clasei string

.c s t r i nc () - elibcrcaza memoria alocata dinamic de constructor.

Operatori supraincarcati

• Operatorul de atribuire :::: este supraincarcat pentru a atribui unui ~ir de tipstring un alt sir de tip string sau un sir de caractere din C ori un caracter:

string& operator= (const string& str)string& operator:::: (const char* s);string& operator= (char c);

• Operatorul + este supraincarcat ea funcpe friend si poate fi utilizat 'pentruooncatenarea a doua siruri de tip string, a unui sir de tip string cu un sir decaractere din C, respectiv dintre un caracter si un sir de tip string:

string operator+ (const string& s t . c ons t; string& s2)string operator+ (const string& sl, const char* 52)string operator+ (const char* sl, const string& s2)string operator+ (const string& sl, char 52)string operator+ (char sl, canst 5tring& 52)

• 'Operatorul += este supraincarcat ca functie membra si functioneaza pemruconcatenarea eu un ~ir string, un sir C si, respccriv, un earacter:

PROGRAMAREA iN LIMBAJUL C/C ++ PENTIW L1CElJ64

r-'

,

Operatoru1 de indexare [] rerurneaza 0 referinta la caraeterul de pe pozitiaspecificatii poz :

char& operator[] (size_t poz);const ch~r& operator[] (size_t poz) const;

Daca poz este ega1 cu lungimea sirului, va returna 0 referinta la earaeterul nul.Daca sirul este constant, atunci referinta rcrurnata va fi constants.

Operatorii de citire/seriere sunt supraincarcati astfel incat sa functioneze ca pentrusirurile din C

(const string& s)(canst char* e j :

(char c);••

, .J

l r.n·

Constructorii clasei st:ring

string (); - creeaza un sir vid.

string (const string& s) i - consrructorul de copiere: -crceaza un siridentic' ell sirul s. .

string (const string & s, size_t poz, size_t nr = npos); _.creeaza un sir care contine nr caractere din s, Incepand de Ja pozitia po z. Daca

- nr lipseste sau este prea mare, se copiaza caraetere1e din s de la pozitia poz panala sfarsitul sirului.

string (const char* s) i - creeaza un sir pe, baza sirului de caractere din Cs (secventa de caractere terminara cu caracterul 0).

string(const char* s,size_t nl; - creeaza un sir continand primele ncaractere din sirul de earactere s.

string (size_t n , char c) i - creeaza un sir care contine caracterul crcpctar de n ori.

string& operator+=string& operator+::::string& operator+=

istream& operator»ostream& operator«

{istream& is,(ostream& o s •

string& str);const string& str)j

• Operatorii relationali si de egalitate sunt supraincarcati ca functii friend pentrua functlona atat pentru compararea slrurtlor de tip s t ring, cat §i pentrucompararea unui $ir de tip string Cll un sir din C:

bool operator:::::::: (canst string& sl, canst string& 82)boo1 operator== (canst char* sl, canst string& 52)boo1 operator:::::::: (const string& sl, canst char* 52)boo1 operator!= (const string& sl, conse string& s2)

Observaiii

size teste un tip care are ca valori nuruere naturale, capabil sa retina dimen­siunea oricarui tip de date.

2, npos este un membru static constant, care are valoarea maxima pentru tipul....., size_to Cand utilizam aceasta valoare ca lungime a unui subsir , are sCITIni1katia

! "pana la srar~itul1;:iruluj".

,! ! 1: i •

~

Page 34: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

PROGRAMAREA ORIENTATA PE OBIECTE iN C+ + 67

• Fuuctia insert () insereaza la pozitia paz in sirul curent un sir s (care poate fistring sau din C):

string& insert (size~t paz, canst string& 5)

string& insert Csize_t poz, const char* s);

Peate inscra dear 0 subsecvenja din sirul de tip string s (cea care incepe lapo z L si are 1ungimea n.r-L}:

string& insert (size_t paz, canst string& s, size_tpazl, siz€_t nrl) i

Poate insera primele n caractere din sirul din Cs :

string& insert (size_t paz, const char* s, size_t n);~

, Sau poate insera de n ori caracterul c :

string& insert (size_t paz, size_t n, char C)i

string& erase (size_t paz = 0, size_t nr = npos) ;

• Puncria erase () srerge nr caractere din sirul curent incepand de la pozitia paz.Pararnetrul paz are valoarea implicita 0, iar nr are valoarea implicita npos(stergerea se face pana la sfarsitul sirului) :

.' Functia find () cauta in sirul curent un alt sir s (de tip string sau sir din C)incepand de la pozitia poz si rerurneaza pozitia de inceput a primei aparitii (saunpos daca nu apare) :

size_t find (canst string& s, size_t poz = 0) canst;e Lz e j t; find (const char* S,. s,ize_t poz = 0) canst;

Poate de asemenea cauta doar primele n caractere din sirul din C s :

size_t find(canst char* s,size_t poz,size~t nl canst;

Sau poate cauta un caracter c :

size_t find (char c, size_t poz = 0) canst;

• Funcjia replace () inlocuieste in sirul curent 19 earactere, incepand de Iapozitla paz Cll un alt srr s (de tip string sau din C):

string& replace(size_~ paz,size_t 19,canst string& s);string& replace (size_t poz, size_t Ig, canst char* s)

sau doar cu un subsir al lui s (care tncepe la pozftia p oz L ~i are lungimea 191):

string& replace (size_t paz, size_t 19, canst string& s .size_t pozi, size_t 191);

sau eu primele n caracrere din s :

string& replace (size_t paz, size_t 19, const char* s,size_t n);

sau cu -n caractere c :

~

~

-'

~

~

i,'-"

size_t n, char Clisize_t 19,string& replace(size_t paz,

• Functia getl ine () citeste caraetere in sirul s pana 1a intalnirea caracteruluidelimitator d , respectiv pana la intalnirea marcajului de sfarsit de linie '\n'.

istream& getline (istream& in, string& s, char d) i

istream& getline (istream& in, string& s);

• Puncna swap () interschirnba valorile a doua siruri de tip string:

void swap (string& x, string& y);

Funcjii membre

Puncjtile mernbre sunt foarte numeroase, mentionarn cateva dintre acestea. Listatuturor functiilor membre poate fi consultata online in docurnentatia lirnbajului C+ +(http://www.cplusplus.com).

• Itunctiile length () si size () .rcrurneaza lungimea sirului (numarul de carac­tere din sir) :

size_t length() canst;size_t size() const;

• Punctia pop_back () sterge ultimul caracter din sirul curent :

vaid pop_back ( ) ;

• Functia empty () returneaza true daca sirul este vid ~i false in eaz contrar:

baal empty() const;

• Puncjla membra data () rerumeaza un str de caractere din C (succesiune decaractere terrninata cu caracterul nul), continand caracterele din sirul curenr :

canst char* data() canst;

• Funcjia pU~h_back() adauga caracterul c 1a sfarsitul sirului curent:

void push_back (char c) ;

Page 35: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

68 PROGRAMAREA iN LIMBAJUL CIC--H PENTRU LICEU PROGRAMAREA ORIENTATA PE OBIECTE IN C+-I- 69

i ;

r-'

"

r-«,

~

,

t i

,..,l ;

t. ;

i

'I

-

r:

• Functia substr () rerurneaza un subslr al sirului curent, care incepe la pozitiapaz ~i are 19 caractere (valoarea implicita pentru parametrul 19 este npos, ceeace tnseamna ca se considers toate caracterele de la pozitia paz pana la .sfarsituluisirului curent) :string substr Ls Lz e t paz := 0, size__ t 19 :::: rrpo s ) con s c :

Functii de conversie

• Functiile stoi (), stal (), stoll (), stolul {), stolull () convertesc unstring s care contine un numar intreg seris in baza b (valoarea implicita pentrub fiind 10) ~i returneaza numarul intreg obtinut (de tip int, long, long long,unsigned long, respectiv unsigned long long). Daca pointerul pestenenul, dupa ape] in p se va afla adresa caracterului din slr care urmeaza dupavaloarea numerica convertita. Valoarea implicita pentru parametrul peste 0, cazin care p nu esre utilizat.

int stoi (canst string& s, size~t* p=O, int b=lO);long stol (canst string& s, size_t* p=O, int b=10) ;long long stoll (canst string& s, size_t* p=O, int b=10)unsigned long stoul(const string& s,size_t* p=O,int b=10)junsigned long long stoull(const string& s,size_t* p=O,int b=lO);

• Functiile stof () , stod () si s t o Ld () convertesc un string s inrr-un numarreal si rerurneaza numarul convertit ea rezultar (de tip float, double, respectivlong double). Semnificatia parametrului p este aceeasi ea la functiile de can­versie in intreg :long double staId (canst string& s, size_t* p=O);double stad (canst string& 5, ~ize_t* p=O);float stof (canst string& s, 5ize~t* p=O);

Problema 4. Ed

Sa consideram un text format numai din Iitere mici ale alfabetului englez. Asupraacestui text se pot executa urrnatoarelc operatii de editare :

1. L (cursorul se muta eu 0 pozitie la stanga ; in cazul in care cursorul se afla Iainceputul texnilui, aceasta operatic nu are niciun efect).

2. R (cursorul se mute cu 0 pozitic la dreapta; in cazul 111 care cursorul se afla lasfarsitul textului, aceasta operajie nu are niciun efect).

3. B (sterge caracterul din stanga cursorului; in cazul in care cursorul se afla lainceputul textului, aceasta operatic nu are niciun efect).

4. I<secventa> (insereaza secventa de litere mici specificata dupa litera I inpozitia curenra a cursorului).

5. D<rrr->' (sterge lncepand eli poz.itia curcnra a cursorului nr earactere; in cazulin care numarul de caractere existente din pozitia curenta a cursorului pana lasfarsitul sirului esre < nr, se vor sterge toate caracterele exisrente de Ia pozitiacurcnta a cursoruJui pana la sfarsitul sirului).

Initial, cursoru1 de scrierc se ami la sfarsirul tcxtului (dupa ultimul caracrer).

Cerinta

Scrieti un program care sa aplice unui text dat 0 secventa de operatii de editare sicare sa afiseze textul astfel obtinut.

Date de intrare

Fisierul de intrare ed . in coniine pe prima linie textul dar. Pe cea de-a doualinie cste scrls un nurnar natural N, care rcprczinra numaru l de operatii de editare. Peurmiitoarele N 1inii sunt scrise cele N operatii de edirare (cate 0 operatic pe 0 linie),in ordinea in care trebuie sa. fie executate.

Date de iesire

Fisierul de iesire -ed. au t va contine 0 singura linie pe care va fi scris textulobtinut dupa executarea in ordine a celor N operatii de editare.

Restrictii si precizari

• Textul dar este format din eel mult 50000 litere mid ale alfabetului englez.• 1 ~ N ~ 5000• La oriee operatic de inserare (I) se pot insera in text maximum 10 caractere ,'. La orice operatic de stergere (D) se pot sterge din text maximum 1000 caractere.

Exemplu

ed. in ed.autgwerty qwarbb10L

LD3L

""RIbbLIaaaD2

(.campion 2006)

Soliqie

Solutia devine imediara, utilizand clasa string. Cirim succesiv operatiile siexecutarn fiecare operatie citita, in functie de tipul ei :

#include <fstream>#include <string>#include <cstdlib>

using namespace std;ifstream fin("ed.in")

Page 36: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

70 PROGRAMAREA IN LIMBAJUL CIC++ PENTRU LICEU

T,,PROGRAMAREA ORIENTATA. PE OBIECTE iN C+ + 71

i

L

case 'L'

case 'R'case 'B'

case 'I'case 'D'

of stream fout (" ed. out" ) ;

string S, 0Pi

int paz i

int main ( ){int it N, 19;

fin»s;po a e s . length () ;fin»N;for (i=O; i<N; i++)

(

fin»op;switch (op[O])

{if (poz>O) poz--; break;}{if (poz-c s . length () ) poz++; break;}{if (poz>O) {s.erase(poz-l,l); poz--;break;

{s.insert{poz,op,l,string: :npos); break;}(lg=atoi(op.data()+l) i

/Ilg=stoi(op.substr(l);s.erase(po2,lg); poz-lg; break;

)

fout«s« ' \n' ;fout.close(} ;return 0;

)

Singura operatic mai diflcila estc stergerea, deoarece a fost necesara conversiaunui subsir al sirului op (in care este memorata opcrana curenta) intr-un numarlntfeg (lg). Exfsta doua variante pentru a realiza acest lucru (ell functia e t o i () ,care penrru compilatoare mai vechi nu functioneaza, fiind inrrodusa in bibliotecaIirnbajului in anu1 2011) sau transformand cu ajutorul functiei data () subsirulextras in sir de caractere din C, apoi realizand conversia eli functia atoi ().

2.21. Mostenirea

Mostenirea reprezinta unul dintre principiile fundamenta1e ale POQ si, in esenja,consta in posibilitatea ca dintr-un concept general sa obtinem un concept particular(sau mai specializat).

Procesul .prin care se realizeaza mostenirea se numeste derivare. Prin derivare, clasaderivata mosteneste toate datele si functiile membre ale unci alte clase (denumitaclasa de baza). Clasa derfvata se difcrenuaza fara de clasa de baza prin adaugarea unormembri (date sau functii) sau prin supratncarcarea functiilor membre ale clasei de baza.

Util izand derivarea claselor, dezvolrarea aplicatiilor devine mai eficienta. Aplicatiilenu sunt de fiecare data tnccpute de 1a zero. 0 parte din cod este deja sensa ~i va fil1lo~tenita. Codul mostenit este deja testat, deci exista 0 garantie 3, corectitudiniiacestuia.

o clasa poate f clasa de baza pcmrumai multe clase derivate, iar 0 clasa derivatepoate fi clasa de baza pentru alte clase, obtinandu-se astfel ierarhii de clase. In uncledintre limbajele de programare onentara pe obiecte, orice clasa este 0 class derivatadintr-o alta clasa de baza. gcnerala, definita in cadrul limbajului (de exemplu, in Javasau in C#, aceasta clasa este denumita Obj ec t ). Limbajul C+ + fiind un limbajhibrid, permite, asa cum am vazut deja, definirea unei clase tara derivarea acesteiadintr-o alta clasa.

Derivarea unei clase dintr-o ctasa de baza

Sintaxa declararii unei clase derivate (denumita ClasaD) dintr-o clasa de baza(denurnita ClasaB) este :

class ClasaD: specificator_acces ClasaB{

Iideclara\ii de date mernbreIideclaratii de functii membre

} ;

In declarada clasei derivate, specificator__acces poate fi public,protected sau private. Daca nu este mentionat specificatorul de acces, el esteconsider-at implicit private. Uzual, programatorii C+ + utilizeaza la derivarea cla­selor spccificatorul public.

Reamintim ca membrii private ai unei clase pot fi accesati doar' in ·cIa-sarespectiva §i in functiile prietene ale clasei respective; membrii p.ro t.ec t e.d pot fiaccesan in plus §i in clasele derivate si in functiile prierene ale claselor derivate.

Efectul specificatorilor de acces asupra membrilor clasei de baza este sintetizar in .tabelul urrnator. Yeti observa ca. in c1asa derivata, aceesu1 este mai resrrlctiv dccatin clasa de baza, in functie de specificatorul de "acces utilizat 1a derivare.

Atribut in clasaB Speciflcator acces ~cces in clasaD Acccs in exteriorpublic private inacccsibiJprivate p'r i.ve-t e inaccesibtl inaccesibilprotected private inaccesibilpublic protected inaccesibiJprivate protected inaccesibil inaccesibilprotected protected inacccsibtlpublic public accesibilprivate public inaccesibil inaccesibilprotected . protected inacccsibil

-.J

~

l......j

~1,

~

w

'--'

'--'

, 1

-J

-J

-.J

Page 37: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

72 PROGRAMAREA IN LIMBAJUL CIC++ PENTRU LIeEU PROGRAMAREA ORIENTATA PE OBlECTE iN C+ + 73

r-'

n

r-'

n

~- j

i !I I

r

",.,:

I",

"

r

~

Exemplu

Sa construim, intr-o forma extrem de -simplificata, 0 class pentru evidentaresurselor umane la 0 companie. Grice persoana, indiferent ca este client sau angajat,trebuie sa aiba un ·nurne §i un cod unie de identificare in cadrul companiei ,. Vom construi, in prima instanja, clasa Persoana astfel :

class Persoanapublic:

static int IdCrt;protected:

int Id;string Nume;

public:Ilconstructori:Persoana();Persoana{const string& 5)Iidestructor-Persoana () ;I/functii de accesint Getld () ;string GetNume();void SetNume(const string&)void Scrie();

} ;

Numerele de identificare ale persoaneJor sunt generate automat, cu ajutoruI datcimembre statice IdCrt. Valoarea acesteia va fi incrememata de fiecare data la creareaunei persoane (in functiile constructor). Am declarat doi constructori (unul taraparametri, care seteaza doar Id-ul, ~i unul cu un pararnetru de tip string, carescteaza si numele). in ambii constructori ~i In destructor aflsam dire unmesaj, pentrua putea urmarl modul in care se creeaza, respectiv se elimina oblectc.

Implernentarea functiilor mernbre este :

Persoana::Persoana(){ Id=++IdCrt; Nume="";eout«"Am creat 0 persoana fara nume\n";Persoana: : Persoana(const string& s){ Id=++IdCrt; Nume=s;

eout«"Am creat 0 persoana eu nume\n";

IidestructorPersoana: ;-Persoana(){ eout«"Arn elirninat 0 persoana\n";Ilfunctii de aeeesint Pe.r s.oana . . ccc r c () { return Id;string Persoana: :GetNurne() { return Nurne; }void Persoana: :SetNume (const string& s) { Nume=s; }void Persoana: : Serie () { c ou t c c j d-c I "<cNume c ' \n'; }

Observati ca in c1asa Persoana am declarat datele membre utilizand specifica­rorul de acces protected. In acest mod avem acces direct la datele membre dinclasele derivate. Aces! lucru nu era obllgatoriu. Am fi putut declara dateJe membreprivate si sa Ie accesam prin intermediul funcrlilor publice de acces,

Din clasa Persoana vorn deriva clasa Angajat, care are in plus un salariu §i 0tunctie (date membre) si functii de acces Ia salariu §i la functie.

c1ass Angajat : public Persoana(protected:

string Functie;int Salariu;

public:int GetSalariu();void SetSalariu(int);string GetFunctie();void SetFunctie(string)void Scrie ( ) ;

} ;

Definitiile functiilor membre fiind :

int Angajat::GetSalariu() { return Salariu; }void Angajat: : SetSalariu(int x) { Salariu=x; }string Angajat::GetFunctie() { return Functie;void Angajat: : SetFunctie (string s) { Functie = s'void Angajat: :Scrie(){ c ou t c c Ld-c I I «Nurne« I I -e er'unc t t e-c I I «Salariu« I \n ';

Unnatoarea secventa de cod genereaza doua obiecte de tip Persoana (x, utili­zand constructorul implicit, si y, utilizand constructorul eu un parametru) si unobiect de tip Angajat (z). Deocamdata in clasa Angajat nu exists un constructordefinit, prin urmare, se apeleaza doar Ja constructorul implicit at clasei Persoana.

Persoana x , y( "Popescu ves i Le»)x. SetNurne t " Ionescu Dan");x.Scrie() ;y.Scrie() ;Angajat z;z.SetNurne("Vasilescu Ana") j z.SetFunctie(lt c ontabil")z.SetSalariu(lOOO) ;z.Scrie() ;

Dupa executia acestei secvente, pe ecran se va afisa :

Am creat 0 persoana fara numeAm creat 0 persoana eu nurne1 Ionescu Dan2 Popescu VasileAm creat '0 persoana Lara nume3 Vasilescu Ana eontabil 1000

Page 38: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

r-!

74 PROGRAMAREA iN LTMBAJUL C/C ++ PENTRU LTeEU

Am eliminat 0 perSoanaAm eliminat 0 persoanaAm eliminat 0 persoana

I/destructor-Angajat () ;) ;

PROGRAMAREA ORIENTATA. PE QBJECTE IN c++ 75I ', '

Definirea unui constructor in clasa derivata este obligatorie daca 111 clasa de bazanu exists un constructor tara pararnctri.

Pentru exemplifieare, vom cornpleta clasa Angaj at cu trei constructori :

unul tara parametri, care se bazeaza pe constructorul tara parametri al clasei debaza si construiesrc un angajat tara nume, functie sau salariu ;unul eu doi parametri, care se bazeaza pe constructorul tara parametri al clasei debazf §:i construtestc un angajat fiira nume, dar cu functie ~i salariu ;unul ell rrei pararnetri (numele angajatului, functia ~i salariul) care se bazeaza peconstructorul cu un paramctru al clasei de baza (numele angajarului fiind transrnisacestuia).

ReguliJe de functionare a constructortlor/destructorului raman valabile ~i in claselederivate. Torusi exists 0 serfc de elemente specifice, care ilustreaza relatia dintreconstructorii/destructorul clasei de baza ~i constructorii/destructorul clasei derivate:

• pentru construirea unui obiect al clasei derivate se apeleaza mai lntai construe­torul clasei de baza, apoi se apeleaza constructorul clasei derivate;

• la eliminarea unui obiect a] unei clase derivate se apeleaza mai Intai destructorulcJasei derivate, apoi destructorul clasei de baza.

Cand declararn un constructor in clasa derivata tr-ebuie sa spccificam in lista deparametri mai intai parametrii pentru consrructorul corespunzator din clasa de baza,iar in continuare eei pentru construetorul c1asei derivate.

Cand definim constructorul elasei derivate trebuie sa specifidim §:i eonstructoruJclasei de oaza eu cei corcspunzatori, astfel :

~

u

,

-J

,

.'-.J

--'

, i:

sal) :intcanstAngajat::Angajat(const string& sf,Persoana (){Functie=sfi Salariu=salicout«"Arn creat un angajat fara nume,cout«"cu functie si salariu\n";

Definitiile pentru constructor! ~i destructor sunt :

Angajat: :Angajat (canst string& sn, const string& sf, canstint sal): Persoana(sn){Furlctie=sfi Salariu=salicout«"Arn creat un angajat cu n ume . functie si salariu\n";

Angaj at: :Angaja.t () : Persoana (){cout«"Arn creat un angajat fara functie si salariu\n" i

I/destructorAngajat::-Angajat(){ cout«"Affi eliminat un angajat\n"j

Observati ca atat constructorii, cat si destructorul afiseaza pe ecran mesajespecifice, astfel Incat la executie sa putem identifica exact ce se executa.

Pentru exemplificarc yom erea ~i vom afisa trei obiecre de tip Angajat (cateunul pentru fiecare constructor definit) si apoi le vom afisa.

La declararea unui obiect a1 clasei derivate trebuie precizata mai Inrai listaparametrilor actuali pentru constructorul clasei de baza, apoi pentru constructorulclasei derivate.

Anca j a t; Xi

x.setNume('''vas·ilescu Ana") i x.SetFunctie("contabil")x.SetSalariu(1000);x.Scrie(} iAnq'a j a t; y ("director", 2000);y. SetNume ("Vasilescu Ana") i

y.Scrie{) ;Angajat z t v Pope. Ion","casier",500)z.Scrie() i

Urmarind mesajelc afisate pe eeran la executia acestei secventc de instructiuni ,deducem ca' se apcleaza mai intiii constructorul clasei de baza, apoi ccnstructorulclasei derivate. in cazul destructorilor este invers (se apeleaza mai intai destructorulclasei derivate, apoi destructorul clasei de baza).

Am creat 0 persoana fara DumeAm creat un angaja~ fara functie si salariu1 Vasilescu Ana contabil 1000

tipdl pd1 ,c l a s an t t Lp, pb1 , tip2 pb2 , •.• , tiPh pbh,tipdk pd,:> : clasaB (pb1,pb2 , •••pbh )

Constructorii si destructorul in clasa derivata

clasaDtiPd2 pd2 ,

class Angajat : public per-ss o arra{protected~

string FUDctieiint Se.Laz a u :

public:int GetSalariu ()void SetSalariu{int)string GetFunctie();void SetFunctie{string);void Scrie() i

//constructoriAngaj03t() ;Angajat (const string& sf, const int sal);Angajat(canst string& SD, canst string& sf, const int sal)

Page 39: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

7(> PROGRAMAREA iN LIMBAJUL CIC+-j- PENTRU L1CELJ

<r" PROGRAMAREA ORIENTATA PE OBIECTE iN C+ + 77

2.23. PolimorfismuI

Pentru a evita ca un fisier antet sa fie inclus de mai multe ori Intr-o aplicatie , vominclude conditionat continutul acesruia, utilizand directiva preprocesor it i fndef .

#ifndef NUMECLASA H#define NUMECLASA H." //continutul fisierului antet numeclasa.h

#endif

Polimorfismul reprezinta un alt principiu fundamental al programarii orientate peobiecte. Cuvantul polimotfism descrie posibilitatea de a avea mai multe forme. in viata

. reala, polimorfismul este extrem de uzual. De exemplu, daca as spunc "Deschide ! ".aceasta "functie"va fi executata in mod diferit daca este yorba de a deschide usa saua deschide ochii ori a deschide un fisier etc.

in c+ +, ideea este similara : apelul unci functii rnerubre va avca un efect diferuin functie de obiectul care invoca functia (functia apelara este selectata in functie de

tipulobiectului).in exemplul prezentat la sectiunca "Mo~tenire" am intalnit deja polimorfismul .

Atat in clasa de baza Persoana, cat §i in clasa Angaj at a fast definita functiascrd e () . in clasa Persoana, functia afisa doar Id §i rcurne, iar in clasa Angaj atafisa in plus Functie $i Salariu.De exemplu, sa 'analizam apelurile functiilor

scrie () din secventa urmatoare de cod:

Persoana x ("Vasileseu Ana") ;Angajat y( "Po'pa Ion", "casier", 500);x.Scrie(} ;y.Scrie() ;

Pe ecran se va afisa :

:~-

tip Persoana,

1 Vasilescu Ana2 popa Ion easier 500

deoarece primul ape! a1 functiei Scrie () este pentru obicctul x deal doilea este penrru obiectul y de tip Angajat.

Am creat 0 persoana fara numeAm creat un angajat fara nume eu functie si salariu2 Vasilescu Ana director 2000Am creat a persoana eu DumeAm creat un angajat eli DUffie, functie si salariu3 Papa Ion easier 500ffin eliminat un angajatAm eliminat a persoanaAm elirninat un angajatAm eliminat 0 persoanaAm eliminat un angajatAm elirninat 0 persoana

Conversiile implicite de tip

Cornpilatorul C+ + admite urrnatoarele conversii implicite de tip:

dintr-un obiect a1 clasei derivate Intr-un obiect al clasei de baza ;dintr-un .pointer (sau rcferima) catre un obiect al clasei derivate catre un pointer(sa_u referlnjaj.catre un obiectal clasei de baza.

Nu sunt perrnise conversiile inverse!

Mostenirea multipla

In c+ + este permisa mostcnirea multipla (0 clasa poare fi derivata din mai multeclase de baza). In acesta caz, la declararea clasei derivate nu se specifica 0 singuraclasa de baza, ci 0 succesiune de clase de baza. separate prin vir gula , fiecare clasa de ,baza fiind precedata de propriul specificator de acces. Toate regulile mentionate .11

pentru mostcnlrea shnpla raman valabile. 'Exisra multi programatori care considera mostenirea multiple inutila (deoarece

aceleasi rezultate ar putea fi obtinute si cu mostenire simplil), ba chiar un indiciu caierarhia de clase nu este corect proiectata. Din Iimbajul Java, mosrenirea multipla afast in mod deliberat eliruinata.

':

': j

~

,

r-'

; :

,-

2.22. IncIuderea conditionata

Cand clasaD este derivate din clasaB trebuie sa includem fisierul antet ell

declaratia clasei de baza (clasaB. h) in flsierut anret al clasei derivate. Aces! lucrupoate crea problemc, in sensuJ ca Iurr-o aplicatie este posibil ca declaratia unci clasesa fie inclusa de mal multe ori, ceca ce ar genera croare Ia compilarc.

Pentru a evita astfel de shuam, la inccputuj flsierutui antet, pentru orice clasa,Yom dcfini 0 constanta simboJidi semnificatiYa, cu ajutoruJ dircctivei preprocesor#define:

I #define NUMECLASA~H

Sa analizam acum urmarorul exemplu :

Angajat y t vPopa Ion", "casier",SOO)Persoana &r=y;r.Scrie() ;Persoana *p;p=&y;p->Scrie () ;

Aceasta secventa de cod va afi~a pe ecran :

2 Papa Ion2 Papa Ion

,....,

Page 40: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

I,

class Persoana{ public:

Ooservaji ca am declarat 0 referinta r (catre un obiect de tip Persoana) ~i unpointer p de asemenea carre un obiecr de tip Per s o arra: Atat z-, cat si p primescadresa obiectului y de tip Angajat. Ambele apeluri ale functiei Scrie () (deci ~i functiaapelata pi-in interrnediul referinjci r, §i eea apelata prin interrnediul pointerului p)produc acelasi efect: se apcleaza funcpa Scrie () din clasa de baza Persoana.

Aces! ruecanism este denumit reeoluiie statici (static resolution = static linkage= early binding): compilatorul selecteaza funcna inainte de execuua programului,conslderand Ia versiunea din clasa de baza.

Functiile virtuale

a functie virtuala este 0 functie din clasa de baas a cerei declaratie este precedatade cuvantul-cheie virtual.

Definind 'in clasa de baza 0 functie virtuala, iar 'in.clasa derivata 0 functie eu acelasinume, anuntam compilatorul ca nu dorim rezojutie starica pentru aceasta funcpe, cl dorimca identificarea versiunii fuuctiei ce trebuie Sa fie apelata sa se realizeze in timpulexecutiei programului, in functie de obiectul care 0 invoca. Acest meeanism senumeste rezoluiie dinamica (dynamic resolution = dynamic linkage = late binding).

Caracteristicile functiilor virtuale

• Sunt functii mernbre nestatice.• Daca a functie este declaratii virtual 'in clasa de baza, pentru fiecare functie din

clasele derivate avand acelasi prototip se va face rezolujie dinamica.• Suprajncarcarea functiilor virruale In clasele derivate nil este obligarorie.• Daca supraincarcarn functia eu un alt prototip, este considerata 0 alta functie, deci

se face rezolutie statica.• Constructorii nu pot fi functii virtuale, destructorul poate fi funcue virruala.• FUJ1cIiiJe inline .nu pot fi virtuale ,

Exemplu

Pentru exernplificare vom relua claselc Persoana §i Arlgajat (eu 0 midi simpli­fieare: elirninarn destructorul si mesajele afisate in constructori). in clasa Persoanavorn declara funcna .sc r-Le () ca funcpe virtualii.

In plus, vorn mai deriva din clasa Persoana !ilea a clasa denumita C'Ld eri t.. inGlasa Client aclaugam codul IBAN al clientului (ca data membra), funcjiilc de aceesla codul IBAN ~i doi constructori.

Esre necesar sa utilizam includere conditionata.Fisleruj antet persoana. h :

#ifndef PERSOANA_H#define PERSOANA_H#include <iostream>#include <string>using namespace std;

I, };J #endif

Observati ca am declarat functia Scrie () ca functie virtuala, pentru a. obtine rezo­

lutie dinamica. Fisierul persoana. cpp :

#include "persoana.h"persoana: :Persoana(){ Id==++IdCrt; Nume==""; }persoana::persoana(const string& s}{ Id=++IdCrti Nume==s; }Ilfunctii de accesint Persoana: :Getld() { return rdjstring Persoana::GetNume() { return Nume;void Persoana::SetNurne (const string& s) { Nurne=Sj }void Persoana: ~ Scrie () { c ou t c c Ld-c-c ' '«Nume«' 'vn ' }

~

'--'

-~

..J

-'

,-

~

~

79

const int)

PROGRAMAREA ORIENTATA PF. OBIECTE iN C+ +

static int IdCrt;protected:

int Id;string Nurnei

public:Ilconstructori:Persoana ( ) ;Persoana(const string& s);Ilfunctii de accesint Getld () ;string GetNume{)ivoid SetNume(const string&)virtual void Scrie();

) ;

#endif

class Angajat : pUblic Persoana{ protected:

string Functieiint Salariui

publ.ic:int GetSalariu ()void SetSalariu(intlstring GetFunctie();void SetFunctie(string)void Scrie();

Angaja1:();Angajat(const string&, const int) i

P...l"lga Jat (const s cring&, const s tring& I

Fisierul antet angajat. h :

#ifndef ANGAJAT_H#define fu~GAJAT_H

#include "persoana.h"

PROGRAMAREA iN LlMBAJUL CIC++ PENTRU L1CEU78

Page 41: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

81PROGRAMAREA ORIENTATA PE OBiECTE iN C--l-t

int Persoana::ldCrt=Oiint main (){persoana x ("Vasileseu Ana");Angaj at y ( "Papa I on" , "cas i e r " , 5 0 0) ;Client z ( "ronescu Dan", "R049A.AAA1B31007 593 840000")x , Scrie () i y. Scrie () i z . Scrie () ;persoana *p;p~&X; p->Serie();p~&y; p->Serie(};p~&Z; p->Scrie ()return 0;

i~include "client.h"using namespace std;

2.24. Tratarea erorllor utilizand clasa exception

Functiile virtuale pure

Dad! dorim sa includem 0 functie virtuala in clasa de baza §i aceasra urmcaza safie redefinitf in clasele derivate, dar nu exista nicio definitie cu sens in olasa de baza ,atunci putcm defini 0 functie virruala pura. " .

Declaratia unei functii virtuale pure:

virt~al tip nume,_.functie{lista----Paramecri) =.:0;

Constructia = 0 anunta compilatorul ca nu cxtsta corpul functiei , ca aceasta csle 0

functie virtuala pura.

Executand aplicatia coustituira din aceste fisicrc , obrinem pe ecran :

1 Vasilescu Ana2 Papa Ion easier SOD3 roneseu Dan RO·19AAAA1B310075938400001 Vasilescu Ana2 popa Ion easier 5003 lonescu D~n R049AAAA1B31007593840000

Observati ca, in acest caz, compilatorul analizcaza continutul pointerului, nu tipulacestuia, ~j se executa funcjia Serie () corcspunzatoare.

Biblioteca standard a limbajului C+ -+ contine 0 clesa pcutru tratarca crcrilcr.Aceasta clasa se numeste exception si. pentru a utiliza aceasta clasa, trebuie saincludem fisierul antet corcspunzaror :

~ #include <excepcion>

se)

Persoana ()

string&,

'«Salariu«'\n'iconst string& sf, const

{ return Salariu;{ Salariu::::x; }{ return Functie;{ Functie :::: Si

return Codlban; }string& se) { Cadlban=sei

string&)

string& sn, const string& se);

protected:string Codlban;

public:string GetCodlban()ivoid SetCodlban{constvoi.d Scrie () ; .IlconstructoriClient () ;Client (const

nDr.~D A H An,.., A, iN LIMBAJUL CIC++ PENTRU LICEU

r-rsrerut angaj at. cpp :

#include <iostream>#include "angajat.h"int .~gajat: :GetSalariu()void Angajat: :SetSalariu(int xlstring Angajat:: GetFunctie ( )void Angajat: : SetFunctie (string s)void Angajat: :Scrie(){ c ou t.c-c Ed-c c ' "<c.Nume-c c ' '«Functie«'Angajat: :Angajat (const string& SD,int s): Persoana(sn){ Functie=sf; Salariu=s; }Angajat::Angajat(const string& sf, canst int 5){ Functie=sf; Salariu=s; }Angajat: :Angajat () : Persoana (){ Salariu=Oi Functie=""; )

Pisierul antet eli en t . h :

#ifndef CLIENT_H#define CLIENT_H#include "persoana.h"class Client: public Persoana(

"0

) ;

4fendi't

Fisierul c 1 i en t . cpp :

#include "client. h "string Client: :GetCodlban() {void Client: : SetCodlban(constvoid Client::Scrie()

{ cout«Id«' "<cNume-c-c ' "<ccoo.rben-e e : 'vn ' ;Client: : Client () : Persoana () {Codlban=" " ;Client::Client(const string& sn, constPersoana(sn){ Codlban=sci

Fisierul care contine funcria main ( )

#include <iostream>ffinclude !'angajat.h"

~

\ l

~

-

: !,

,...,

"/,i ,i "

,-

Page 42: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

82 PROGRAMAREA iN LIMBAJUL C/C++ PENTRU L1CEU

rPROGRAMAREA ORIENTATA PE OBlECTE iN C+ + 83 , ~

Din clasa exception au fost derivate c1asele: ~

Numele clasei Descriere'!

i

exception Clasa de baza peruru roare excepjiile standard in C -+ +. iExcepjii care pot fi generate la alocarea dinamica a memorici (ell opera.

,

bad_alloe

itorul new) - se incearca alocarea dinamica a unei zone de rncmoric, darnu exista suficlenta memorte disponibfla. i

bad_cast Bxceptii generate de operarorul dynamic_cast, care aparc atunci cand Ise converteste un pointer sau 0 referirua ta un object al clasei de baza Intr-un

Ipointer la un obiect al clascl derivate.

bad_exception Excepjiile bad_exception SUI'l1 generate de erori ncasteptatc. care nusum capturate de niciun cecch . I

bad_typeid Opcrarorut typeid rcrurneaza informaui dcsprc tipul unui obiect. 0 croare Ibad_typeid esre gencrata la incerearca de a aplica opcrarorul t.ypeLd Iunei expresu vide. I

logic_error Erori logice generate de program. Accasta cstc ctasa de baza peruru Idomain error, inva1id_argurnent, 1engtlLerror, out_of_range. !

domain_error Exceptie gcnerata atunci cand estc utilizat un domcniu matematic invalid.,,

invalid argument Eroarc gencrata de paramctri incorccti.

length_error Eroare generate la crcarea unui obiect a carui lungime dcpaseste lungimeamaxima adrnisa.

out- of_range Eroare generata auinci cand un indice cste in afara domeniului (pentru clasavector de exemplu, sau bi tset, de catre operatorul de indexare l l ).

runtime_error Eror i generate in rirupul cxecutici prograrnului. Aceasta estc clasa de baza ipentru overflow_error, underflow_error, range_error.

overflow_error o exceptio generate de -0 croare maternarica de tip overflow (depasirc Isupenoara a domeniului de valori). I

range_error o exceprie generata de incercarea de a memora 0 valoare care se afla in Iafara domeniului de valori.

underflow_error o exceptie generata de 0 eroare matemauca de tip underflow (dcpasire 'I

inferioara a domeniului de valori) ----1 I[

,r-bad_typeid

~

,~

i~

c.J

~

« e.what() « '\n'

nul" )

Functia membra what ( )

int CitesteNenul(){runtime_error eroare ("Numarint val;

#include <iostream>#include <exception>#include <typeinfo>using namespace stdjint main (){try

{ string* p=O;typeid(*p) ;

Iitentativa de a identifica tipul unui obiect inexistent)

catch (exception& e){cout < "Standard exception: " < e. what () < '\n 1 j }

return 0;

Exemplu de utilizare a exceptiei standard bao_typeid:

"Aruncarea" explicita a unei erori standard

Functia CitesteNenul () va "arunca" explicit 0 exceptio de tip runtime_errorin cazul in care se citeste valoarea O. Observati ca pentru a putea utiliza clasaruntime_error am inclus stdexcept.

#include <iostream>#include <stdexcept>using names~ace std;

Pe ecran se va afisa :

Standard exception: std: :bad_alloc

In clasa exception §i in clasele derivate exista 0 functie membra denumitawhat () . Functia returneaza mesajul de eroare corespunzator unei erori aparute.

Exemplu de utilizare a exceptiei standard bad_alloc :

#include <iostream>#include <exception>using namespace std;int main (){try

{ int* v= new int[lOOOOOOOOO];catch (exception& e)

{ cout « "Standard exception:return 0; }

range_error

out_of_range

length_error

domain error

overflow_error

underflow_e:;.ror

invalid_argument:

bad_cast

bad alloc

logic_error

bad_exception

runtime_error

exception

Page 43: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

C""'

84 PROGRAMAREA iN LIMBA.lUL C/C+..- PENTRU LlCEU

cin » val;if (val == 0) throw{eroare);return val;

int main (){ try

(

int x=CitesteNenul()icout«x;

)

catch (runtime_error& e){ cout«"Eroare capturata: "«e.what ();

return 0;

La introducerea valorii 0, programul va aflsa pe ccran :

Eroare capturata: Numar nul

lIII

I

PROGRAM AREA ORIENTATA PE OHiECTE iN C.,. -j

int CitesteNenul(){int val;cin » vaJ.;if (val =:= 0) throw ExceptiaMea ("Numar nul") ;return val;

int main (){ try

{int x=CitesteNenul()ic ou t c c x r

catch (ExceptiaMea& e){ c ou t;«-c" Eroare capturata: "«e .whet; () ;

return 0;

85

2.25. Exercitii §i probleme propuse

4. Presupunand ca III clasa Factura de la exercitiul precedent este definita 0 funcucmembra nestatica publica denurnitf Scrie (), care afiscaza pe ecran date refcri­toare Ja factura curenta. in dcfinitia acestei functii in exteriorul clase! ne putemrefcri la data membra Cod astfel :

1.. Un obiect este pentru 0 clasa ceea ce ...a. caine este pentru pisica.b. filosof este pentru Kant.c. Nichita Stanescu este penrru poet.d. carte este pentru biblioteca,

2. Presupunand ca ati definit a clasa denumita Factura care conrine data membranestanca privata Cod, ce retine codul facturii. Considerand un obiect F de tipFactura, care dintre urmatoarele instructiuni aflseaza corect codul facturii?a. cou t c-ep . Cod; b. cout«F (Cod) ;c. cout«Factura.Cod; d. Niciuna dintre variantelc precedente.

3. Presupunand ca In clasa Factura de la exercitiul precedent este definite a functiemembra nesranca publica dcnumita Total ( ), ce returneaza suma totala de pcfactura curcuta. Considcrand obiectul F de tip Factura, care dintre urmatoarcleinstructiun! aflseaze corect toralul de pe factura ?

C""'

,, .

-

.-

~

-

Derivarea propriei clase de exceptii din clasa exception

in c+ +, pot fi "aruneate" erori de orice tip, dar acest lucru este imposibil in altelimbaje de programare. De exemplu, in Java sau in eneste posibila numai "aruncarea"unei erori standard sau 0 eroare de un tip derivat din ercr-ile standard. Uniformizarearnodului de trarare a erorilor poate face programele mai usor de inteles si de tnrretinut.

Exemplu

Vom deriva din clasa logic_error 0 clasa denurnita Except Labtee.. Decla-ratia clasei :

#ifndef EXCEPTIAMEA_H#define EXCEPTIAMEA H#include <stdexcept>class ExceptiaMea : public std::logic_error{public: ExceptiaMea(const char * $); };

#endif II EXCEPTIAMEA_H

Definina constructorului :

ExceptiaMea :: ExceptiaMea Cconst char * s)std: :logic_error(s) { }

in functia Ci testeNenul () vom "arunca" 0 cxccpue de tip ExceptlaMea incazuJ in care se citestc vaJoarea 0 :

#include <iostream>ttincluJe "exceptiarnea.h"#include <stdexcept>using namespace std;

3. cout«F. 'I'o t.aL () i

c. cout«Factura.Total()i

a. F.Codc. Cod

b. cout«Factura: :Total();d. Niciuna dintre variantcle precedcntc.

b. this->Codd. Faccura.Cod

Page 44: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

86 PROGRAM AREA iN UMBAJUL C/C +--1 PENTRU LICEl, f'.- -uncue este 12

definita in exteriorul clasei. care este antetul corect pentru definitia functie] 1Scrie() ?

7. Considerand ca antetul constructorului clasei Factura este Ea c t u r a (int=l,string=" Anonim"), care dintre urmatoarcle declaratii sunt corecte ?

a. Fl *F2c. Fl.operator*(F2}

a. Factura::void Scrie()c. void Factura: :Scrie()

6. Care dintre urmatoarele variantestructor al clasei Fec t uz-a ?

a.void Factura();c.void Factura: :Factura()

a. Factura F;c. Factura F(7);

b. void Factura.Scrie{)d. Factura::Scrie()

reprezlnts 0 declaratie corecta pentru un con-

b. Factura ( )d. FacturaCanstructor();

b. Factura F(7, "Papa Vasile")d. Factura F("Fopa Vasile");

13.

PROGRAMAREA ORIENTATA FE Ol3lECTE IN C+ + 87

Presupunand ca supra'indirdim ca fuuctie fri.end operatorul -;. ~i' dorim safunetioneze A§i sub forma F1 +F2...-F3 (unde FL P2, F3 sunt obiecte de tip

Factura). In accst caz trebuie sa :

a. supra'incarcam operatorul + pentru a accepta 3 parametri ;b. returnam ca rezultat un obiect de tip Factura;c. returnam un rezultat avand un tip standard al limbajului C+ + ;d. supratncardim operatorul + tara parametri, astfel incat la apel sa poata accepta

un numar variabi l de parametri ;e. Niciuna dintre var-iantele preccdcnte.

Presupunand ca am supraincarcat operatorul binar * ca functie membra publicaa clasei Factura, iar Fl si F2 sunt doua obiecre de tip Factura, 'care dintre

urmatoarele var iante reprezinta 0 utilizare corecra a acestui operator?

b.operator*(Fl,F2)d. Niciuna dintre variantele precedente

{ ~

~

~

8. Care este declaratia corecta pentru destructorul clasei Factura?

9. Care dintre urmatorii constructori pentru clasa Factura pot coexista ?

Pe orice facrura trebuie sa fie specificata valoarea taxei pe valcare adaugata(TVA). Care dintre urmatoarele variante repreainra cea mai adecvata modalitatc

de a retine valoarea TVA-ului ?a. -Factura (int);c. -Factura () ;

b.void -Factura();d. -Factura(Factura&)

14.

a. Data membra nestanca ~

c. Var-iabila globala :

b. Data membra statics ~

d. Variabila locala funcuei Scrie () .

a. friend Factura operator+(Factura, Factura)b. Factura operator+{const Factura&)c. Factura operator+(const Factura&, const Factura&) constd. Fact.ura operator+(const Factura&, const Fact:ura&)e. Fact:ura& operato:r+(const Fact:.ura&, canst F'actura&)f. Niciuna dintre varianrele prcccdcmc.

10. Care este declaratia corectaa constructorului de copiere al clasei Factura?

a. friend Factura(Factura);p. Factura(censt Factura&);c ...reid Pec t u r a : : r-act.ure (const Factura&);d. Factura& Factura (const Factura&);e. Factura Factura(Factura&);f. Niciuna dintre variantele precedente. .

11. Presupunand di am supratncarcat operatorul binar + ca functie prietcna a claseiFactura, care varianta poate fi un antet corect al definitiei operatorului +?

a. Factura (in t) ;c. Factura(int, string="");

b. Faciura(int=O, string="");d. Factura ( ) ;

15.

16.

Presupunand ca Firma este 0 data membra statica de tip string a claseiFactura, care dintre urmatoarele afirmatii sunt corecte?

a. Data membra Firma trebuie initial izata chiar de 1a declararea sa in cadru1

declaratiei clasei Factura astfel : static string Firma:=o"";b. in fisierul care conrine fuuctia main (), initializam Firma ca variabila

globala astiel : str"ing Fa'c't.ura":: FiI-ma=-"vasileSRL";c. in functia main ( ), initial izam Firma ca variablla locals astfel: string

Factura: :Firma="VasileSRL";d. Declarant un obiect F de tip Factura §i apoi initializam Firma ca membru

a] lui F astfel: F. Firma::: "VasileSRL".

Presupunand ca supralndirci'im operatorul = pentru c1asa Factura, care dintreurrnatoarele variante repreztma 0 declaratie corecta pentru acest operator?

a. friend Factura operator=(Factura&, const Factura&)

b. Factura& operai.::.or=(const Factura&) i

c. Factura& opera't.or={Factura&, Factura&) const;d. Factura& opera~or~(const Factura&) const;c. void opera LOT"" (Factu:caD:, const Fac:r"ura&);

f. Niciuna dintre variantelc precedente.

.. .~

,I~

-

Page 45: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

88 PROGRAMAREA iN LlMBAJUL C/('-t--!- PENTRU LlCEC PROGRAMAREA ORIENTATA PE OBlECTE iN C+ + 89

17.

18.

19.

21. Care dintre urrnatoarele perechi pot reprezenta 0 relatie de ripul clasa de bad)!clasii derivaui't

b. cl~~s Y: public class Xd. class X: public Y

b. Cilindru/Cerc;d. Poligon/Poligon convex.

a. Punct/Poligon;c. Cerc/Triuughi ;

a. class Y: public Xc. class X: public class Y

a. Se apeleaza rnai inrai un constructor al clasei A, apoi WI constructor aI clasei B,apoi un constructor al clasei C.

b. Se apcleaza mai intai W1 constructor aJ clasei C, apoi un constructor al clasci B,apoi un constructor al clasei A.

c. Se apeleaza doar un constructor ai c1asei C.d. Este posibil sa nu se apeleze niciun constructor, in cazul in care clasele nu au

constructori definiti.

26. Definiti 0 clasa denumita Caine. Datele membre VOl' fi codul de idcntificare,numcle, rasa, anu1 na§terii. Datele membrc VOl' fj dcclaratc pr iva t.e. Declaralifunqii membre publice pentru acces 1a date.~i pemru afi~are. Scrieti 0 aplicatiein carc sa demonstrati ca aceasta clasa functioneaza carect.

25. Sa consideram ca A este clasa de baza pentru clasa B, iar Beste clasa de bazapentru clasa c. Cand creep un obiect al clasei c :

24. Care dintre urmatoarelc afirrnatii sunt corecte ?

a. Orice operator din limbajul C+ + poate fi supraincarcai.b. Prill supralncarcare putem modifica arttatea operatorilor .c. Prin supraincarcare prioritatea ~i asociativitatea operatorilor nu se schimba.d. Tori operatorii pot fi supraincarcati atat ca fuuctii friend, cat ~i ca functii

mernbre ale clasei.e. Pentru orice clasa cream trebuie sa supraincarcam toti operatorii limbajului.f. Uni! operator: pot fi supraincarcati atar ca operator! unar-i, cat §i binari.

23. Considerand ca am derivat public clasa X din clasa Y, iar in clasa Y este decla­rata data membra d eli specificatorul de acces protected, care dintre urrna­toarele _afirmalii sunt adevarate ?

a. Nu avern acces la d in clasa x.b. Avern acces la din orice functie din x.c. Avent acces la din orice functie prietcna cu clasa x.d. Data membra d trebuie redeclarata in X pentru a avea acces 1a ea.e. Avern acces 1a d numai in clasa y si functiile prietene ale clasei Y.f. Niciuna dintre variantele precedente.

22. Care dintre urmacoarcjc var-iante reprez.inta faprul ca am derivar clasa X dinclasa Y, eu specificatorul de acces public?

a. cste posibil sa definim mai multe funcni cu acccasl lista de paramctri, dar ellnume diferite ;

b. sa definim mai multi destructcri pentru 0 clasa ;c. sa definim mai multi constructori pcntru 0 clasg ;d. sa definim mai multo functi i cu acelasi nume, dar care irebuie sa difere prin

tipu] rezultatului ;e. sa definim mai multe funqii cu accla~i nUIllC, dar care trebuic sa dih:~rc prill

Iista parametriJor;f. putem s~ utilizam funqii cu Ull singur nume pentru a iniplemcnta toate

operaIiilc llecesare.

Presupunand ci'i supraincarcam opcratoru! < pentru a afisa 0 facrura, caredinrre urrnatoarele variame reprezinta 0 dcclarane 'coreera a acestui operator?

a. friend Factura opera~or«(ostream&, canst Factura&);b. friend ostream& operator«(ostream&, Canst Factura&)c. friend void operator«(const ostream&, canst Factura&);d.ostream& operator«(ostream&)C.ostream& operator«(ostream&, Factura)if. Niciuna dintre variantele precedente.

Presupunand cii dorim sa supraincarcarn pentru clasa Factura operatorul ++ cafunctie publica membra a clasei, atar in forma prefixata, cat si in forma post­flxata. Care dintre urmatoarele afirmatii sunt corecte ?

a. Trebuie sa supraincarcarn operatorul ++ de doua ori, cuurrnarorul prototipFactura& operator ++ (),. . .

b. Trebuie sa supraiucarcam operatorul ++ 0 singura data, cu urmatorujprototip Factura& operator ++ () ;

c. Trebuie sa supratncarcam operatorul ++ de doua ori, eu urmatoarele proto­tipuri :Factura& operator ++()iFactura operator ~+();

d. Trebuie sa supraincarcam operatorul + + de doua ori, eu urrnatoarele proto­tipuriF'actura& operator ~+()i

Factura operator +~ (int)

c. Operatorul ++ nu poate fi supratncarcar pentru clasa Factura;f. Niciuna dintre variantele precedente ..

Principalul rnctiv pentru care utilizam directivele preprocesor #define, #ifndef,#endif in fisierul antet al unei clase este ca ...

a. dorim sa atribuim un nume semnificariv fisierului antet respectiv ;b. ne asiguram ca astfel clasa a fost declarata inainte de a fi utilizata ;c. astfel evlram declaratia multipla a unei clase in cadruI aceleiasi aplicatii ;d. realizam 0 economic de memorie. ..

20. Prin supraincarcare ...

r"'

, ,

r"'

'"

':

, ,

-

Page 46: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

28. Euclid

27. Complex

Un numar complex poate f reprezentat in forma algebrica. retinand partca realasi partea imaginara a numarului. De exemplu, z=2. 5-3i cste un numar complex(2.5 este partea reala, iar -3 este partea imagtnara a numarului). Definiti o clasadenumita Complex pentru Jucrul eli numere complexe. Datele membre vor f parteareala §i partea irnaginara a numarului (ambele de tip double, ambele private).Definiti construcrori, funcjii de acces §i operatorii specifici pentru lucrul eli numerecomplexe. Deruonstrati intr-o aplicatie ca aceasta clasa functioneaza.

Utilizati clasa BigInt pentru a rezolva urrnatoarea problema.Este bine-cunoscut algoritmul de calcul al celui mai mare divizor eomun

(emmde) eu algoritmul lui Euelid prin impartiri repetate. Conform acestui algoriun,cmmdc a doua numere naturale nenule a §i b se calculeaza pastrand restul Impartirhsi reluand impartirea cu vechiuJ impartttor §i vechiul rest. Algoritmul se va terminacand restul impartirf devine zero. Cel mai mare divizor comun al celor doua numerea si b va fi ultimul irnpartitor.

Pentru calculul celui mai mare divizor comun al perechii (16,22) se vor efeetuasuccesiv impartirile :

90 PROGRAMAREA iN LIMBAJUL CIC ++ PENTRU UCEU

DeLrnpe r t d t; Imparlitor Rest16 22 16 Pasul 1

22 16 6 Pasul 2

16 6 4 Pasul 3

6 4 2 Pasul 4

4 2 0 Pasul 5

1-J:<.VlJl",r~IVl.rU,"l;,n. Vf\.Jl;,'~' In. Ln. r J.:. VLaJ.:.\..... I J.:. "" .... T , n-Exemple

euclid.in euclid. out Explicatie

B 5 Numarul maxim de pasi pentru oricare pereche

5 de numere mai mici egale eli 8 este 5. Perechea

8 (5, 8) este minima eu aceasra proprietate.

12345678910 48 Numarul maxim de pasi pentru oncare pereche

4807526976 de numere mai mici egale cu 12345678910

7778742049 esre 48.

Perechea (4807526976,7778742049) esteminima eli aceasta proprietate.

-C

'-'

...J

.JVom numi un "pas" 0 operatic de impartire ce intervine in calculului cmmdc. Se

observa ca pentru determinarea cmmdc(16,22) =2 au fost neeesari 5 pasi.

Cerirua

Cunoscand valoarea unui numar natural D, scrieti un program care determina 0

pereche de numere naturale (a, b) mai mid sau egale eu D, al carer cmmdc se obtinetnrr-un numar maxim de pasi. Daca exists mai multe perechi eu aceasta proprietate,se va afisa eea minima. Spunem di perechea (a, b) este mai mica decat perechea(x, y), daca a-ex sau a e x si b<y.

Date de intrare

Ftsierul de intrare euclid. in contine un singur numar natura] n (4<n<1 0 2 °°)..Date de iesire

Fisierul de icsire euclid. out va contine pe prima linie numarul maxim de pasideterminat. A doua linie va contine un numar natural a reprczentand pr imul numiir alperechii minime identificate, iar pe a rreia linie se va serie uuruarul b reprezentand aldoilea numar din pereche.

Cerinta

Date fiind un set de reguli si textul in care' trebuie realizate inlocuirile, sa sedetermine forma finala a textului,

Date de intrare

Fisierul de intrare replace. in contine pe prima linie numarul natural N(O.:o;N::;;10) reprezentand numarul de reguli. Urmatoarele 2N Hnii contin perechi desiruri, primul sir din pereche fiind sirul care se cauta, iar pe randul iruediat urmatorsirul cu care trebuie inlocuit acesta. Ultimul rand a1 fisierului de inrrare continetextul in care se vor face inlocuirile.

Date de iesire

Fisierul de iesire r eoLace . out va contine 0 singura linie pe care va f scristexrul obnnur dupa aplicarea eel or N reguli de inlocuire ,

~

-

Page 47: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

soseste la cabinet laora la care este programat primul pacient ;nu lucreaza mai mutt de 8 ore;cand termina de tratat un pacient. iar durata cfectivs a tratamentului este maimica dedit durata maximala estimata. doctorul se odihneste in timpul ramaspana la durata rnaximala estimate :secretara are suficienta expedcnta st estimeazf corect durata maximala a unuitratament, astfel ca doctorul nu depaseste niciodata durata maxiruala atratamentului unui pacient ;dupa terminarea tratamenrului unui pacient (si a eventualei perioade de odinna),doctorul invita in cabinet urmatorul pacient prograrnat ;doctorul nu suporta sa existe pacienti in sala de asteptare ; fiecare pacient vineexact la ora la care este prograrnat ~i intra imediat in cabinetul doctorului.

in fiecare zi, secretara analizeaza Iista programarilor pentru a doua zi §i anu­leaza 0 serie de programari (telefonand pacientilor pentru confinnare sau pentru repro­gramare in alta zi), astfel incat :

toate restrtctfile din algoritmul de lucru al doctorului sa fie respectate ;doctorul sa trateze un numar maxim de pacienti.

Scrieti un program care afiseaza Iista programarilor confirrnate pentru a doua zi.

.-,

.-,

,

I

92 PROGRAMAREA iN LIMBAJUL CIC ++ PENTRU LICEU

Exemplu

replace. in replace. out

3 azi_es c e..va.ner aLs a., eac e jvesejesties"tejoivineri

-azi esti joi si esti vesel

(Olimpiada Municipala de Informatica, Iasi., 2009)

30. Modificati clasa BigInt astfel incat sa Iucreze cu numere naturale scrise inbaza b (b<=3 6). Un numar in baza b utiiizeaza b cifre (cifreJe mai mari decat 9fiind eodifieate eu Htere din alfabetul englez A=10, B=l1, "', z=35).

31. Derivati din clasa Biglnt 0 clasa care sa impJementeze numerele tntrcgi mari.Adaugari 0 data membra care sa reprezinte semnul nurnarului 1;>1 supraincarcatifunctiile ~i operatorii in mod corespunzator.

rI

PROGRAMAREA ORIENTATA PE OBJECTE IN C+ + 93

,....

r-;

, ,

r-t,

! ,

,i

;-

32. Timp

Creati 0 clasa denurnita Timp pentru a memora timpul expnrnar in are (de la 0. Ja 23), minute (de la 0 la 59) ~i seeunde (de la 0 Ia 59).

Creati un constructor cu trei parametri (pentru are, minute, secunde), avand totivalorile implicite o. Constructorul trebuie sa verifice faptul ca restrictiile specificatepentru ora, minute, secundc sunt respectate.

Supraincarcati operatorul de citire si operatorul de afisare pentru c1asa Timp(rimpul va fi afisat sub forma ora :minute: secunde, rninurele §i secundele avandexact deus ci.fre).

Supraiucarcati operatorul + pentru a aduna doi timpi. Daca prin adunare sedepaseste 23 : 59 : 59, se obtine ca rezultat timpul corespunzator din ziua urmatoare.

Supraincarcati operatorul - pentru a scadea doi timpi. Daca scazatorul este maimare dedit descazutul, afisati timpul corespunzator din ziua precedents.

Supraincarcati §i operatorii +=, respectiv -r e .

Supraincarcati operatorii de cgahcate si relationali.

33. Dentist

Creati 0 clasa denumita prograrna~eDentist, in care sa utilizati c1asa 'I'ri.rnpconstruita la problema precedenta, pentru a rezolva unnaroarea problema.

La un cabinet stomatologic, secretara realizeaza programarea pacientilor. Pentrufiecare pacient programat, redne numele, timpul la care pacientul doresre sa fieprogramat· (ora §i minutul), respectiv durata maximaHi estimativa a tratamentului(determinata pe baza vastei experiente a secretarei §i exprimata. de asemenea in ore §iminute). Doctorul lucreaza dupa urmatorul algoritm:

;,

II

I

34. Polinoame

Un polinom poate fi reprezentat ca un vector in care retinem coeficientii aces­ruia, pe pozitia i in vector fiind plasat coeficienrul monornului Xi. De exemplu , Iapolinomul de grad 5 P {x ) =X5-4X3+2X+1S, vectorul de coeficienti va fl :

I p- 115 I 2 I 0 1- 4 10 11 1o 1 2 3. 4 5

Construiti 0 clasa denumita Polinom pentru lucrul eli polinoamc avand aceastareprezentare. Scrieti 0 aplicatie in care sa demonstrati functionalitatea clasei.

35. Poligon convex

Creati c1asa Punet pentru reprezentarea unui punct in plan specificat princoordonatele sale carreziene. Creati clasa Segment (un segment fiind determinar dedoua puncte in plan). Utilizand clasele Punct §i Segment, rezolvati urrnatoareaproblema:

• In fisierul convex. in se afla pe prima linie un numar natural n (35n:S: 1000)reprezentand numarul de varfuri ale unui poligon convex. Pe urmatoarele n liniisunt scrise care doua nurnere reale reprezentand coordonatele varfurilorpoligonului (in ordinea abscisa. ordonara). Varfudlc poligonuJui sunt specificatein flsier in ordinea parcurgerii poligonului in sensul aceIor de ceasornic.

• in fisierul convex. out afisati pe Iinii separate perirnetrul ~i aria poligol1ului.convex citit din fi§ierurde intnire.

Page 48: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

94 PRQGRAMARF.A iN LIMBAJUL CIC++ PENTRU UCEUPROGRAMAREA ORIENTATA PEOBIECTEij\' Cot i·

95

'-..-i

39. Teste grilaConstruiti clasele neccsare pentru a rcal iza 0 aplicatie de lucru ell teste grini. Un

test grila este format dintr-un numar variabil de iterni . Un item consta intr-oinrrebare pentru care se ofera exact patru variante de raspuns, dintre care doar un .......!singur raspuns este corecr. Cand se genercaza un test grila, se aleg in mod aleatoriuitemi distincti din Iista iteniilor disponibill , numarul acestora flind prestabilit (dartara a depasi 100). La rezolvarea unui test griJa, pentru evaluare vom considera catori itemii din test au aceeasi pondere pentru calculul punctajului la test. La evaluaretrebuie sa se afiseze punctajul total obtinut Ia test, dar si feedback punctual pentrufiecare item. Feedbackul poate fi doar corect/Incorect sau puteti afisa un 1feedback mai elaborat, specific itemului respectiv (pentru iternii care .au asociat un Ii

feedback constructiv). -'

36. SfereDerlvan din clasa Punet clasa Punct3D pentru reprezentarea unui punet ill

spatiu, spccificar de asemenea prin coordonatele sale carteziene. Definiti. clasaSfera (0 sfcra fiind idemificara prin coordonateie cenrrului sau - un puncr inspatiu - ~i raza). Uril izati clasele Punct3D sl Sfera pentru urmatoarea problema:

• Flslerul de Jntrare sf ere. in contine pe prima Iinie un numar natural n(2SnS100), reprezenrand HUmaTU] de sfere, iar pe urmatoarele n Jlnii dire patrunurnere Teale Y.. y Z r, reprezentand coordonarele centrului ~i raza pentrufiecare dinrre cele n sfere. Scrieti un program care sa verifice dad! exista eelputin doua sfere care se inrersecteaza. ProgramuJ va afisa pe ecran mesajul DAsau mesajul NU, dupa caz.

37. Date calendaristice

Creep 0 class pentru lucrul cu date calendaristice. Scrleti 0 epllcaue in care sademonstrap ca aceasta class fuucjioneaza.

39. Biblioteca

Studiati activitatea de la biblioteca scolii ~i reaiizati 0 eplicape care sa permjragestiunca unci biblioteci scolare. La biblioteca trebuie sa retinem :

evidenta cartilor (pentru fiecare carte retinern cota dir!ii, titlul, aurorul, edirura,anul aparijiei) ; aplicajia trebuie sa permira adaugarea unei carti, srergerea uncicartt, caurarea cartilor dupa titlu (cautare cu potrivire totals sau partiala),diutarea tuturor cartiJor unui autor etc. ;pentru carrile de speciaIirate, rerineti domeniuJ caqii (informatica, drept,medic ina ClC.); apJicatia trebuie sa realizeze caudiri dupa domeniu ;evidenta cititori1or (penfru fieeare cititor retinem· coduJ de identificare aeititoruJui, llumeJe, adresa, telefonul, e-mail-uJ); aplicaria trebuie sa permWladaugarea L111ui dtitor, ~tergerea unui eithor, cautarea cititorilor dupa nume(eautare cu potrivire totala sau paqiaJa), diurarea unui citiror dupa codul -deidcIHificare etc. ;evidenra imprumuturiIor (un imprumut este identificat prin cota dirtii imprumu­tate, codul cititoruIui care a imprumurat cariea, data 1a care a avut loe imprumutul~i data la care a fost restituita caftea imprumutara; utilizati pentru reprezentareadatelor calendaristice cJasa definita 1a problema precedenta); apIica~ia trebuie sapermita reaJizarea unui imprumut, restituirea unci carri, vizualizarea tuturorimprumuturiJor restante (cartile pentru care lermenuJ de predare a fost depa~it,

impreuna cu dateIe cititorilor care au impromutat aceste carti), vizuaJizarea tuturorimprumuturilor unui eithor, vizualizarea luturor eititoriIor eare au irnprumurat 0

anumita carre etc.

iIltr-o data membra statidi yeti retine numarul de zile pentro care poate fiimprumurata 0 carte (ace]a§i pentru wate dirtiIe ~j pentru top cititorii).

40. BlackjackBlackjack, cunoscut si sub numele de 21, este unul dintre cele mai populare

jocuri de cani de casino din lume. ReguIile jocului pot fi consultate pc Internet (deexemplu, vezi http://ro.blackjack.org/reguli). Construiti clasele necesare si realizati

o aplicatie pentru jocul de Blackjack.

4]. Catalogul electronicCoustruiti clasele necesare si proiectati 0 apticarie care sa funcnoncze ca un

catalog scolar electronic. Catalogul electronic contine catalogul corespunzator fieca­rei clase din scoala . Catalogul unci clase confine roti elevii clasei, cu notele (inclusivnota la teza, daca este un obiect cu reza) ~i absentele (motivate ~i nemotivate) lafiecare obiect. Catalogul trcbuie sa permita teate operatliIe permise in catalogul

"oficial" .

, 1~

...J

.....J

-'

-

i~

,...J

-'

...J

Page 49: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

",J'''''-'' 97

using narnespace std;

Iil /Ideclaratietemp~ate <c~ass T>T minim (T, T);

"«minim (51,52)«' \n' ;«minim(il,i2)«'\n'

"«minim rx t . x2 ) < ' \n ' i

)

Iidefini tietemplate <class T>T minim(T x, T y){

if (x<Y) return X;

return Yi

int main (){string sl("Ana are mere"), s z r vAna t.o lvj .int il==8,- i2:=5idouble xl""3.14, x2:<i. 5;I lapelScrie(sl, il} i Scrie(x2, 52} Scrie(il, 'xl);retur'n 0;

Functia minim () poate fi ape lata pentru orice tip de date T pentru care est~

definit operatorul -c,

Exemplul 2. Afisarea a dOUG valori de tipuri diferite

Pentru a exemplifica modul in care declaram. definim $i apelam 0 functle sabloncare acccpta mai multe tipuri ca paramctr-i, vom construi .functia Scrie (), careprimesre ca pararnetri doua valor! de tipuri (parametrtzatc) potential difertte s!afiseaza pe ecran vaJorile respective. Presupunem ca in cazuJ tipurilor pentru careapelarn functia exists operatorul de afisare < < supraincarcat.

#include <io5tream>#include <string>using name-space std;/Ideclararetemplate <class 'I'L, class 'r2 >void Scrie (Tl, 'r2);

52 ("Anatol");int main ()·{st.ring 51 ("Ana are 'mere")int i1==8, i2==5;double xl=3.l4, x2==1.5;Ilapelcout«"Min string:cout«"Min int: "cout«"Min double:return 0;

template <class '1'1' class 'f2 , ... , class T k>

o functie sabion este 0 functie pcntru care eel putin unul dinrre tipurile de dateutilizate este parametrizat. Functia sablon corespunde unei familii de functii, carerealizeaza aceeasi prelucrare, dar asupra unor d'ate de rlpuri difer-lte.

Declararea/definitia unei functii sablon este prccedata de :

3.1. Functiile sablon

3. Elemente de programare generidi

Programarea generica este 0 paradigms de programare ce are ca scop proiectareacomponentelor software (algoritmi, structuri de date, mecanisme de alocare a memo­riei etc.) -lntr-un mod abstract (sau generic), astfel incat utilizarea acesiora sa fieposibila in contexte cat mai variate. in acest scap. accentul este plasat pc organizareaacestor componente astfel inca; sa poata fi reutilizate -5i exrinse in diverse situatii sipc dezvoltarea algoritmilor si, prin unnare, sa fuuctioneze eficient indiferent detipurile/structurile de date implicate.

Programarea generica presupune Ull nivel inalt de abstractizare ~i are 0 comple­xitate ridicata, dar este a abordare narurala : indiferent ca sortam numere, oi sauelevi, metoda de sortare utilizata este practic acecasi.

Concret, pentru ca aceeasi secventa de cod sa poata functiona pentru tipuri dedate diferite, nu este necesar sa 0 rescriern pentru fiecare tip de date, ci vom consi­dera di tipul datelor este un parametru.

In C++, programarea generics este posibila utilizand functii 1;>i clase parame­trizate dupa tip. Acestea sunt denumite functii/clase sablon (template):

Ulterior, in antetuJ sau in corpuJ functiei, pot f utilizare tipurile 'I'J, 'f2 , .•• , T"..

Exemplul 1. Minimul a doua valori

De exemplu, vom scrie a funcpe sablon pcntru dcterminarea minimului a douavalori. Yom prezenta un program complet, pentru a exemplifica modul de declarare,definire si apelul unci astfel de functii.

I:' #include <iostream>, #include <string>

r:

C"'

r,

, I

r-,

!

Page 50: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

8 YKUuKANlAKCA IN LIMBAJUL CIC++ PENTRU LlCEU ELEMENTE DE PROGRAMARE GENERIC.I\. 99

" .,

In definijia clasei , evident, se utilizeaza tipurile T1 , T2 , ... , Tk •

Pentru a utiliza 0 clasa sablon, trebuie sa specificarn numelc clasei. urmat de tipulactual incadrat Intre paranteze unghiulare (xc.). in cazul in care clasa admire caparametri mai multe tipuri, tipurile actuale vor fi specificate intre paranteze unghiu­lare, separate prin virgula.

o clasa sablon estc 0 class pentru care eel putin unul dintre tipurile de dateutilizate estc parametrizat. Clasa sablon corespunde praetie unei famil ii de elasesimilarc, care suporta acelcas! prelucrari,

Din punet de vedere sintactic, declaratia/deflnitia unei clase sablon este precedatade 0 construcue de tipul :

3.2. Clasele sahlon

I i

w

.......;

.~

i I

L

... , class T k >class T 2 ,template <class Tl'

Iidefiniretemplate <class TI, class T2>void Scrie(Tl a, T2 b){cout«"Prima valoare: "«a«"cout«"A doua valoare: "«b«'\n'

Exemplul 3. Suprainciircarea functiilor sablon

Functiile sablon pot fi supraincarcate, ca orice alte functii. Binetnjeles, la supra,jnoarcare, trebuie sa ne asiguram eli functiile supraincarcare difera flira ambiguujjprin lista parametrilor.

Pentru a exemplifica supraindircarea, definim functia inv () 0 data ell doi para­metri (acestia vor fi interschimbati) si 0 data eli un singur parametru (acestuia i se vaschimba semnul algebric).

#include <iostream>#include <string>using n~espace std;

template <class T>void inv{T&) i

Exemplu. Clasa sablon Stiva, I

! i,

temPlate <class T>void inv{T&, T&};

int main (){int i1=8, i2=5;double x1=3.14., x2=1. 5;inv(i1}; inv(il, i2);inv(x2); inv(x1, x2);cout«il«' I «i2« I \n' ~

cout«x1«' '«x~«'\n';

return 0;

template <class T>void inv(T& xl{ x=-x; }

template <class T>void inv(T& a, T& b){ T aux=a; a=b; b=aux;

Stiva este 0 structura de date absrracta, care suporta doua operatii :

- inserarea unui element la varful stivei- extragerea elementului din varful stivei.

Deoarece aecesul este limitat doar la elementul din varful stivei, aceasta strucrurade date functioneaza dupa principiul LIFO (Last In First Out - ultimul intrat, primuliesit) .

Pentru exemplificare, vom defini clasa sablon Stiva care sa impJementeze acesttip de date abstract. Vom considera drept parametru tipul T al elementelor din stiva.Vom reprezenta 0 stiva ea un vector s cu maxim SMAX elemente de tipul T; datamembra vf indica varful stivei. Vom include 5 functii membre publice: Push ()

(insereaza un element in stiva, la varf), Pop () (extrage elemeutul de la varfulstivei), 'Pop () (acceseaza elementul de la varful stivei), Empty (l. (verifica dadistiva este vida) si Size () (care rerurneaza numarul de elemente din stiva).

#ifndef STIVA_H#define STIVA_H#include <stdexcept>

II #define SMAX 10000using namespace std;template <typename T>class Stiva{protected: int vf; T s[S~~];

public:S.tiva() { v£=-l;~'& Top (J

{logic_error e (" Stiva vida") j

1,

~

-'

Page 51: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

} ;#endif /1 STIVA_H

JOIELEMENTE DE PROGRAMARE GENER1CA

Cerinpi

Scrreti ·un program care sa cireasca un program iI1 Jimbajul SL ~i sa il execute.

Date de intrare

Fisierul de intrare s 1 . in contine pe prima linie un numar natural n reprezentandnumarul de instructiuni din programul in limbajul SL care urmeaza. Urmatoarclen linii contin cele n instrucjiuni ale programului, cate 0 instructiune pe C? linie.

Dale de iesire

Fisierul de iesire s 1 . au t va contine 0 singura linie pe care va fi scrisa valoareaafisata de programul SL din fisierul de intrare.

Restrictii

----------------- - .------------- --- - ---r------··-·------·-·-··--- -- --------- -- .. ----PLUS Extrage din stiva doua Daca stiva este

valori (cele de la varf), le 4aduna §i introduce in sriva 10rezultatul. 2 a

si executam PLUS, stiva va arata astfel :1420

TIMES Extrage din stiv_a doua Daca am fj executat TIMES pentru aceeasivalori (ccle de fa van), Ie suva, am fi obdnut :inmultesre §i introduce in 4 astiva rezultatul. 2 a

Daca valoarca de Ia varfulIFZERO n stivei esre 0, atunci se sare

1a cea de a n-~ instrucjiune Idin program. In caz contrar,se continua executia cuinstructiunea urmaroare.

J;)ONE Afiseaza valoarca de lavarful stivei si Incheieexecutia programului(indiferent dad! mai existssau nu instructiuni).

2 ::; n ~ 1000• in cazu1 instructiunilor PUSH si IFZERO exists un singur spatiu tnrre nume1e

instructiunii §i argument.• Argumentul instructiunii PUSH este un numar intreg din intervalul

[-10000, 10000J, iar pentru IFZERO un nuruar natural din [0, i ooo j

Programul din fisierul de inrrare este corect (nu va conrine cicluri infinite, nu vacxtrage 0 valoare dintr-o sriva vida).

PROGRAMAREA iN I.JMBAJUL c:«: H PENTRU LlCEli

if (vf<O) throw e;return s [vi J i

T PoP (){logic_error e("Stival vida") i

if (vf<O) throw e;return 5 [vf--] i

void Push (canst T& xl{logic_error e("Stiva pllna")

if (vI==SMAX-l) throk e;s[++vf]=x; I

bool Ernpty{) {return yf==-ljint Size() {return yf+lj

Aplicatie. Problema SL

100

Limbajul SL (Stack Language) Iucreaza ell 0 stiva (initial vida) ~j un singur registru(care initial contine valoarea 0). ub program in limbajul SL este formal dintr-osuccesiune de instructiuni, caw 0 iristruqiunc pe 0 linie, scrise ell majuscule. Inprogram, insrructiunile sunt numeroratc de la O. Executarea unui program Incepe euprima instructiune a programului. Ins;truqiunile limbajuiui SL sunt:

I

iInstr-uctiune Efect Exemplu

IPUSH x Introduce valoarea intre' ga Daca stiva esre :

Ix in sttva. 12si executam PUSH 4, -stiva va araraastfe1 :41

. 2

STORE Valoarea de 1a varful stivei Dad. stiva este :este exrrasa §i este plasata in 1 .registru. 2

~j executam STORE, stiva va arata astfe1 :2iar in rcgistru se ami valoa rea 1.

LOAD Conjinutul regisrrului esre Dad! registrul are valoarea 4 si stiva estecopiat ~i introdus in suva. 1

2dupa executarea operatiei LOAD registrulva uvea tot vaioarea 4. iar stiva este :4

I]

2- - -- -- - - - - ---

l :

r-r-

r

~

r-'

~

L ,

~

Page 52: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

'02

Exemple

PROGRAMAREA IN LIMBAJUL C/C++ PENTRU LJCEU l03

void ci tire (){char c;fin»ni fin.get(c)ifor (int i=O; .i cn . i++) get1ine(fin,P[iJ,'\n'}i

sl.in sl.out: Expltcat!e

14 12 Executam acest program pas eli pas, urmarind stiva ~i registrulPUSH 5 Instructiunc Stiva Registr-uPUSH 3 PUSH 5 5 . 0PLUS

3STORE PUSH 35

0LOADIFZERO 11 PLUS 8 0

PUSH 4 STORE 8

LOAD LOAD 8 8PLUS IFZERO 11 8 8DONEPUSH 10 PUSH 4

488

LOADTIMES 8DONE LOAD 4 8

8

PLUS 1·28

8

DONE 128

8

PUSH 10

LOAD

TIMES

DONE

(.campion 2008)

Solutie

Vorn citi iustructiunile programului intr-un vector P cu componente de tip string.Vern parcurge secvenpal instructiunile prcgramului ~i Ie vom executa. Pentru fieeareinstructiune, extragern cuvanrul-chele a1 acesteia (cautand mai Intai caracterul spatiueu functia membra a clasei string find () , ap.oi extragem prunul cuvant cu functiamembra substr ()). In functie de instructiune, executam operatia ccrespunzatoare,utilizand operatiile implementate in clasa Stive . Observati ca in eazul instrucrtu­nflor PUSH si IFZERO a fast necesara ~i extragerea numarulul si conversia sa innumar intreg.

#include <fstrearn>#include <stdexcept>#include "stiva.h"#include <string>#include <cstdlib>#define NMAX 1000using·namespace stdiifstream fin ("s1. in")

void ci tire ()int executie()i

int main ()

ci tire () i

fout«executie()«'\n'fout. close ()return 0;

int executie (){int i, a, b, paZjstring op, snrifor (i=Oj i<ni i++)

{paz=p[i).find(' 'J;

op=P[i] .substr(O,poz)if (ap=="PUSH")

{snr=P[i) .substr(paz+l)iS.Fush(ato.i (snr ..data().); con t.tnue i }

if (op=="STORE") { R=S.Pap()i continue;if (op=-="LOAD") {S.Push(R)j con t i.nuc : }if (op=="PLUS")

( a=S.Pop(); b=S.Pop(); s.push(a+b)if (op== "TIMES")

( a=S.Pop(); b=S.Pop(); s.push(a*b)if (op=="IFZERO")

if (S.TOp()==O){snr=P[i] .substr(paz+l)ji=atai(snr.data())-lj continuej}

if (op=="DONE") { return S.Top()i }}

, ~~

continue; }

continue;}

1I

L...:

r 1

'-'

~

i 1LJ

t,

: 1

~

I,

~

-J

Page 53: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

l j

l04 PROGRAMAREA iN LIMBAJUL C/C -H- PENTRU L1CEU ELEMENTE DE PROGRAMARE GENERICA 105

3.3. Exercitii §i probleme propuse

3. Presupunand ca am definit clasa sablon X ell un singur tip ca parametru $i con­sidcrand di dorim sa declararn un obiect ob, transmitand constructorului ca para­metru valoarea 7, care dintre urmatoarelc declaratii sunt corecte ?

1. Construirea unci functii sablon cste recomandata atunci cand ...a. este necesara 0 functie cu mai multi parametri.b. sunt necesare mai multe functii cu acelasi nume, dar care realizeaza preJucrari

diferite, in functie de paramerri.c. sunt necesare mai multe functii, care au parametri de tipuri diferite, dar care·

realizeazii aceleasi prelucrilri.d. este ncccsara crearea unei singure functii, pentru a nu crea confuzii.

2. Care dintre urrnatoarele varianre preceda definitia unei clase sablon ?

4. Definiti 0 funcue sablon care sa determine minimul dintr-un vector, indiferent detipul componentelor vectorului. Apelati functia create pentru vectori eu clementede tipuri difer-ite.

5. Definiti 0 functie sablon care sa sorteze un vector, indiferent de tipul cornpo­nentelor vectorului. Apelati functia creata pentru vectori eu elemente de tipuridiferite.

6. Unific

Utilizand clasa sablon Stiva, rezclvati urmatoarea problema;Se considera un sir A= (AI, A2, ... , AN)' format din N numere naturale nenule.

Doutt numere se considera vecine daca se afla pe pozitii alaturate (Ai are ea veeini peA i - 1 ~i Ai+~, pentru orice l<i<N, A 1 are ea vecin doar pe A 2, iar AN are ca vecin doarpe A N - l ) .

Daca doua clemente vecine Ai, Ai+! (l~i<N) au eel putiu 0 cifra comuna, ele sepot unifica. Procedeul de unificare consta 111 eJiminarea din numerele Ai $i A i ..-1 arururor cifrelor eomune ~i adaugarca prin alipire a numarului obtinut din Aj.,.l lanumarul obtillut din Ai, formandu-se astfel un nou nurnar. Numarul Ai va ti inlocuitell noul I1Umar, iar numaruI Ai-l1 va fi eliminat din $ir. (De exemplu, llumercleA;.=23814 '$i A.'J=-40273 au cifrcle 2, 3, 4 eomunc, dupa unificare obrinemAi.:o: 8 1 7, iar Ai + l este eliminat; observati ca, daca dupa eliminarea cifrelor eomuncnumerele incep cu zerouri nesemnificative, acestea vor 1'i eliminate, apoi se reali··zeaza alipirea.) Dadi in urma eliminarii cifreior comune. unul dintre numere nu mai

Cerinta

Plslerul de intrare unific. in contine pe prima linie 0 valoare naturala N, iar peurmaroarele N linii, in ordine, cele N numere naturale din sirul A, cate un numar pe 0linie.

Cunoscandu-se sirul eelor N numere naturale, sa se determine:a. cifra care apare eel mal frecvent in scrierea tuturor eelor N numere ; daca

exista mai muJte cifre cu aceeasi frecventa de aparitie maxima, se va retine ceamai midi citra ;

b. sirul obtinut prin efectuarea unui nurnar maxim de unificari, dupa reguliledescrise in enunt.

Date de intrare

are cifre, atunci numarul rezultat va avea cifrele ramase in celalalt. Daca in urmaeliminarii cifrelor comune atilt Ai cat ~i A j + 1 nu mai au cifre, atunci ambele numcrevor fi eliminate din sir , tadi a fi inlocuire eli 0 alta valoare.

Ordinea In care se fae unificarilc in sir este fmportanui : la fiecare pas se alegeprima' percche de clemente veeine Ai Ai + 1 care poatc fi unificata , cousiderand sirulpareurs de Ia stanga la dreapta. (De exemplu, considerand Ai=123, Ai-l'1=234,

Ai+2=235, se unifica A:-. eu Aid = > Ai=14, iar unificarea cu urmatorul numar nurnai este posibila.)

Date de iesire

Fisierul de iesire unific. out va contlne pe prima linie un numar natural creprezentand cifra c,ar.e apare eel mai frecvent in scrierea eelor N numere naturale. Pecea de-a doua Iinie, un numar natural Nr reprezentand nurnarul de numere naturaleramase In sir dupa efectuarea unui numar maxim de unificari, Pe cea de-a treia liniese vor serie cele Nr numere naturale ramase, in ordinea din sir, separate prin care unspatiu.

Daca, in urma procedeului de unificare, toate numerele vor fi eliminate, fisierulde iesire va contine 0 singura linie, pe care se va scrie cifra care apare eel maifreevent in scrierea celor N numere naturale.

Restricjii

• 1 <; N <; 100 000• Numerele din sirul initial, precum $i numerele obtinute in urma uniflcarilor , nu

vor depa§i 10 1 8

b. X<int> ob=7;d.x ob<int>(7);

b. <template class T>d. template <class T>

a. template <T>c. template class<'I'>

a. x ob (7) ;

c. X<int> ab(7);

r-'-

I

1- ;

l J

i

[

,...,

r

l .

r

r

I'!

iI ,

!-

rI ;

I.

r

Page 54: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

lOG

Exemplu

PROGRAMAREA iN UMBAJUL C/C+-t PENTRU L1CEU

rII'

(Olimpiada Judeteana de Informatica 2013)

7. Construiji 0 class sablon denurnita Coada, care sa implementeze aceasra strucrura'de date. Arnintim ca 0 coada este a srructura de date abstracts care permiteurmatoarele operatii :- inserarea unui clement 1a sfarsirul cozii- extragerea elementului de la inceputul cozii.Demonsrrau functionalitatea clasei intr-o aplicatie in care sa util izati eozi euelemente de tipuri diferite. .

unific.inlunific.out106

476740

1232311238

3312035

50007

3

2

o 837

Expticatii

Cifra care apare eel mai frecvem cste 3 (de 6 orij.Se unifica : 47 cu 67 = > 46.

Sirul ramas : 6 46 40 123 231 1238 331 2035 50007Se unifica : 6 co 46 => 4.

Sirul ramas : 4 40 123 231 1238 331 2035 50007

Sc unifica : 4 Cll 40 = > O.

Sirul ramas : 0 123 231 1238 331 2035 50007

Se uniflca : 123 cu 231, ambele numere raman fara cifre, dec!vor f ambele eliminate.

Simi dimas: 0 1238 331 2035 50007

Se unifica : 1238 cu 331 = > 28. Sirul ramas:' a 282035 50007

Se unifica : 28 cu 2035 => 835. Sirul ramas : 0 83550007

Se uniflca : 835cu50007 => 837. Sirul ramas : 0837

4. STL. Concepte generale

4.1. Ce este STL ?

SlL (Standard Template Library - biblioteca de sabloane standard) esre 0 bibliotecareunind implementari generice a numeroase structuri de date ~i algorltmi fundamen­tali in informatica. STL nu este singura biblloteca de acest tip, dar cu siguranta estecea mai utilizata, datorita rnodului in care a fost proiectata strucrura sa, a eficienteiimplementarilor $i a faptului ca prograrnatorii pot integra ell usurinta componente STLin aplicatiile lor. Programatorii familiarizati eu structura STL, principiile P~Q §i celeale programarii generice considera aceasta biblioteca un instrument foarte eficient,care creste semnificativ productivitatea lor in dezvoltarea aplicatiilor.

Structura STL este aproape in intregime creatia lui Alexander Stepanov, care ainceput sa puna in practica primelc sale idei referltoare 1a programarea generics in1979 (acelasi an in care Bjarne Stroustrup a inceput sa elaboreze C++). Prmcipalulcolaborator a1 lui Alexander Stepanov a fost David Musser, care promova principiileprograrnarii generice inca de Ia Incepurul anilor '70. Initial, biblioteca a fost conceputapentru limbajul ADA, dar nu s-a bucurat de succes in industria software, Ulterior,biblioteca a fast implementata in C++, datorita facilitatilor pe .care aeest limbaj Ieofera pentru programarea generlca eficienta. in 1992, Meng Lee. a fost cooptat inproiect si, impreuna, aureu~it sa finaIizeze biblioteca STL, conform cerinjelorcomitetului pentru standardizarea ANSI/ISO a limbajului C++. La ora actuala, STLface parte din bibliotecile standard ale JimbajuJui C+ + ~i producatorii decompilatcare includ STL in produsele pe care Ie distribuie.

STL contine elase container, algoritmi generici, iteratori, funcrori, adaptori ~i alo­carori. Yom face 0 prezentare generals pentru fiecare categoric, urrnand ca in capite­lele urmatoare sa analizam in detaliu clasele container. Nu ne propunem 0 abordareexhaustiva a bibliotecii STL. Dorim sa realizarn tnsa 0 abordare opcratlonala. Scopulnostru este formarea unei viziuni de ansamblu asupra biblioteciiSTL, impreuna cu 0

profunda tntelcgere a conceptelor care stau la baza consrruir ii acesteia, prccum ~i

Iormarea unor abilitati de utilizarc avizata a eomponenteJor STL pentru rczolvareaunor probl erne de Jactura algorunuca.

o documentatie complcra ~i foarte bine structurata pcntru biblioteca STL poate fconsultata online la adresa http://www.sgLGom!tcQh/stl. Yeti. considera utili1 sidocumentatia STL inclusa ill docurnentatia pentru limbajul C++ 13 adresahttp://www .cpiusplus.eom/refcrence/stl.

-i

-"

Page 55: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

108 PROGRAMAREA IN LIMBAJUL etc -H PENTRU LICEU

~.",.;

STL. CONCEPTE GENERALE 109

~~

r

r-

r-r-

r

,4

-,

4.2. Clasele container

Un container este un obiecr care contine 0 colectie de alre obiecte , denumiteelernenrele containerului, in tuncue de modul de organizare a elementejor , in STLexists doua categorii de clase comainer :

• containere secventiale (sequence containers) - contln 0 succesiune de clemente deacelasi tip T; containerele secventiale din STL sunt vector, deque st list; inC+ + 11 au fost introduse inca doua containere secvenuale : array siforward_list;

• containere asociative (associative containers) ~ permit accesul rapid la clemente,prin intermediul unor chei; containerclc asociative sortate din STL sunt set,multiset, map si multimap; in C++ 11 au fost introduse §i containereleasociative nesortate : unordered_set, unordered_mul ti set, unor-deredjnep§i urio.r-de r-e djmuLtimap.

Practic, containerele implementcaza diferite strucruri de date. in functie de pro­blema pe care trebuie sa 0 rezolvati pentru a obtine 0 implementare eficienta, trebuiesa alegeti clasa container adecvata.

Utilizarea claselor container

Clasele container dispun, in mod unitar , de 0 serie de funcpl membre ~i operatorisupraincarcan. in functie de container, evident, exists ~i alte functii si opcratoridisponibili, specifice ctasei. Prezentam in continuare cateva exemple.

Tipurile definite in clase container

Grice class container din STL defineste in mod public urruaroarele tipuri :

Tip Semnlflcatic

value type Tipul elerncntelor eontaineruluipointer Pointer eu tipul de baza veLuej t ype (T*) - contine adresa unui

element al containerului .reference Refertnja ell tipul de baza value type (T&)iterator Tipul iteratoruluidifference type Tip intreg, reprezentand tipu! rezultarului difercnjci dintrc doi itcratorisize t.ype Tip imreg pozitiv, care rcprezima tipul dimcnsiunii unci zone de memoriereverse~iterator Tipul iteratorulul invers

Tipurile pointer, reference, i.terator si reverse_iterator au definitesi versiuuilc constante (const-pointer, ccnatjreterence, cons t j i t er-a t o r~i canst~reverse_iterator). Versiunile constantc nu permit modificarea ele­rnentului indicat. Existenta versiunilor constante nu este doar 0 masura de securitate,ci 0 necesitate, deoarece In functii canst pot fi utilizate doar versiuni canst.

Constructorii si destructoru.l

Teare clasele container au un constructor implicit (constructor tad! parametri), unconstructor bazat pe un domeniu (prirneste ca parametri prim -care indica primulelement -al domeniului - ~i ul tim - care indica pozitia de dupa ultimul element aldomeniului; acesr constructor creeaza un container ~i Il mitializeaza cu obiectele dindomeniul [prim, ul tim)), un constructor de copiere ~i un destructor,

Operatorul de atribuire

Pentru toate clasele container este supraincarcar operatorul de atribuire =:.

Functiile membre referitoare la dimensiunea containerului

Clasele container contln trei functii membre care se refera la dimensiune :• size () - rerumcaza numarul actual de clemente din container;

empty () - rerurucaza 0 valoarc de tip bool {t r-ue pentru un container vid ,adica un container pentru care size () ==-0 §i false in caz contrar) ;

• rnax jsiae () - returneaza numarul maxim de elememe ce pot fi stocate incontainer.

Interschimbarea a dOUG containere

Interschimbarea a doua containere se poate realiza prin intermediul functieiswap () care poate fi definita arar ca functie membra, cat ~i ca functie ncmcmbra(algoritrn). Fie cl si c2 doua containere. Interschimbarea lor prin intennediulfunctiei swap () se realizeaza astfel :

cl.swap(c2l; //functia membra swap()swap(cl,c2); //functia nemembra swap{)

lnserarea elementelor intr-un container

ClaseJe container dispun de funcpa membra insert ( ). care permite inserareaunui element inrr-un container sau a unui domeniu de elemente Intr-un container,

Ellminarea elementelor dintr-un. container

Functia membra erase (') permite eliminarea unui element specificat dintr-uncontainer sau a elerncntelor dintr-un domeniu specificat. Exista ~i functia membraclear () , care determina stergerea tuturor elementelor din container.

4.3. Clasele adaptor pentru containere

Clasele adaptor pentru comainere sunt definite pe baza unci alte clase container,asigurand 0 functionalitate resrransa pentru aceasta. Exists trei clase adaptor prede­finite in. STL, bazate pc containere secventiale : stack (stiva), queue (coada) ~I

prLc r i t.yi qu eoe (coada cu priorirate).

Page 56: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

~\1:

template<class T>cl.ass Iteratar(

public:

Iteratorii permit accesul la elementele unui container, independent de modul incare aceste elemente sunt stocate.

Jteratorf sunt asemanatorl cu pointerii. Mai exact, iteratorii sunt 0 generalizare apointerilor, fiind obiecte care .indica (point) alte obiecte.

Fiecare clasa container are definiti iteratorii proprii. Declarana unui iterator itpentru clasa container CC<T> este:

~ CC<T>: : i terator it;

(i t permite accesul Ia elementele containerului CC<T> pentru citire si scriere)

r CC<T>:: const_i terata}:" it;

(it permite accesulla elementele containerului CC<T> pentru doar pentru citire)

o declarare schematica a clasei Iterator este:

II constructari, destructorboel operator=={censt Iterator<T>&) const;heel operator!=(const Iteratar<T>&) const;Iterator<T>& operator++(); II prefixatIterator<T> operator++(int) II postfixatT& operator*{) const;T* operator->{) const;

private:} ;

Din schema precedents deducem ca orice iteratcr perrnite urmatoarele opcratii :

comparani (cu ajutorul operatorilor supratncarcatt == $i ! =);incrementare (utilizfmd operatorul supraincarcat ++, atat In forma prefixata, cat $iin forma posrfixara) ; ~

dereferentiere (cu ajutorul operatorului de dereferentiere * poate fi accesatelementul indicat de un iterator, asemanaror cu dereferentierea pointerilor) ;selectie Indirecta (cu ajutorul operatorul de selecjie indirecta -> se poate selecta unmembru al obiectului indica! de iterator, prin intermediul iteratorului;functionalitatea acestui operator este sirnilara cu eea din cazul pointerilor).

ClaseJe container con tin functii mcmbrc necesare iteratorilor pentru pareurgereaelementelor :

functia begin () rcturneaza un iterator care indica primul element al conral­nerului :functia end () returncaza un iterater care indica pozitia de dupa ultimuI elemental contail1crului.

Observaiii

1. Iterarorf de intrare permit ciurea datelor dintr-o sccventa (priutr-o singura par­curgere), in timp de iteratorii de iesire permit doar scrierea vaJorilor tmr-osecventa (de asemenea printr-o singura parcurgere).

2. Ireratorii de inaintarc permit atat accesul la elementele eontainerului pcntru citire ,cat ~j pentru sericre; permit parcurgerca unei sec vente doar Intr-un singur scns ,Insa, spre deosebire de iteratorii de jnrrarc/Iesire. elementele containerulu i pot tlparcursc de mai mulrc ori. Jtcratoru bidirecdonali sunt similari cu cei 'de inainrare.numai ca permit in plus parcurgerea secventei in sens opus (cu operatorul ~-).

i~

I

-!

-1

,,~

':i

....J

,

'~

-

~

~

IIISTL. CONCEPTE GENERALE

Observatii

1. Domeniul unui iterator poate fi deflnit cu ajutorul functiilor begin () $i end ( )astfel: [begin () , end () ) .

2. Domeniul unui iteraror este vid (contaiuerul nu contine clemente) dacabegin ( ) ==end ( ) .

3. Pentru a parcurge elementele unui container Cob de tip CC<T>, utilizam uniterator it, pe care 1I initializam cu ajutorul functiei begin () ; cat timp n11 amparcurs roate elementele (it! =end (), iteratorul este incrementat :

CC<T> Cob;CC<T>: :iterator it;fer (it=Cob.begin{); it!= Cob.end(}; ++it)

in funcpe de operatiile ce pot fi efectuare eu Ireratorii, in STL exists cincicategorri de iteratori. TabeJul urrnator ilusrreaza pentru fiecare categoric de iteratori :

modul in care iteratorul poate aceesa elementele containerului (pentru citire : * i t

sau it->membru, tara a fi utilizat in membruI stang al unei atribuiri ; pentruscriere: * i t.eve Loe.re, adica utilizat doar in membrul stang al unci atribu iri ;respectiv pentru citire si scricre) ;sensu] in care se poate realiza parcurgerea elementelor containerului (doar inainteeli ajurorul operatorului ++, in ambele sensuri cu operatorii +-i- $i --, rcspecrivdaca este permis accesu1 direct [aleatoriuj la .elemenrele containerului).

Itcratori Opcraju pcrmisc Clasc asoclate

Iteratori de intrare Acccs pentru citire istream

(input ituerators) Parcurgere inainte

Iteratori de iesire Acces peruru scricre ostream, inserter

(output iterators) Parcurgcre inainte

Iteratori de lnaintare Acces pentru citire §i scricre(forward iteraiors) Parcurgere inainte

Iterarori bidirecrionali Acces pentru citire sl scriere list, set,

(bidirectional isercuors) Parcurgere in ambele sensuri multiset, map.multimap

Iteratori cu acces aleatoriu Acces pentru cirirc §i scrierc vector, deque,

(random access iteratorsv Acces direct (aleatoriu) string, array

PROGRAMAREA iN LIMBAJUL CIC++ PENTRU LICEU

4.4. Iteratorii

110

Page 57: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

r-

r-

<i"""

SlL CONcEvrE GENERALE In~

-

Pentru a putea fi parcurse cu un iterator invers, clasele container contin doua

funetH membre sirnilare cu begin () ~i end ( ) . Acestea sunt:

- rbegin () - returneaza un itcrator care indica ultimul element al comainerului(aeeasta este pozitia de la care incepc 0 pareurgere inversa) :

- rend () - returncaza un iterator care indica poztna dinainie de primul element a1containerului (aici se termina 0 parcurgere inversa).

Pentruun r-ever s e j i.c e ret or-, operatoril de incrementare st decrementare se,comporta invers. Prin urmare, iata cum se implcmenreaza parcurgerea in ordineinversa a elementelor unui container Cob de tip CC<T> cu ajutorul iterarorului invers

rd t :

CC<'l'> Cobj

CC<T>: :reverse~iterator ritj

for (rit=Cob.rbegin() ; ritl= Cob. rend ( ) j ++rit) ..

Iteratorul de inserare

Iteratorii de inserarc sunt adaptor! care rransforma un iterator de iesire asrfel meatIa 0 atribuire de tipul "* .i.t=valoare nu va fi suprascrls un clement al coutainerului,

.ci este inserata in container valoarea specificate. 0 alta caracterisrica a iteratot-ilor de

.inserare esre d'i operatorul de incrementare ++ nu are niciun cfect (nu mcdiflcaiteratorul) .

in STLsunt definite 3 categorii de iteratori de inserare :

Iterator Erectback_insert_iterator Insereaza valoarea Ia sfarsirul containcrului

Disponibil pentru c1ascle vector, deque, list §i stringfront_insert_ iterator lnscreaza valoarea la inccpurul comainerului

Disponibil pentru clasele deque §i list:

insert_iterator Insereaza valoarea intr-o pozijic spcctficata (utilizand functlainsert a containerului)

Iteratorul pentru flux

Un iterator pentru flux (st r-eemo.cera t or-) este un adaptor utilizat pentrucitirea(istream_iterator) sau scrierea (o s t r-eemj i t ere r.cc-) Iutr-un flux.

iteratori cuacces aleatoriu

iteratoribidirectionali

Iteratori deinaintare

PROGRAMAREA iN LIMBAJUL C/C ++ PENTRU LlCEU

iterateri de ie~ire

iteratori de intrare

J 12

Operator Sintaxa Erect

lndexare it[n] Acces la elemcmul de pe pozitia n

Adunare cu intreg it+n Iterator care indica a1 n-lea element urmator (pcntru nn+it pozitiv) sau precedent (pentru n negativ)

Scadere cu Intreg it-n Iterator care indica al n-lea element precedent (pentru npozitiv) sau urmatcr (pentru n negativ)

Atribuire compus cu it+-n Iteratorul it va indica al n-Ica clement urmaror (penttu nadunare pozitiv) sau precedent (pcntru n negativ)

Atribuire com pus eu it--n Iterator it va indica al n-lea element precedenr (pentru nscad ere pozitiv) sau urrnator (pentru n ncgativ)

Scaderea a doi itl-it2 Rerurncaza un numar intreg reprezentand distanta dintreiteratori doi iteratori (numarul de clemente din domeniul determinar

de cei doi itcratori)

Operatori relationali itl<it2 Rctumeaza 0 valoare bool indicand daca elememulitl>it2 indicat de itl preccda clemcnrul indicat de it2 «);

it:i<=it efect similar pentru >, >,~, <"".

itl>=it2

4.5. Clasele adaptor pentru iteratori

Iteratorul invers [revers ej i Cera t.o.c}

o clasa adaptor pentru iteratori este 0 clasa sablon care schimba modul defunctionare a unui iterator.

4. Analizand operatiile disponibile pentru fiecare categoric de iteratori, deducem 0

ierarhizare a iteratorflor :

3, Iteratorii cu acces alcatoriu suporra toate operariile perrnise pentru operatorilbidirectionali ; in plus, sunt supraincarcati operatorii care' permit accesul direct laelementele containerului :

r-

~ Orice iterator eu acces aleatoriu este ~l iterator bidirectional; orice iterator!' bidirectional este si iterator de Inaintare ; orice iterator de inaintare este iterator

de Intrarc/iesire.

,!,

in ·STL esre defirrit. adaptoruJ r eve.rs ejLter-accc- -(iterator inver's); carer transforms un iterator bidirectional sau un iterator cu acces aleatoriu inrr-un iterator1 care perrnite parcurgerea eleruentelor unui container in ordine inverse.

r-

Page 58: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

.~'(::,.;:,;",

114 PROGRAMAREA IN LIMBAJUL C/C++ PENTRlJ LlCEU STL. CONCEPTE GENERALE 115

4.6. Functorii 4.7. Clasele adaptor pentru functori

4.8. Algoritmii

Ca.si in cazul containerelor ~i iteratorjlor, exista adaptori pentru funcrori , care auca scop cresterea flexibiliratii in utilizare a functorilor predefiniti.

De exemplu, exisra doi adaptori de legarura (binder) care .Jcaga" unul dintreparametrii unui functor cu doi parametri, fixandu-l pe 0 anumita valoare. Cu ajutorulacestor adaptori, un functor binar poate fi utilizat ca functor unar. Cei doi adaptoride tip binder sunt bindlst si bind2nd ("leaga" primul, respectiv al doileaparametru) .

A1goritmii sunt functii generice (sablon), care nu apartin claselor container §i care[mplementeaza 0 serie de prclucrart fundamentale asupra eIementelor containerelcr,[ndiferent de tipul acestora.

Exceptand a1goritmii nurnerici, pentru a utiliza algoritmii predefiniti in STL,irebuie sa mcluden fisierul antet algori t.hm :

-] #include <algorithm>

Algoritmii interactioneaza cu elementele conrainerelor prin intermediul iteratorilor :

Algoritmii au ca pararnetri iteratori §i functori. De exemplu, de multe ori unalgorttm prelucreaza un anumit domeniu (range) de clemente ale unui container. Unastfel de domeniu este definit de doi iteratori (prim ~i ul tim) §i reprezinta toateelemcntele tnccpand de 1a elementul indicat de iteratorul prim (inclusiv acesta), panaIa elementul indicat de iteratorul ul tim (exclusiv acesta). Un astfel de domeniu estenotat [prim, 'u I tim). De asemenea, cand se specifica pozitia de inceput a unuidomeniu, aceasta se precizeaza prin intermediul unui iterator. Un alt exemplufreevent intalnir sunt algoritmii care verifica 0 _anumita conditie pentru elementelecontainerului (conditia aceasta este transmisa ca pararnetru printr-un functor. curezultat booI, adica un predicat).

In functie de prclucranle realizare, algoritmii predefiniti din STL pot fi clasati in10 categorii. Unii dintre acesti algoritmi sunt disponibili doar incepand cu C+ + II.Pentru a in9.i~a acest lucru, mcnjionam (ll) dupa numele algoritmulul.

'--'

~

'-..J

,

c.J

-i

.,J

, ii~

ContainereIrcraroriAlgoritmi

Functorii aritmetici sunt binari §i rcaltzeaza operatia arinnetica specificate prinnumele lor asupra eelor doi parametri, returnand rezultatul operatiei. Acestia sunt:p Lus (pentru adunare eu operatorul -), minus (pentru scadere cu operatorul -),muLtiplies (pentru inmultire ell operatorul -), divides (pentru impartirc eu I),modulus (pentru restul impartir» eu operatorul %).

Exista si un functor aritmetic unar denumit negate (schimba semnul algebric alargurnentului sau.rutilizand operatoru1 unar -).

Un functor (obiect functle) este un object al unci clase care are supraincarcatoperatorul (), denumit operatorul apel de functie.

Sa notam ell x 0 astfel de clasa ~i Xob un obiect al acestei clase. In cazul in careoperatorul () este supralncarcat pentru clasa x, putem utiliza constructia xob ( ... ),in paranteze fiind specificata lista parametrilor operatorului (). Aceasta construqj,rcprezinta un apel al operatorului () pentru obiectul Xob. Lista parametrilor poate fivida (functor generator) sau poate confine un parametru (functor unar), doi parametri(functor binar) sau oricati parametri sunt necesari.

o categoric speciala de functori sunt predicatete, acestea fiind functori (unari saubinari) care returneazao valoare de tip bool.

in C sau c+ + nu este posibil sa transmiti unei functii ca pararnetru 0 altafunctie, Este tnsa posibil sa fie transmis un pointer de functie (pointer care contineadresa unei functii). Funcrorii corespund pointerilor de functii din limbajul C.

in STL sunt predefinite mai multe categorii de functori. Pentru a utilize acest;functori, trebuie sa includeti flsierul antet functional:

#include <functional>

Functori aritmetici

Functori de comparare

Functorii de comparare sunt binari §i returneaza WI rezultat de tip bool:equal_to (pentru egalitate cu operatorul ==), not_equal_to (pentru neegalitateeu operatorul ! =), less (rnai mic), greater (mai mare), Les s tecua I (mai micsau ega!), greater_equal (mai ma:;-e sau egal).

Functori pentru opera/if logice

in STL exists predefiniti trei functori pentru operant logice: log::,cal~not(functor unar pentru negatia loglca cu operatorul ! a parametrului sau), logica.l_and(functor binar pcntru conjunctia logica eu operatorul && a ector doi parametri) ~i

logical~or (pentru disjuneIia logica a celor doi paramctri utiJizand opcratorul I I).

,~

Page 59: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

Ii 7

care indeplincse 0 anurniUi con. II

"" ._---._--._-STL. CONCEPTE GENERALE

rC-6'~i-a-;; -~I~~~;1~~i~ -di~t-r'-~;l- -d-b,-,;cniu

ditie intr-o poziue speclficata

lncepano eu 0 pozhie speciflcata, se atribuie primelor n clemente valo­rile generate succesiv de un .gencrator specificai ca parametru

Jnterschimba valorilc a doua obiccre. Penrru swap sum transmise caparametri rcfcrinjc la obiecrele care sc interschirnba ; penrru i t.er_swapsunt rransrnisi ca parametri ireratori care indica po ziti a elemente]or carese interschirnba

Atribuie 0 valoare tuturor elcmemelor dintr-un domeniu

Incepand cu 0 pozitic specificata, se atribuie prlmelor n clemente 0valoare speciflcara.

Intcrschimba valorile dintr-un domeniu cu valorile unui alt domeniu,care Incepe la 0 pozitie specificata

Sterge dintr-un dcrneniu toate clementele egale cu 0 anumita valoare,respectiv care indeplinesc 0 anum ita conditie

Prelucrcaza elementele dinrr-un domeniu (dad prelucrarca esre 0

functie unara) sau din doua domenii (daca prelucrarea estc 0 functlcbinara) !?i stocheaza rezultarul prclucrarii trur-o pozitic spccificata

Inlocuicste toate elernentele dintr-un domeniu egale cu 0 anumiravaloarc, respectiv care indeplinesc 0 anumita conditio eu 0 alta valoare

Efect similar cu replace, rcspectiv replace_if, doar cii rezultatu!obttnut este copiat iucepand eu 0 pozltie spccificata

Arribulc elemeruelor dintr-un domeniu valori generate succesiv de ungenerator (functor tara parametri)

Efect similar cu remove, respectiv remove_if, numai di rczultatuleste eopiat incepiind cu 0 anumita pozi!ic

Daca exista iotr-un domeniu succesiuni de clemente cgale, respectivcare indeplincse a anumita conditie, situatc pc pozi~ii consecutive, seclimina aeeste sucecsiuni, pastrand doar primul element.

lnverseaza ordinea elementelor dintr-un domelliu. Rezultatul sc obtinein acela!?i domeniu, rcspectiv se copiw...1. inccpand eu 0 pozi!ie speeificata

Realizeazi:i 0 rotatie spre stanga cu un anum it numar de po:lilii a ele­mentelor dintr-un domeniu

Rearanjeaza in mod aleatoriu elemcmele unui domcniu

Rcaranjcaza in mod alcatoriu clememc1c ullui domcniu utilizimd ungenerator

remove

generate

generate n

replace_copy

replace~copy_if

remove_if

(] ! :move

move.Lbe ckwec-d (J 11

swap_ranges

swap

it.er_swap

transform

fill

fill~n

replace

replace_if

copy_if(jll

remove_copy

remove_copy_if

unique

unique_copy.

reverse

reverse_copy

rotate_copy

rotat.e

random_shuffle

shuffle(l.1lCopiaza (in ordine, rcspcctiv in ordinc illversa) clcmentclc unui domeniu imr-o pozitic specificatil

Copia7.1i primele n clemente' inccpand eu 0 pozi\ic specifieatii "Ia 0 aWl.POZ.iiic specificaui

py

copy_backward

copy_n i l l

,

ll(l PROGRAMAR,EA iN LlMBAJUL e/c., + PENTRU LICEi.;

Algoritmii care nu modified elementele containerului

Acesti algoritmi realizcaza In general verlflcari ale clcmcntclor dintr-un domeniu,in functie de 0 anurnita conditio. Conditia poate fi ca elementele sa fie egale sau ca.un anumit predicat (transmis ca parametru) sa aiba valoarea true.

Algoritm Efectall_of Ill) Vertfica dad! toate elementele dintr-un domeniu verifica 0 anumira conditieany_of (1] l Veriflca daca exista un element intr-un domeniu care vcrtfica 0 anurruraconditienone_of.(ll! Verifies daca niciun element dintr-un domeniu nu vertfica 0 anumita conditiofor each Aplidi. 0 anumita functie pcntru fiecare element dintr-un domeniufind, find_if, Cauta 0 valoare care Indcplineste 0 anumita conditie Intr-un domeniufind_if_not(111,find_end,find_first_of

adjacent_find Cauta lntr-un domeniu doua valori care indeplinesc 0 anumita conditie,aflate pc pozitii consecutive

count Determina numarul de apariui ale unei valori intr-un domcniucount_lf Deterrnina numarul de valori care indeplinesc 0 anumita conditie dintr-un

domeniu

mismatch Parcurge in ordine clernentele a doua domcnii !?i determine prima pozttiepentru care elementcle de pe pozitia respccuva nu se "potrivesc" (nulndeplinesc 0 anumitf conditio)

equal Parcurge In ordine elementele a doua domenii !?i verifies daca elcmentelecorespondente din cele doua domenii se .pomvesc" (indeplincsc 0 anumiraconditie)

is-permutation Verifica dad un domeniu cste 0 permutare a unu] alt domeniu(11 )

search Cauta prima "potrivire" (in functie de 0 anumita conditie) a unui sub-domeniu Intr-un domeniu

search_n Cauti'i hur-un domeniu prima -aparitic a unci suceesiuni de n valori conse~ Icutivc care indepJinesc 0 anumil1i condilie.

.Algorltmil care modified elementele eontalnerului

Ace~ti algoritmi apliea 0 anumitii pre]uerare elementelor dimr-un domeniu (sau aprimelor n clemente incepand eu 0' pozitie specifiealli - variantele a1 diror, l1umeconIine _n); rezultatul se obtine in domeniul initial sau se copiaza intr-un altdomeniu identificat doar prin pozitia de inceput (variamele

- copy).

I . Algoritm

IErect I

Icopy

r

r

ii

Ii

-

: ', ,

I •

.-

r,,

-..

i

.-

1-

r:

Page 60: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

r-

118 PROGRAMAREA IN LIMBAJUL etc ++ PENTRU UCEU stt.. CONCEPTE GENERALE 119

,

cJ

Algoritmii de partitionare

Acesti algoritmi impart un domeniu in doua subdornenii (primul subdomeniu esteformat din elementele pentru care predicatul transmis ca parametru rerurneazavaloarea true, iar eel de-al doilea subdorneniu este format din elementele pentrucare predicatul rerumeaza valoarea false).

Algoritmii de cautare binaraAlgor itmii din aceasta categorie acrloneaza asupra unui domeniu ordonat. Si in

acest caz pentru compararea a doua elemente se utilizeaza operatorul implicit == sau 0

functie de comparare spectficata ca parametru.

Algoritmii de lucru cu multimiAcesti algoritmi lucreaza cu domenii ordonate. Domeniile obtinute ca rezultat SUIlt

de asemenea ordonate. Ordonarea elementelor se face considcrand implicit operatorul< sau 0 functie de comparare spcclflcata ca parametru.

i~

,

....:

r .~

..J

....:

LJ

Interclascaza elemeruele unui domeniu cu elemenrele unui altdomeniu. copiind rezuhatul incepand eu 0 pozitic spccificata

Erect

Retumcaza un iterator care indica pozitia primului element din domeniul specificatcare nu cste mai mic. respectiv cste mai mare decat 0 valoare specificata

Cauta binar 0 valoare intr-un domeniu specificat si returneaza true in cazulin care valoarea exista in domeniu, rcspectiv false in caz contrar

Erect

Returneaza pentru un domeniu specificat, subdorneniul format numai dinelementc egale eu 0 valoare specificate (subdomeniul fiind idcntificar printr-opereehe de lteraron : prlmul indicand pozitia de tnceput, al doilea pozitia desfar~it)

equal_range

Algorttm

lower_boundupper_bound

binary_search

merge

Algoritm

Copiaza la 0 anumita pozirie elementele dintr-un domcniu pcnrru carepredicatul spccificat ca parametru rcturneaza true, iar la alta pozitieelementcle pentru care predieatul retumeaza false

Efectul esrc similar ell partition, numai ca se garanteaza caordinca inijiala a elementelor din fiecare domeniu se pastreazf

Retumeaza true dad elemenrele unui dorneniu sunt partitionate inmaniera descrisa la parti t ion

Returncaza un iterator care indica pozitia primului element dirur-undomeniu speeificat pentru care predicarul nu retumeaza true. Seconsiders ca domeniul a fosr deja partijionat

Rearanjeaza elementele dintr-un domeniu astfel incat elementelcpemru care predicatul specifieat ca parametru returneaza true sumplasate inaintea elementelor pentru care prcdicatul returncaza false;retumeaza ea rezultat un itcrator Care indica inceputul cclui de-al doi­lea subdomcniu

Erect

is_oarti tioned (lll

Algoritm

parti tion_copy(lll

partition

stable-partition

partition-po i n t(11 )

Algoritmii de ordonare

Acesti algoritmi ordoneaza sau verifies ordinea elementelor unui domeniu ;pentru eompararea a doua clemente se utilizeaza operatorul = sau 0 functie de COll1­

parare specificata ca parametru.

Algoritmii de lucru cu heap-uriIn accasta categorie sunt inclusi algoritmii fundamentali de lucru eu heap-uri,

algoriuni care vor fi apelati §i de adaptorul priori ty_queue. Pentru compararea adoua elemente se utilizeaza implicit operatorul < sau 0 functie de comparare speci­ficata ca parametru.

Considerand di elementelc din domeniul [prim, ultim-l) constituieun heajJ, sc rearanjcaza clcmentcle_din domeniul [prim, ultim) aSlfclindi.t sa constituie un heap (praclic, se extinde un heap, prill inserarca

_____ __ .,_~J_c_r:1~1ll~.J~i _i:~~~~~~ ~_r!l:~~,?~~ .. . ___ __. __ __. . .

~

,

~

'-'

~

-'

Erect

Jnterclascaza domeniul [prim, mij) cu domeniuJ [mij,ul tim), obtinand rezultann lntcrclasarf in domeniul[prim,ultim)

lncluziunc : vcnfica daca toate elementele unu i domcniu apar­~in unui alt domeniu

Construieste la 0 pozitie speciflcata un domeniu care este rezul­tatul reuniunti. intersccttei, diferenjei, respectiv diferentei sime­trice a doua domenii

Rearanjeaza elemcmeJe dilltr-un domeniu astfel ineat sa constituie un heap

Algoritm

inplace_merge

includes

set_unionset_intersectionset_differenceset_symetric_difference

push_heapmake heap

i _

Realizeaza 0 ordonare parpala a elcmcntelor dintr-un domeniu.Rezultatul se obtine in acelasi domcniu, respcctiv se copiaza intr-unalt domeniu

Ordoneaza elementelc dintr-un domeniu

Ordoneaza elementelc dintr-un domcniu , garantand di elornenteleechivalente i§i pastreaza brdlnea initiala

Rcaranjeaza elemcntele dintr-un domcniu astfel fneat al n-Jea ele­ment (considerand clementele surtate) sa fic pc pozilia sa eurectiC .elc1l1entele mai mici decal el fiind plasalc inairllea sa ~

Rcturneaza true daca elememele dintr-un anumit domeniu suntordonate

Returneaza un iterator care indica pozi!ia primului clement carenu este in ordine hHT-un domeniu specificat

~s_sorted_untilon

is_sorted Ill)

Sort

stable_sort

Algoritm

nth_element

partial_sortpartial_sort_copy

Page 61: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

'''I'''

'10 ;';~.:::;.:;;:;,:.;:,;~:::.::,' ':""::vJBAJUL C/C; ;-;::;;·;·:~V •••~._~sn.. CONCEPTE GENERALE 121

pop_heap

sort_heap

. _."'''' - _...... -- - - ... --Se extragc din heap~uJ aflat in domeniul [prim, ul tim) primul.element ~i cste lnterschirnbat eu ctemcntul de pc pozitia indicata deul t.Lrn-. 1, apoi heap-us estc restrucrurar astfel incat elcrneutelc ramase indomcniul [prim, tz Lt d.rn-e L} sa consdtuic un heap

Sorteaza elementelc dintr-un domcniu organizat caun heap

Algoritmii numeric!Algoritmii numerici realizeaza prelucrari ale unor secvente numerice. Pentru a

utiliza aceasra categorie de algoritmi trebuie sa includern fisierul antet rrume r i c.

Algoritmii de maximum/minimum

Acesti algoritmi determine eel mai mic/mare element dintr-un domeniu, returnamjfie 0 referinta, fie un iterator care indica pozttia acestuia. Pentru compararea a douaclemente se utilizeaza implicit operatorul < sau 0 functie de comparare specificata caparametru.

rmi~~xl;l;

is__heap'11)

4.9. Clasa ~ablon pair

Algoritm Erect

accumulate Implicit, insumeazii ejcmeruele dintr-un anumit domcniu. Dad. cstespecif'icata. executa 0 alta operatic in loe de adunarc cu elcmcmclc

din domcniu

adjacent_difference Implicit, determina sirul ditercntelor dintre elementele consecutiveale unui domeniu. Dad!. cste specificata, executa 0 alta opcraue inIoc de scad ere eu elcmenrele din domeniu

inner--product Implicit, dcicnnina suma produselor dintrc elcmentele corespondentca doua domcnii. Bste posibila specificarca altar operajii in loc de suma

~i produs

partial_sum Implicit, calculeaza suul surnelor partlale ale elementelor unui dome-niu. Este posibila specificarca unci altc operatii in loc de adunare

iota ill)Construiestc 0 secvcnta crcscaroare de valori consecutive, Incepandcu 0 vajoare specificateEJect

Rcturncaza 0 pereche (pair) in care primul element estc minirnul. Jaral doilea element estc ruaximul dintr-un domcniu

Rctumeaz..'l 0 rcrertma carre cca mai mica. rcspecriv cea mai marevaloare dintr-un domcniu spcciflcar

Rctumeaza true dad elcrnentclc dintr-un domeniu specificat constituj,un heap, respectiv false in caz contrar

Rcturucaza un ueraror care indica pozina primului element dintr-undomcniu specificar eare Incalca proprletatea de neap

Algoritm

is_heap_until (ll)

I

Imi n

max

rII ,

j

i

L :

I

Algoritmii referitori la ordonarea lexicografica

Xi=Yi, pentru once i=l. k-l :;;i fie Xk<Yk, fie ke-rr. PC11tru coinpararea a douaelemente, se utilizeaza implicit operatoru! < sau 0 funqie de eomparare specificata caparametru. a

Algoritm Efect

lexicographical_compare Functia returneaza un rezultat de lip bool care indica daeaprimul domcniu specificat ca parametru preceda lcxicografical doilea domcniu spccificat ca paramctru

next_permutation FUIJqia rcaranjeaza clcmcntele unui dorncniu astfel incat saprev--permutatl0n reprezinlC pennutarea imedia! unnaloare/precedcnt:1, in ordine

lexicografica. Functia rcturnca:di t:r.-ue daca rearanjarea af?sl posibilii, respectiv f<=:.lse in caz contrar

Spunem di 0 secventa x= (Xl, X2,

vedere lexicografic 0 secventa Y= (Yl," Y2,

ObservatieIn declaratie am utilizat cuvantul-cheie st.ruct. in c+ + tipul struct esrc similar

cu tipul class, diferenta consmnd In fapm! di toti mcmbrii tipului struct sunt publici.

Defini[ia clasei pairtemplate~<class Tl. class T2>struct pair{/Idate membreTl first;T2 second;Ilconstructor implicitpair (): first (Tl () ), second ('1'2 ()) {}

Ilconstructor Cli doi parametripair(const Tl& a. const T2& b): firstla) second (b) {}Ilconstructo:r- de copiere cu conversie implici t.atemplate<class U,class v> pair{const pair<U,V>& p):first{p.first) second(p.second} {}

};

Deoarece apare frecvcnt necesitatea de a lucra ell 0 perechc de valori , a fosrpredefinita in biblioteca STL clasa sablon pair. Pentru a utilize clasa pair trebuie

sa lncludern fisieru! antet utility.

Declaratia clasei pairtemplate <class 'P'I • class r1'2> struct p a.i r i

X n ) preceda (este mai midi) din punet de... , Ym) daca exista un indice k astfel tncat

Rcturneazii 0 pcreche de iterator-i (pair) in care primul element indicaruinimul. lar al doilca element indica maximul

Rcrurncaza un ucrator care indica pozijia cclui mai mic/marc elementdintr-un domeniu spectflcat

minrnax_eleme.nt1111

min_element:

Imax_element

r

,~

-

r

r

r

":',. ;

r

Page 62: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

122 PROGRAMAREA IN LIMBAHJL CIC++ PENTRU L1CEU STL. CONCEPTE GENERALE 123

, 1,

-J

, 1

Observajii

1. Clasa pair continc doua date membre publice: first $i second, avand tipulTl, respectiv 'r2.

2. Clasa pair are doi constructor! (constructorul implicit si construcrorul delnitializare care construieste 0 pereche pe baza a doua valori specificate caparametru) §1 un constructor de copiere.

3. Des! nil sunt explicit dcfiniu in cadrul clasei, compilatorul gcncreaza automatdestructorul §i supraincarca operatorul de atribuire ,

4. lncepand Cll C++ 11, in clasa pair a fast inclusa functia membra swap, careinterschimba first cu second.

Functia make-pair ( )

Functia sablon makejjaa.i r- permite construirea unei perechi pe baza a douavalori specificate ca parametru, astfel :

temp~ate <class Tl,class T2>pair<Tl,T2> make---.J)air (Tl x, T2 y){ return ( pair<Tl,T2> (x,y) };

Operatorii de egalitate si operatorii relcqionali

Operatorii de egalitate §i operatorii relational! sunt supratncarcati pentru afunctiona cu perechi. Yom detalia doar operatorul == $i operatorul <, dcoarecesemnificatia celorlalti operatori poate fi descrisa eu ajutorul acestora.

Operatorul de egalitate ==0=

template <class Ti, class T2>bool ope.ra t oxvv (const pair<Tl, '1'2>& a, const pair<'T'l,T2>& b);

Perechea a estc cgala eu perechea b (a,.o;~,:b) dad! a. f Lr-ss t e-e-b . first. sla.second==b.second.

Operatorul relational <

template <class Tl, class T2>beel operator«const pair<Tl,T2>& a,const paiY<Tl,T2>& b);

Compararea a doua perechi se realizeaza din punct de vedere lexicografic. Maiexact, percchea a este mai mica dedit perechea b (a-cb) daca a.first<b.firstsau a. first==b. first ~i a . second<b. second.

Exemplu

In exemplul urmator vom dernonstra modul de utilizare a constructorilor, a functie!make---.J)ai r- () ~j a operatorilor relauonali, foJosind perechi In care pr-imul element(first) este de tip string, iar al doilea (second) este de tip float. Perechea picste creata uuhzand consrructorul de initializare, jar perechca p2. esre creata utll.Izandconstructorul implicit, apoi este initializata apeland functia make jpeLr- () .

#include <iostream>#include <utility>using namespace stdiint main (){pair<string,. float> pl("Ionescu Dan~, 9.75)pair<string, float> p2;p2=make---.J)air (" Popescu Ana", 9.43);cout«pl. f Lr s t.«-c ' '«pJ. second«' 'vn 'cout«p2.first«' '«p2.second«'\n'if (pl==p2) cout«nperechi egale\n";

else cout«"Perechi neegale\nn;if (pl<p2) cout«~pl<p2";

else cout«"pl>=p2"ipl=make-pair("popescu Ana", 9 .98) i

if (pl<p2) cout e c" Dupa schimbare: pl<p2\n" ie Lee cout«" Dupa schimbare: pl>=p2 \n" ;

return 0;

Dupa executia acestui program, pe ecran se va afisa :Ionescu Dan 9.75pop e s ou Ana 9.43Perechi neegalepl<p2 Dupa schimbare: pl>=p2

4.10. AlocatoriiAlocatorii sunt clase care deflnesc modul de alocare a mernoriei pentru conraine­

role dinSTL

4.11. AplicajiiIn capitolcle urmatoare vom descrie difertte clase container si vern face aplicatii

eu acestea. Aici vom demonstra modul de funcjionare a unor algoritmi din STL utili­zand un tablou unidimensional (vector din C). In loc de ireratori vom utiliza pointed.Acest Iueru este posibil deoareee se realizeaza 0 conversie irnplicita a poinrerilor Initeratori. Pentru exemplificare, luam in considerare urmatoarele declaratii :

I.,. int a[]=IIO,11,12,13,14,15,16,17,18,19j;. int n=10;

Inversarea elementelor intr-un tab lou unidimensional

Declaratia functici -r eve.rs e ( )

template <class ~jdirectionallterator>

void .reverse (Bidirectionallterator pr::cm,Bidirectionallterator uJ.tim);

i~

, i~

~

-"

:1

-J

~

Page 63: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

reverse (a+st,B+dr)

Daca st=3 si dr-»? , dupa inversare vectorul a este :{lO,11,12,16,15,14,13,17,18,19}.

Eliminarea elementelor care indeplinesc 0 anumitd conditieDcclarana functiei remove_i f () :

Dupa inversare , vectorul a este: {19, 18 , 17 , 16 , 15 , 14 , 13 , 12 , 11 , 10 } .Pentru a invcrsa doar elementele din vector de la pozitia st (inclusiv) pan a la

pozijia dr (exclusiv), putem apela functia reverse () astfel:

125sri: CONCEPTE GENERALE

int st=3, dr=6, nr;int * p s f e r-emove __ if (a+st., e-r-d r . EstePar)nr=a+dr-psf; //determin numarul de elemente eliminat:.ecopy{a+dr,a+D,psf) ;//copiez restul vecto~ului

n-=nr; I/actualizez dimensiunea vectorului

Sortarea unui tablou unidimensional

#include <iostream>#include <algorithm>using namespace std;,st~ing s;void majuscula{char& c){ if (c>='a' && c<='z') c·-=c-'a'-l·'A';int main (){cin»s;for_each (s. begin (), s. end ( ), ma j u s ouLal :cout«s;return 0;

Observatie

Functiei for_each i-am transmis ca parametri doi itcratort (s _begin () rerur­neaza un iterator care indica inceputul sirul , iar s. end () rerurneaza un iterator careindica pozitia de dupa sfarsitul sirului) §i numele functiei care rcalizeaza prelucrarea(majuscula).

Transformarea sir

Ne propunern sa aplicam 0 prelucrare tuturor elementelor unui sir de caracrcre (Incazul nosrru, do rim sa trausformam toate literele mici din sir in majuscule). Pentruaceasta am putea utiliza algoritmul for_each () din STL.

~template <class lnputlterator, c1.ass Function> -

: r'unc t i on for_each (lnputlterator prim, lnputlterator ultim,; Function fn);

AlgoritrnuJ foreach () aplica tuturor elementelor din domeniul tpr-Lm. ultim)

o prelucrare descrisa de functia fn.

Sortarea clementelor unui container se poate realiza eu ajutorul functiei sort ( ) .Aceasra functie este supralncarceta :

template <class RandomAccesslterator>void sort (RandomAccesslt.erator prim, Randoml~ccess:rt:erat.or

ul tim) i

template <class Randorn.i;ccesslterator, class Compare>void sort (RandomAccesslterator prim, Rzmdorns.cces s Ltera t.oz u I tim,

Compare camp)

PROGRAM:\REA iN LIMBAJlJL CIC++ PENTRU LICEl}124

Functia remove_if () el imina din domeniul [prim, u Ltim) reate elernentelepentru care predicatul rerurneaza valoarea true, pastrand ordinea elementelor neeli­rninate. Punctia rerurneaza un iterator care indica noua pozitie de sfarsit a domeniuluiobtinut dupa eliminare.

Functia parcurge domeniul si, la fiecare pozitie pe care se afla un element careindeplinesre conditia, cauta primul element urmator care nu indeplincste conditia si ilplaseaza pe pozfna curenta. Astfel, ordinea elementelor se pasrreaza. iar algoritmulde eliminare csteliniar.

Sa presupunem ca dorim sa eliminant din vcctorul a elemenreJe pare. Vom construio functie cu rezulrat bool care sa verifice conditia dorita (aceasta functie va f unlizaraca predicat).

l: hool EstePar (int x) {return x Si,;2 = -== O; }

Pentru a elimina elementele pare din intrcgul vector a, putem apela functiaremave_i f () astfel :

int * psf=remove_if(a,a+n,EstePar) j

Evident, functia remove_i f () llU .modiflca dirncnsiunea vectorulu i a. Prillurmare, vorn actualiza dupa apel valoarea variabilei n (numarul de clemente dinvectorul a), scazand din pointerul psf In care am retinut noua pozitie de sfarsit adomeniuJui, pointeruJ a care indica inceputul acestuia:t .nvps f e a :

Daca dorim' sa rcalizjim cliruinarea elementelor pare doar de pe Ull interval dinvectorul a, sa spunem intervalul Ler.s t . a+dr), atunci trebuie sa avem grija s5mutam 1a stangacu nr pozitii toate elementele din intcrvalul ra+dr, a+n) (unde eunr am notat numarul de clemente eliminate).

Functia reverse () inverseaza ordinea elernenrelor din domeniul [prim, u Lt Lm) .Pentru a inversa inrrcgul vector, putem apela functia reverse () astfel:

reverse(a,a+n);

template <class ForwardlLerator, class UnaryPredicate>Porwardlterator remove if (Forwardlterator prim,

Forwardlterator ultim,UnaryPredicate pred) j

r-t-

r-r

r-t

r-'

,-.

r-

r-'

i,

-

ii

I

Page 64: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

126 PROGRAMAREA iN LIMBAJUL CIC++ PENTRU LlCEUSTL. CONCEPTE GENERALE 127

in programul precedent am -definit 0 funcue de compararc. Puteam defini

ComparElevi ca functor, astfel :

}

void Scrie (){int ijfor (i=O; i<n; i++)

fout«a[i) . rrume-c-c ' '«a[i] .jxr-eri-c c ' '«~ali] .mg «' \n';

int n;ifstream fin("elevi.in"} j

of stream fout("elevi.out");void Ci teste (){i..nt i;fin»n;for (i=O; i<n; i++) fin»a[i] .TIume»a[iJ .pren»a[i] .mg;

Conctuzie

Daca tipul elementelor containerului este un tip predefinu al limbajulul sau un tipdefinit de utilizator care arc supraincarcat operatorul <, sortarea crescatoare aelementelor se rcalizeaza cu prima forma a functicl sort ( ) .

Sortarea cresciuoare a unui tablou unidimensional de elevi

Definim 0 strucrura denurnita elev care va avea 3 campun : numele elevulul ,prenumeJe elevului ~j media sa gcnerala. Pentru acest lip _de date, apcratorul < nueste supraincarcat, prin urtnare vom defini 0 functie de cornparare a doi elevi(intentionam sa sorram elevi i lexicografic dupa nume , iar dacil exista mai multi elevicu acelasi nume, ii vom sorta lexicografic dupa prenume).

#include <fs~ream>

#include <algorithm>using namespace std;struct elev {string nume, pren; double mg; };

eleva [1000];

'--'

-.J

, 1

, i

-'

~

r:

w

u

e2}

int main (){Citeste ()sort{a,a+n, ComparElevi)Scrie () ;return 0;

bool ComparElevi (const elev& el, canst elev&

{return el... nume<e2 . rrume I Iel.nume==e2.nume && el.pren<e2.pren;

int main (){Citeste ()sort(a,a+D)Scrie() ;return 0;

Pentru a sorta crescaror dear domeniul j e e s t.. a+dr)

sort re r s t • a+dr);

#include <iostream>#include <algorithm>#include hfractie.h"using n~nespace std;fractie a [lOOOJint n;void c i teste ( ){cin»n;for (int i=O; i<n; i++) cin»a[i]i

void Scri e ( ){for (int i=O; i<n; i++) cout«a[iJ«'cout« ' 'vn ' j }

Prima forma se poate utiliza penrru a sorra elementele din domeniul [prim, ul tim)in ordine crescatoarc (considerand pentru compararea elementelor operatorul -c, caretrebuie sa fie dcfinit pentru tipul elementelor containerului).

A doua forma perrnite speciflcarea functiei care se utllizeaza pemru comparareaeJementelor cornainerului (printr-un functor sau un pointer de fuuctiejv.Aceasta trebuiesa 'fie 0 functie ell doi parametri sl trebuie sa returnczc un rezultar de tip boo 1.Rezultatul va f t rue daca primuJ parametru trebuie sa fie plasat in vectorul sortaiInaintea eelui de-a I doilea parametru ,

Metoda de sortare utilizata este un algoritm crcat de David Musser In 1997denumit introsort (sau introspective sort - sortare lnrrospectiva). Acesr algoritm opti­mizeaza metoda de sortare quicksort, utilizand tieapson, pentru cazul in care adan­cimea recursiei este prea mare. Complexitarea acesrul algoritm este de 0 (n log n)in cazul eel mai defavorabiI {unde cu n am notat numarul de clemente din domeniulce trebuie sortat).

Sortarea crescdtoare a unui tablou unidimensional de numere intregi

Pentru a sorta crescator jnrreg vectorul :

sort (a, a-rn) ;

Sortarea crescatoare a unui tablou unidimensional de fractii

Revenim la clasa fractie, pe care am definir-o in capitolul a1 doilea , Pentruaccasta class am supraincarcar si operatorul <. Sortarca unui tablou unidimensionalell clemente de tip fractie se poate realiza asrfel :

Page 65: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

} ;

Daca a are cornponente de tip int, Yom sorta descrescaror elemcntele saleastfeI :

return el.nume>e2.nume ! Iel.nume==e2.nume && el.pren>e2.pren;

Sortarea descrescdtoare a unui tab/au unidimensional

Pentru a sorta descrescator un tablou unidimensional, trebuie sa urilizam cca de-adoua forma a funcjie! de sortare , specificand ca al treilea parametru criteriuI desortare (un functor sau a funcue de comparare).

Pentru clemente de tipuri predefinite sau definite de utlllzaror cu operatorul >

supraincarcat, se poate utiliza functorul predefinit greater<'l'> () . Pentru a puteautiliza acesr functor, trcbuic sa includcm fisierui antet functional.

Functorul greater este dcfinit astfel :

template<class T> struct greater:binary_function <T,T/hoal>(

heal operator() (canst T& x, canst T& y) canst{ return x>Yi

129

sortareasema-

j.n care extsta

cout« ' \n' }

a elementclor egale. Pentrude asemenea in doua variante,

STL. CONCEPTE GENERALE

Sortarea stabild

int main (){i.nt iicout « "n="i cin»nifar (i=l; .i c e n : i ..H·) p[iJ=iido

{far (i=l; i<=n; i++) cout«p[i]«'while (next_permutation (p+l,p+n+1J );return 0;

using.namespace stdiint ni:lnt p[NMAX]

Sortarea stabila conserve ordinca initialasrabiJa se utilizeaza functia stable_sort () ,natar ell functia sort ( ) .

Complexitatea sortarn stabile este de O(n log ri) (in cazulmemorie suplimcntara suficienta) sau O(n Loq-ri) ill caz contrar.

Generarea de permutari

Itemplate <class Bidirectionallterator>

;'bool next-permutation (Bidirectionallcerator prim,; Bidirectionallterator ultim)

I.template <class Bidirectionallterator, class Compare>r baol next-permutation (Bidirectionallterator prim,; Bidirectionallterator ultim, Compare comp) i

Functia next-pennutation () rearanicaza elcmemele din domeniul [prim, ultim)astfel 'incat sa constituie permutarea imediat urrnaroare din puncr de vedere lexico­grafic. Implicit, elementele se cornpara ell operatorul <. Daca sc urliizeaza cea de-adoua varianta, compararea elernentelor va fi realizata cu ajutorul functorului c omp,Functia rcrumeaza true daca rcaranjarea a fast posibila.

Vom utiliza aceasta functie pentru a genera In ordine Iexicografica toate permu­tarile de ordin n. In acest seop Yom utilize un vector p, pe care 11 vom initialize ellcea mai mica permutaredin punct de vedcre Jexicografic (1,2, ... , n). La fiecare pasafisam permutarea curenta si generam permutarea urmaroare. Proeedeul se repera cat(imp generarea 'urmatoarei permutari este posibifa.

#include <iostrearn>#include <algorithm>#define NMAX 50

canst

PROGRAMAREA iN L1MBAJUL CIC++ PENTRU LJCEU

haal operator(} (canst elev el, canst elev e2){ return el.nume<e2.nume I I

el. n1..line==e2 . nume && el. p.reri-c e z v p r e.n i} ;

ClasaComparElevi ComparElevii

128

[ 7t ruc t ClasaComparElevi

I

sortia,a+n, greater<int>();

In accfasi mod procedarn, de exempJu, $i pentru un vector ell clemente de tipfractie (deoarece pentru aceasta clasa am supraincarcat operatorul » :

~ sort (a,a+n, greater<fractie>(»);

Sortarea descrescdtoare a unui tahlou unidimensional de elevi

in cazuJ in care operatorul > nu este supraincarcai pentru tipul elemcntelor pecare trebuie sa Je sortam, trebuie sa definim un functor sau 0 funcue pentru compa­rarea elememelor. in cazul vecrorului de elevi, sillgura modificare pe care trebuie sao facem penrru a obtine ordonare lexicografica descrescatoare este schimbarea crite­riului de sortare in functia ComparElevi () :

hoel ComparElevi (canst elev& el, canst elev& e2)(

r

r-e­,

-

i j

, ,

-

Ii

r-',

I, ,

r-t

I

Page 66: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

Anagramele unui cuvant

Daca dorim generarea permutarilor III ordine lexicografica inversa. vom initializavectorul p ell eea mai mare permutare (n , n-l, ... , 1) §i la fiecare pas, dupa afisarea per­mutarii curente, generam precedenta pennutare apelaud functia prev-perrnutation ()

for (i=l; i<=n; i++) p[iJ=n-i+l;do

{for (i=l; i<=n; i++l cou t c cp Li j c c ' 'i cout«' \n';}while (prev---permutation(p+l,p+n+l));

130 PROGRAM AREA iN LIMBAJUL C/C ++ PENTRU LICEU

'i111

STL. CONCEPTE GENERALE

#include <iostream>#include <algorithm>int n;intf[lOO];

class TermenF{public:int £1, £2;int operator () () {int £3=£2+£1; £1=f2; £2=£3; return £3;

) TF;

1311:

':

! 1

b. sort (a+l, a-i-n ) i

d. in acest caz nu este posibila sortarea eli sort ( ) .

o anagrama este un cuvant care are aceleasl there ca si cuvantul dat, eventualintr-o alta ordiue , De exemplu, cuvintele tamara §i armata sunt anagrame.

Generarea anagramelor unui cuvant este un procedeu similar ell generarea permu­tarilor. Exista totusi un aspect la care trebuie sa tim atenti : daca incepem generareaanagramelor cu cuvanrul citit, yom obtine doar anagramcle mai mari din punct devedere lexicografic decat acesta. Din acest motiv, inainte de a tncepe gcncrarea, Yomordona crescator literele cuvanrului citit (pentru a obtine cea mai mica anagramsposibila).

#include <iostream>#include <algorithm>#define NMAX 50

us~ng namespace stdjstring s;

int ma i.nL){cin»s;sort(s.begin(), s.end())do

cout«S«,l vn ' ;while (next-permutation(s.begin(),s.end())jreturn 0;

Programul evidentiaza faptul ca functia de generare a urmatoarei permurarifunctioneaza ~j in cazuJ in care in domeniul specificat valorile nu sunt distincte.

Generarea sirului Fibonacci

Vom genera intr-un tablou unidimensional primii n termeni din sirul Fibonacci,utilizand funcua generate () .

In acest scop, vom declara un functor TF, obiect a1 clasei TermenF. ClasaTermenF are datele 11!e.mbre £1 si £2 (doi termeni consecutivi din sirul Fibonacci) sioperatorul () supraincarcat. Acesr operator returneaza urmatorul termen din sirulFibonacci ~i actualizeaza corespunzator f 1 si f 2 :

!! using namespace std;

int main(){cout « ,rn=~; cin»n;f[OJ=TF.£l=O; £[lJ=TF.£2=1; I/initializaregenerate(f+2, £+n, TF) j //generarefor (int i=O; i<n; i++) cout«f[iJ«'return 0;

4.12. Exercitii ~i probleme recapitulative

1. Sa consideram un tablou unidimensional a ell elemente reale, plasate pe pozitiile1, 2, ... , ri , Care dintre urrnatoarele variante sorteaza crescator elementelevectorului a?a. sort(l,n);c. sort(a+l,a+n+l)

2. Care dintre urmatoarele expresii are valoarea true daca in eontainerul C nuexista elemente (este vid) :

a. C.begin()==O b. C.end()==Oc. C.begin () ==C.end() +1 d. C .begin() ==C .end()

3. Care dintre urmatoarele afirrnatii sunt adevarate ? ..a. Grice container, indiferent de tipuJ acestuia, trebuie sa dispuna de constructori

privati.b. Algoritmii interactioneaza ell containerele prin intermediul iteratcrilor .c. Un obiect al unei clase sablon se numeste functor.d. Pentru a indica un element al unui container putem utiliza un iterator.e. Grice container contine functiile membre begin () ~i end ( ) .f. Grice iterator, indiferent de tipul acestuia, suporta operaua de decrernentare .g. Un predicat este un functor care returucaza 0 valoare de tip bool.11. Operatorul + este supraincarcat astfel IDcat sa pennita adunarea dintre un

iterator bidirectional si un intreg.i. Grice iterator poate fi dereferentiat ell operatorul unar "1<.

'--'

-J

~

-'

-

Page 67: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

I"

-i .

r-'

: ;

r-'

,

r-t

r-'"

r-:

r

,

,

~

132 PROGRAMAREA iN LIMBAJUL C/C ++ PENTRU LICEU

j. Algoritmii sunt functii membre ale claselor container.k. Pentru a sorra descrescator eJementele unui container, intotdeauna poate f

utilizat ca parametru al functiei sort () functorul predefinit greater.

4. Gencraji aleatoriu un tablou unidimensional ell n clemente naturale < 10000,urilizand funcua generate () .

5. Sa consideram un tablou unidimensional ell numere narurale eli eel putin treicifre. Utilizand functia for....,:.each (), eliminati din fiecare element a1 tablouluicifra din mijloc (dadi elementuJ are numar impar de cifre) , respectiv cifrele dinmijJoc (daca elementul are numar par de cifre).

6. Sa consideram urmatoarea strucrura :

struet DataC {int an, luna, zi; };

Din flsierul text datel. in se cireste un numar natural n , apoi 0 'succesiune de ndate calendansnce, care una pe 0 Jinie, scrise sub forma:zi-luna-an

Datele calendaristice vor fi memorate intr-un vector cu elcmente de tip DataC.

Ordonati datele cronologic , folosind functia sort (,) din STL in u-ei variante :a. supraincarcati operatorul < ;

b. implementaji criteriuJ de sortare ca functie ;c. implementati criteriul de sortare ca functor.In mod similar, sortati §i datele stocate (in acelasi mod) in fisierul date2. in.Utillzand algoritmii din STL, deterrninati si afisati :d. dateJe calendaristice care se afla in ambele fisiere ;e. datele calendaristice din cele doua fisiere, in ordine cronologica.

7. Fisierul dictionar. in contine cel mult 10000 "de HnH, pe fiecare linie fiindscrisa 0 definitie de forma:

termen=descriere

Rezolvati, utilizand algor-itmii din STL, urmatoarcle cerinte :a. Cititi continutul fisierului dictionar. in ~i construiti un tablou unidimen­

sional ale carui componente sunt perechi .(pair) formate dintr-un termen sidescrierea corespunzatoare.

b. Serrati termenii din dictionar in ordine lexicografica.e. Cititi de la tastarura un cuvant ~i cautau-! eficient in dictionar. Daca ali gas it in

dictlonar cuvantul , afisati descrierea corespunzatoare. in caz contrar aflsaumesajul nu exi s ta.

d. Cautati in dictionar si aflsati pe eeran toare anagramele cuvantului citit de latasratura.

e. Stiind ca numele proprii tncep cu majuscuta, rearanjati termenii din dicponarastfel incat la inceput sa fie numele proprii in ordine lexicografica, apoi restulcuvintelor, de ascmcnea in ordine Icxicograflca.

5. Containere secventiale

Containerele secvenjiale predefinite in STL sunt vec t o r . dcquc;' list si ,incepand cu C++ II, array §i forward_list.

in capitolul precedent am mentionat 0 serie de elemente 'comune tuturor containe­relor din STL. In continuare vorn prezenta eJementele speeifice fiecarui tip de container.

5.1. Clasa vector

Pentru a utiliza aceasta clasa, trebuie sa includem Iisierul antet vector:

#include <ve c.toz->

Clasa vector implemenreaza 0 structura de date similara eu tablouriJe unidimen­sionale (vectorii din limbajul C). Elementele containerului sunt de acelasi tip §i suntrnemorare intr-o zona continua de memorie. Ca unnare, elementele containerului potfi accesate atat prin intermediul iteratorilor, cat si prin intermediul pointerilor.Iteratorii containerului vector sunriteratori cu acees aleatoriu.

Diferenja sernnificariva consta in faptul ca memoria necesara pentru eJementelevectorului este alocata dinamic. In acest scop, c1asa vector utilizeaza un alocator(implicit, acesta estc un obiect al clasei predefinhe a j l o'ca t.o r-).

Constructorii !ii destructorul

Constructorii clasci vector sunt :

• Constructorul implicit (fara parametri) - crceaza un vector vid (tara elemente).

Exemplu

vector<int> a'

EJect: crceaza un vector vid cu clemente de tip in t

• Constructor de umplere (jill) - creeaza un vector cu numar specificat de clemente;in cazul in care se specifics si 0 valoare ca al doilea parametru, elementeJe vecto-rului sum initial izate ell valoarca specificate. ---

Page 68: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

134 PROGRAMAREA iN LIMBAJUL C/C++ PENTRU LICEU CONTAINERE SECVENTIALE 135

Exemplu

vector<int> a(100,0) i

Creeaza un vector cu 100 de elemente de tip int ~i initializeaza cu 0 toateelementele.

Creeaza un vector de dimensiune egala cu dimensiunea sirului s ~i copiaza invector fiecare caracter din sirul s.

• Constructor de copiere - creeaza 0 copie a unui vector.

• Destructorul - distruge obiectul, eliberand memoria alocata dinamic.w

~

, :'

. ,!

• reserve ()

void reserve (size_type n)

Redimensioneaza spatiul de memorie alocat vectorului astfel incat sa contina exactn clemente. Daca dimensiunea curenta a vectorului este mai mare de n elemente , sepastreaza doar primele n clemente ale vectorului (celelalte fiind distruse). Dacadiniensiunea curenta a vectorului este mai mica de n elemente, se adauga elementelenecesare la sfarsitul vectorului (eventual inirializandu-sc elementele adaugate cuvaloarea val).

.shrink_to_fit () 111)

void shrink_to_fit();

Redimensioneaza memoria alocata vectorului astfel incat sa fie egala cu numarulde .clcmenre din vector.

• resize()

void resize (size_type n);void resize (size_type n, const value_type& val) ;

Asigura faprul ca vectorul are memorie alocata pentru eel putin n elemente. Dad!mcmoria alocata pentru vector este mai midi de n clemente, se aloca memoria nece­sara (posibil in timp liniar), in caz contrar apelul functiei neavand niciun efect.

s. errd t ) ) ;

vector<doub~e> b(1000);

Creeaza un vector cu 1000 de elemente de tip double, tara initializare.

Constructor bazat pe un domeniu (range) - creeaza un vector in care copiaza inordine toate eJementele dintr-un domeniu specificat,

Exemplu

cin»s;vector<char> d(s.begin(),

~ string s :

.Clasa vector contine functiile begin (), end (), rbegin (), rend ()semnificatia uzuala. Incepand cu C++ 11, exista ~i functiile corespondentererurneaza const_i terator (cbegin () , cend ()., crbegin () , crend t ) ).

Accesori

• at ()reference at (size_type n) i

canst_reference at (size_type n) canst;

Returneaza 0 referinta catre elementul situat pe pozitia n in vector. Spre deosebirede operatorul de indexare, functia at () verifica validitatea pozitiei n ~i "arundi" exceptiaout_of_range in cazuJ in care n z s Lz e ().

~

~ 1

-J

situat pe pozltia n in vector (pozitiile fiind

const;

unui vector se realizeaza cu ajutoruJ urmatoarelor functii

• front ()

reference front();canst reference rrqnt()

• operatorul de indexare []

reference operator[] (size_type n) i

const,._reference operator f] (size_type n) const;

Retumcaaa 0 rcfcrtnta catre elementuJnumerotate de la 0).

I

IAccesul la elementele

I membre publice :

I I

I

Cll

care

Functiile membre care returneazd iteratori

Functiile membre referitoare La dimensiunea vectoruLui

Complexitaie

Pentru constructorul de umplere Cll initializare, constructorul bazat pe un domeniu~i constructorul de copiere, complexitatea este Iiniara ; ceilalti constructori necesitatimp constant..

Alaturi de functiile uzuale size ( ), empty () ~i max_size () in clasa vectorsunt definite ~i urmatoarele functii rnembre publice :

• capaci ty ()

size_type capacity{) const noexcept;

Rerurneaza dimensiunea zone! de memorie alocata pentru vector, exprimata innumar de elemente ; memoria alocata nu esre obligatoriu egala eli numarul efectiv deeleinente din 'vector (ar putea fi mal mare, pentru a pcnnire inserarea unor noiclemente tara a fi necesara reaJocarea memoriei).

Page 69: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

137

O(n)

assign ()

CONTAINERE SECYENTIALE

0(1) I 0(1) _I .O(n)

• assign ()

template <class Inputlterator>void assign (Inputlterator prim, Inputlterator ultim)void assign (size_type n, const value~type& val);

Functia realizeaza 0 atribuire, Inlocuind elementele vectorulu i eu elementele dindomeniul [prim, ul tim), respectiv cu n clemente cu valoarea val. in cazul incare capacitatea vectorului este mai mica decat numarul de elemente din dorneniu ,respectiv decat n , se aloca memoria necesara.

Complexitatea opera/iilar de inserare/eliminare

push_back (J I pop_back (J I insert ( )

varianta insereaza -elemenrele din domeniul [prim, ul tim) . Punctia rerurncaza uniterator care indica primul element inserat.

Observatii

1. Functiile pop_back (), erase () si clear () nu ellbereaza memoria alocataelementelor eliminate. Nici functiile resi ze () sau reserve () nu reduc dimen­siunea mcmoriei alocate. Pentru ca aeeasta sa fie exact 'memoria necesara, sepoate utiliza lncepand cu C++ 11 algoritmul shrink_to_fit (). Pentrucompilatoare mai vechi, putem apela -la 0 ,,~mecherie'l rcreez unvectorremporarpe care 11 interschimb eu vectorul pe care il redimensionam. Crearea vectoruJuitemporar 0 vom realiza utilizand constructorul de copiere. Sa presupunem caveetorul este denumit v, iata 0 modalitate de a dimensiona exact memoria alocaravectorului v in timp Iiniar:

v e c t.or <T'> (v) .rswap (v) ;

2. Incepand cu C+ + 11, functiile insert () $i assign () au 0 dire 0 var-iantacare primeste ca parametru 0 lista de initializare. 0 lisra de inltial lzare este unobiect al clasei sablon ini t i a.l i.z er-jLi s t; care se construieste automat pebaza unei liste de valori (0 succesiune de valori separate prin vlrgula, Incadrataintrc acolade). De asemenea, au fost introduse inca doua functii membre denumiteemplace () sl emplace_back (), care construiesc §i insereaza un elementintr-o anumita pozHie.

• erase ()

iterator erase (iterator poz) ;iterator erase (iteratar prim, iteratar ultim) ;

Elimina §i distruge din vector elementul indieat de iteratorul poz, respectiv toateelementele din domeniul [prim, ul tim), Ca urmare, dimensiunea vectorului vascadea cu numarul de clemente eliminate. Functia rerurneazf un iterator care indicapozitia de dupa ultimul element el irninat.

PROGRAMAREA iN LIMBAJUL CJC++ PENTRU LICEU

• insert ()

136

iteratoriterator

templateiterator

Ca pentru orice container, este supraincarcat operatorul de atribuire e , func~iamembra swap (), functia clear (), functiile insert () §i erase (). in plus, SUiHdefinite urmatoarele funcni membre publice care modifies veeraruI :

• push~back ( )

void push_back (const value_type& val) ;

Insereaza un nou element la sfarsitul vectorului §i copiaza in acest elementvaloarea val. Dimensiunea vectorului va crcsre eu 1 si, ca urmare, este posibiJ saseexecute realocarea memoriei.

Rcturucaza 0 rcferinra entre prirnul element din vector (spre deosebire de begin (),care rerurneazs un iterator).

• back ()

reference back{)jcanst_reference back() canst;

Returncaza 0 rcferinja catre ultimul element a] vecrorului (spre deosebire de end (),care returneaza un iteraror ce indica pozlua de dupa ultimul element).

• data () (llJ

t ~alue type* data() noexceptif const- value_type* data () canst noexcept: i

Retumeaza un pointer care contine adresa de incepur a zonei de memorie in caresunt stocare elernentele vectorului.

Teare functiile de acces se executa in rirnp constant.

Funcjiile membre care modified vectorul

• pop~back ( )

void pop_back ()

Elimina §i dlstruge ultimuI element din vector. Dimensiunea vecrorutui va scadeaeu 1.

insert (const_iteratar paz, const value~type& val);insert{const_iteratar paz, size_type n,

const value_type& val);<class InputIterator>insert (const_iterator paz, InputIterator prim,

InputIterator ultim);

r Se insereaza unul sau mal multe clemente in vector in pOZ1tIa specificarit dei : iteratorul poz. Ca urmare , dimensiunea vectorului va creste eu numarul de clementeLJ lnserare si este posibiJ sa se execute reaJoearea rnemoriei. .prima'varianta insereazar- valoarea val, a doua varianta (fiLf) insereaza n elemente avand vaJoarea val, a treia

rr

~f, I'L j'

r-'

l..

r

rI

I"

-

Page 70: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

--- -,<.;',; !

Operatorii relationali

3. Desi nil le-arn prezentat, incepand ell C++ 11 exista versi-uni ale unor functiirnembre care au parametri de tip value_type&&:

void Push_back (value~type&& val)jiterator insert (const_iterator paz, value_type&& val);

Construqia Tip&& a fost introdusa incepand ell C+ + 11 'pentru a indica 0referinja Ia 0 vaJoare de tip rvalue (right-value, valoare care poate fi plasata dear inmembrul drepr al unei atribuiri). In limbajul C, 0 valoare temporara care putea fiplasata dear in membrul drepr al unei atribuiri nu era mcdificabila. Acest nou tip indicafaptul ca 0 valoare ternporara care este plasata In membrul drept al unei atribuiri,poate fi tuodificara dupa ce a fost creata, Acest tip a fost introdus din motive deeficienta a implementarii, pentru a indica murarea valor-ii respective'.

De exemplu, in variantele de rnai sus, vaJoarea spccificata ca parametru a]functiei push_back () , respectiv insert () este mutata in vector (nu copiata).

, ,,

"""

139CONTAINERE SECVENTIALE

-doua valori naturale, reprezentand numarut de calorii determinat de taran pentruprodus si cat costa intreaga cantitate din produsul respectiv. Ultima linie a fisierululde intrare va contine 0 valoare naturala S reprezentand suma de care dispune gospo­dina pentru cumparaturi,

Date de iesire

Fisierul de iesire calorii. out va contine pe prima Jinie 0 valoare rcala cu patruzecimale, reprezentand numarul maxim de-calorii continute in produsele cumparate.

Restrictii

1 :5: n :5: 100001 s S S 2000000000

Numarul de calorii si preturile sunt valori naruralc s 30000 .RezuItatuJ afisat este considerat corect daca eroarea este mai mica decat 10-3

Exemple

PROGRAMAREA TN LIMBAJUL CIC++ PENTRU L1CEU138

~

'-'

....;

-

Produs, care are doua date membre: cal~i pret (pretul produsuJui); supraincar-

Explicapi

(Olimpiada Municipala de Informatica, Iasi, 2010)

Rezultatul se obtinc prin cumpararea imegrala a produselor 2,4 ~i 5 ~i a 57.1428571% din produsuJ 3. Prill calcul scobserva faptul ca :300+700+500+57.1428571*150/100 =1585.71428565

1585.7143

struct Produsint cal, pret i

bool operator>(const Pr6aus & pl' const{ return cal*p.pret>pret*p.cal;

) ;

Pentru implementare, definim clasa(numarul de calorii pentru intregul produs)cam ca functie membra operatorul > :

calorii.inlcalorii.out

Soliqie

Problema este 0 reformulare a problemei rucsacului, varianta continua. Metodade rezolvare este Greedy:- sortam produsele dupanumarul decalorii pe care le pot obtine din produsul res­

pectiv cu 1 leu;- cat timp produsul curent poate fi curnparat in intregimc (pretul sau este mai mic

sau egaI decat suma disponibila), Il cumparam (adaugam la total caloriile achizi­tionate, iar din suma disponibila scadcm pretul produsului) ;

- la final, daca mai exista un 'produs, cumparam un procent din acesta, in funqie desuma disponibila; caloriile obtinute se calculeaza ell regula de trei simpUi.

5

100 5

300 4., 150 7

700 2500 20

30A devenit 0 adevarata arts sa alcatuiesti un meniu Care sa fie bogat dar sa conpna

cat mai purine calorii. Fiecare produs are lnscris pe el procenrul de grasnni pe care lecontine ~i numarul de calorii. Din pacate, acest lucru nu se inrampla ~j Ia piara.Vazand aceasta, un taran inventiv, care ofera spre vanzare un numar de n produse, afacut un mic ca1cul ~i a determinat, penrru fiecare dintre produsele oferite spre vanzare,numarul de caJorii pe care le condne intreaga cantitare din produsul respectiv.Taranul a scris pe cate 0 eticheta numerele astfel determinate §i a pus fiecare erichetalanga produsul corespunz~tor, 'avand grija ca dupa flecare vanzare sa corecteze inmod corespunzaror numarul inset-is pe eticheta. 0 gospodina ce dispune de 0 anumitasums de bani S pentru cumparatun doreste sa cumpere produse de la ace] taran astfelincat sa che]tuiasdi intreaga suma S de care dispuhe, dar sa duca acasa cat mai mulrecalorii. Gospodinei 11 este indiferent ce produse cumpara ~i in ce cantitati, scopulflind ca produsele curnparare sa contina in rotalitate cel mai mare numar de calorii.

Cerinfd

Sa se determine cantitatea maxima de calorii ce poate fi cumparadi.

Date de intrare

Fi§ierul de intrare calorii. in va contine pc prima linie un numar natural n.reprezentand numaruJ de produse. Fiecare dintre urmatoarele n linii va contine caw

AplicaJia I. Calorii

Pentru clasa vector sunt supraincarcari tali opcrarortl relationali , compararea adoi vector] realizandu-se din punet de vedere lexicografic.

1. Explicalia este cxtrem de succinta. Thomas Becker a realiZai 0 prezenlarc foarle clara ~i cletaliatacare ponLe fi consultatii la adresa: http://thbeckcr .netJarticlcs!rvaluc_ refercnces/section__Ol .htmL

, I

Page 71: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

J40 PROGRAMAREA iN LIMBAJUL C/C-I-+ PENTRU LICEU

I~'-

COl':TAINERE SECVENTIALE J4J

r-',

,~

!

,-

"i I

I',,

r,

,

n

,..,

Declaram vectorul de produse p asrfel :

vector<Produs> p;

Pentru a nu fi necesare realocari de memorie, rezervgm de la incepur memorianecesara pentru vectorul p :

f: p. reserve (n) ;

Din fisierul de intrare citim succestv care un produs (in variabiJa auxiliara x de tipPr-ocius j si adaugam In-vector produsul x apeland functia push_back ()

Produs Xj

for (int i=O; i<n; i++){fin»x.cal»x.pret;p.push_back{x); }

Penrru sortarea descrescaroarc a produselor din vectorul .p, apelam functiasort () :

~ sort(p.begin(}, p.end(), greater<produs>()}i

Pentru a rezolva problema, parcurgem elementele vectorului p folosind un itera­tor it, atat timp cat produsul curent poate fi cumparat integral:

Ivector<Frodus>: :iterator it;

..

", for (it=p.begin(); it!=p.end(); it++). if (i t->pret <= S): { total+=it->cal;! S-=it->pret; )

eJ.se break;

Aceeasi parcurgere 0 puteam.scrie "normal", utilizand operatorul de indexare :

ifor (int j=O; j<n; j++)

: if (p[jJ .pret <= s)

.: { total+=p[jJ .cal; S-=p(jJ .pret;: else break;

La final, daca mai exisra un produs disponibil, cumparam 0 fracriune din acestprodus, in functie de suma ramasa :

~ if (itl=p.end() total+= (double) S*it->cal/it->pret;

Programul complet arata astfel :

#include <fstrearn>#include <vector>#include <algorithm>#include <functional>#include <iomanip>using namespace std;ifstream fin{"calorii.in")ofstream ,fout("calorii.out")struct Produs

(int cal, pret;boo~ operator> (const Produs & p) canst{ return cal*p.pret>pret*p.cal; }

} ;

int main(){int n , S;double total=O;Produs x;fin»nivector<Produs> Pip . reserve (n) i

for (int i=Oi i<D; i++){fin»x.cal»x.pretip.push_back(x); )

fin»S;

sort(p.begin(), p.end(), greater<produs>())

vector<Produs>: :iterator it;for (it=p.begin(); it!=p.end() it++)

if (it->pret<=S){ total+=it->cal; S-=it->pret;else break;

if (itl=p.end()) total+= (double) S*it->cal/it->pret;

fout«setprecision(12)«total«'\n'; fout.close();

return Oi

Aplicatia 2. ZidIonel a- construit D turnuri formate din'~hl' h2~ : .. , respeotiv h-, cuburi (fiecare

cub avand latura 1). Tatal sau i-a propus sa faca un zid de lungime n. In acest scop,trebuie sa fie alese niste .turnuri dintre cele n construite astfel incat. rearanjandcuburile din turnurile alese, sa se obtina un zid de lungnne D. Zidul trebuie sa fie

format din exact n turnuri avand.aceea~i inaltime.

Date de intrareFisierul de intrare zid. in corinne pe prima linie un numar natural n care

reprczinra numarul de turnuri. Pe cea de-a doua luuc sum scrlse n numere naturaleseparate prin care un spatiu, reprezentand inaltimile ector n turnuri .

Date de iesire.Fisierul de iesirc z i d . au t; va contine pe prima linic un numar natura] k., repre­

zentand numarul de turnuri alese pentru a consttu i zidul. Pe cea de-a doua linie vor f

Page 72: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

serise k numere naturale separate prin .care un spatiu, reprczentand inaltimile celor kturnuri alese pentru construirea zidului.

Restrictii si precizdri

• 0 < n S 1000

• 0 < hi S 1000, pentru orice i=l, 2, ... , n

Exemplu

Exista numeroase rnodalitati de a implementa aeest algorttm. Scopul nostru estede a ilustra modul de funcponare a componentelor SJ'L, prin urmare :

1. Citim succesiv cele n tnaltirni ~i Ie adaugam in vectorul "h (pentru care amrezervat in prealabil memoria necesara) :

vector<int> h;h. reserve (n) ;for (i=O; i<n; i++)

{ fin»x; h.push_back(x);

2. Construim sirul sumelor perriale s , utilizand algorirmul numeric partial_swn ()

Soliqie

Problema este 0 aplicatie directs a principiului cutici al lui Dirichlet. Pentru aalege 0 submultime de turuuri eu suma inaltimilor divlzibila cu n, vom consrrui sirulsumelor partiale sl=h1 ; s2=h1 +h2 ; .•. sn=h1 +h2+ ... +hn • Exista doua cazuri:

1. in sirul sumelor partiale exists lsisn, astfel incat Si%n==O. in acest caz, 0

solutie posibila este fermata din turnurile 1, 2, ... , L.2. ~n sirul sumelor partiale si%n:t:O, pentru orice 1sisn. in acest caz avem n resturi

care iau valori in multimea {1, 2, ... , n -1}. Conform principiului cutiei al luiDirichlet, exista lsi<jsn, astfel incat si%n==Sj%n. 0 solutie posibila este i+l,i+2, ... , j (deoareee (sj-sd %n==O).

zid.in zid.out Explicatie

5 3 Se formeaza un zid de iungime n Si inaljime 24 7 4 2 1 7 2 1

~

w

~

_0

,'--'

.-,

143

fou Lc c ' vn '

CONTAIN ERE SECVENTIALE

vector<int>::iterator poz;poz=find(s.begin(), s.begin()+n, 0)

if (Poz!=s.begin()+n) //cazul 1{cate=poz-s.begin()+l;fout«cate«'\n' ;for (i=O; j c c a t e : i++) fout«h[i.J«'-

vector<int> s;s . reserve (n) ;partial_sum(h.begin(), h.end(), s.begin())

for_each(s.begin(), s.begin() -r-ri , rest);

int main ()int i,j,k, x, cate, gasit;fin»n;vector<int> h;h _reserve (n) ifor (i=O; i<n; i++)

{fin»x;h.push_back(x)

}

void rest (int& x) { x=x%nj

3. 'pransformarn sumele parnale in resruri, utilizand algoritmuJ for~each () :

for_each(s.begin(), s.begin()+n, rest);

Functia rest () transforms un numar intreg in restul impartirii sale la n :

~oid rest (int& x) { x=x%n;

4. Cautam, utilizand algoritmul find (), 0 valoare egala cu 0 in sirul resturilor,retinand in iteratorul poz pozitia pe care se afla prima valoare egala cu 0 :

t vector<int>: : i terator poz;Ii poz=find(s.begin(), s.begin()+n, 0);

Daca poz! =s .begin () +n, ne aflam in primul caz (a fost identificat un restnul), in caz contrar, ne aflam in eel de-al do ilea caz §i trebuie sa identificam douaresturi egale. Programul complet arata astfel :

#'include <fstream>#include <algorithm>#include <numeric>#include <vector>using nameSpace std;Lfs t r e am tint "z i.d c Lri")otstream fout("zid.out")int n;

(.campion 2005)

EBm7 2 1

~~OJ ~1

OJ

h.end(), s:begin{))

7 q 2

~ ~~~

PROGRAMAREA iN LIMBAJUL C/C ++ PENTRU LlCEU

vector<int> s;s. reserve (n) ;partial_sum(h.begin()

142

Page 73: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

Apiicaiia 3. Lucrul cu matrice

in STL nu exista 0 clasa speciala pentru lucrul ell matrice. 6 man-ice poate fi .implementata ca un vector de vecrori.

De exemplu, sa implemental11 0 matrice v ell n linii si m coloane $1 componentede tip into in acest scop Yom declara un v e c t o r- ell componente de tipv ec t o r c Ln r s, $i alocam memorie pentru vectorul de n linii:

~ Vector< vector<int> > v(n);

Vom "umple" matricea ell numerele naturale de la 1 Ja n "m (considerandparcurgerea pe linii). Pentru a nu realoca memorie la fiecare element adaugat, peTItTUfiecare link alocam memor-ia pentru m clemente :

int cont=Ojfor (i=O; i<n; i++)

(vI i] . reserve (m) ;

for (j=O; j<mi j++) v[i].push_back{++cont);)

In continuare putem prelucra aceasra matrice ca pe 0 matrice "nannaIa" (opera-torul de indexare fiind supraillcarcat) :

#include <iostream>#include <vector>using namespace std:int main (){int n , m, i, j, Xi

cin»n»m;vector< vector<int> > v{n);int cont=O;for (i=O; i<n; i++)

{ v[iJ.reserve(m)

for (j=O; j<m; j.++) v l i j . push_back (++cont) ;for (i=O; i<1"1; i+.t-)

for (~j=O; j<m; j++l ccu t e cc j jj fj]«' c ou t cc : \n' ireturn 0;

PROGRAM AREA iN LIMBA.IUL CICH-145CONTAIN ERE SECVENTIALE

<iostream><vector>

Clasa specializata vector<bool>

in fisierul antet vector este definita sl 0 clasa specializata : vector<bool>

(vectoriavfl.l1d clemente de tip bool). Spunem ca aceasia clasa este specializatadeoarece, pentru economic de memorie , 0 valoare de tip boal este implernentata peun bit, nu pe un byte.

Pentru aceasta clasa, iteratorii 1}i pointerii au fost rnodificati astfel incat sa indiceun bit, iar tipul reference este definit ca 0 clasa ce permite aceesarea ficcarui bitdin reprezentare. in acest mod, util izatorul acestui container specializat beneficiazade 0 interfata similara cu cea a unui vector, tara a constientiza efectiv lucrul eubiti.

Yom genera toate uumerclc prime <VMAX prin metoda ciurului lui Erarostcuc.Ciurul va fi reprezentat ca un vector<bool >, initializat eu valoarca t:r ue(ciur li l va fi true daca i cstc numar prim, respectiv false III caz contrar).

Parcurgem ciurul si, daca i cste nurnar prim, atune! eliminant din ciur totimultiplii lui -i.

Aplicatia 4. Ciurul lui Eratostene

Clasa speciatizata hash<vector<bool> >

Functia swap () este supraincarcata astfel incat sa pennita, prin cea de-a douaforma, interschirnbarea a doua elemente ale unui vector<bool>.

lncepand cu C+ + 11, este definita 0 spec.ializare ~i pentru clasa v ec t.o.r-cfioo L>,denumita hash. Aceasta specializare are supraincarcat operatorul ape} de functie t r ,care rerumeaaa 0 valoare hash calculata in functie de toate elernentele din veetorulrespectiv. Aceasta valoare flash perrnitc containereior v ec t.o r cbooL> sa poara fiutilizate drepr cheie in containerc asociativc nesortate.

Functii membre suplimentare

• flip()

void flip () ;

scntmba In timp liniar fiecare bit din container (true devine false, iar falsedevine true).

• swap ()

void swap (vector& x) i

static void swap (reference refl, reference ref2) ;

I#include#include

I

I

ii

I

I

fout«' \n' j

PENTRU L1CEU

i++)!gasit; j++l9asit=lj

fout«h[kJ«'k++)

Ilcazul 2(gasit::::i::::O; i<n && !gasit;for (j::::i+l; j<n &&

if (sli]==slj])

else{for

j--; i--;fout«j -i« I \n I j

for (k=i+l; k<=jj)

fout. close ()return 0;

144

r!

l j

r-«

~

,~

, .

r-'

,~

r

r

Page 74: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

int main (){int i, ji

for (i=2 j i*i<VMAX; i++)if (ciur[i]) Iii este prim

//elimin din ciur multiplii neeliminati aifor (j=i; j*i<VMAX; j++J ciur[j*i]=false;

/Iafisez numerele primefor (i=2; i<VMAx; i++)

if t c i ur j j j j coc t c.e j e e . 'ireturn a i

)

#define VMAX 100000using namespace stdjvector<bool> ciur(VMAX, true);

146PROGRAMAREA iN LIMBAJUL C/C-H PENTRU UCEU

lui

----CONTAINERE SECYENTIALE

int main (){int m, i, X, Y, nrc=Oifin»n»m;for (i=O; .i cm, i++)

{fin»x»Yiv[xJ .push_back(y)v[y] . push_back (x)

for (i=li i<=n; i++)if (!viz[i])

{fout«"Componenta conexa "«++nrc«'\n'dfs(i);f ou t;«-c ' 'vn ' j }

f ou t; . close ()return 0;

147

Ti

-

AplicaJia 5. Reprezentarea unui grafprin liste de adiacenpi

Yom reprezenta un graf neorientat prin lisle de adiacenra si apoi YOm descompunegraful in componente conexe, utilizand parcurgerca DFS.

Pentru a reprezenta listele de adiacenra, utilizam un vector v ell NMAX clementede tip vector<int> (unde ell NMAX am notat numarut maxim de varfur-i din graf),~ vector< vector<int> > V(NMAx) ;

.Citirn succesjv care 0 muchie x y din graf $i inseram pe x In Iista de adiacenjg alui Y $i pe y in Hsta de adiacenta a lui x :

I fin»x»y;

v[x] .push_back(y); v[yJ .push_back(x);

In cazuj in care graful este orientat, y nu mai trebuie adaugat in lista de adiacenjaa lui x.

Pentru a retine daca un varf a fast sau uu vizilat, utilizam un vector<bool>,denumit viz, pe care Il initializam ell false.

#include <fstream>#include <vector>#define NMAX 1001using namespace std; Iifstream fin("graf.in"); ,'.'fstream f ou t; ("graf. out") ; I1nt n; Ivector< vector<int> > v (NMAX) ; Ivector<bool> viz(NMAx, false); Ivoid dfs(int x){viz [x] =true; fout«x«' '; Ifor (int i.=(l; i<vLx].size();.i++) )

if (!viz[v[xJ[iJJ) dfs(v[x][i]); I

i

I

Observatie

o alta implementare posibila ar f sa alocam static vectorul de linii , iar liniile cecontin listeJe de adiacenta sa fie alocate dinamic (utilizand clasa vector). Declaratiagrafului reprezentat prin 1iste de adiacenta in accsr caz va fi :

l~ vec t o r cd.ne> G [NMAX] i

Accaste declaratie aloca un vector cu NMAX componente de tip v e c r o r-e i n t.>

(unde N¥.tA.X este numarul maxim de varfur! din graf).

5.2.Clasa deque

Pentru a utiliza aceasta clasa, trebuie sa includem fisrerul antet deque :

#include <deque>

Cuvantul deque (pronunjat "dec") este un acronim pentru double ended queue(coada cu doua capete sau coada ell dubla prioritate). Clasa deque implementeaza 0

srructura de date alocata dinamic., in care se realizeaza eficient operatii deeliminare/extragere 1a ambe1e capete. Spre deosebire de clasa vector, nu segaranteaza ca elementele sunt stocate intr-o zona continua de memorie. ci sumstocate in "blocuri". Acest mod de stocare permite implementarea eficicnta ainserarilor ~j extragerilor de Ia ambele capete -51 ofera un plus de eflcienta cand selucreaza cu secvente mari, in care realocarile de memorie sunt costisitoare.

Irerator ii clasei d e que SU11l iteratori cu acccs aleatoriu , ca si in cazul vectorilor,dar implementarea lor este tnai complcxa, fiind nccesara parcurgerca mai mulrorblocuri de clemente.

lurcrfata c1asei deque este cxtrem.de asernanatoare eu cea a clasei vector, prinurmare vorn prczenta succint fuuctiite membre al~ clasci.

r -)

c..J

Page 75: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

CONTAINERE SEC VENTI ALE 149

148 PROGRAMAREA iN L1MBAJUL CIC++ PENTRU LICEU

Operatorii relationali

Pentru clasa deque sunt supraincarcati tori oper-atorii relatiouali. compararea

realizandu-se din punct de vedere lexicografic.

Observatie

Functi ile insert () si erase () permit inserarea, respectiv stergerea elemen­telor de oriunde din container, inc1usiv din interior (in acesi caz iteratorii. pointerii $i

.referintele sunt invalidate).

Functiile mernbre care modified containerul deque

Ca pentru orice container. este supraindircat operatorul de atribuire funcuamembra' swap (), -funcua clear (), functiile insert () ~i erase (). Asemanatorcu cele din clasa vcc t.c r sunt definite funcri ile memhre push~bock ( ) ,

pop_back () , assign (), emplace (), emplace_back (). in plus, sum definite

unnaroarele functii membre :

• push~front ()

void push_front (canst value_type& val) ;

Insereaza un element ell valoarea val Ia inceput (inainte de primul element).

se executa in timp constant.

• pop_front ()

void pop_front() i

Elimina si distruge primul element.

Operatiile push_front () si p.op--..:front ( )

Aplicatia 6. Secvreg

Sa consideram secventc consntuite numai din paranteze rotunde !}i paranrezepatrate , adica din caractcrcleJ ) [ l . Prin definijie, 0 secventa de parantczc esteregulata daca se obtine aplicand urrnatoarele reguli :

1. () si l l sunt sec vente regulate;2. Daca A este rcgulata, atunci (A) ~i [A] sunt secvente regulate;3. Dad! A !ii B sunt regulate, atunci AB este secvenja regulate.

De exemplu, () () [J si [( ( ) ) ] [] sunt regulate, in timp ce ] [ sau [(] sau

{ [ }] nu sunt regulate.Se considerti 0 secvenja de parantcze. La fiecare pas se insercaza 0 paramezf

(rotunda sau patrata, deschisa sau inchisa) la inceputul sau .la sfarsuul secveutei.

I

Constructorii si destructorul

Exemple

Accesori

Functiile membre referitoare 10 dimensiune

Functiiie membre care returneaza iteratori

Creeaza un deque eli 0 elemente de tip into

deque<int> a(lOO,O);

Crceaza un deque ell 100 de elemente de tip int si initializeaza ell a toateelementeJe.

~string s;

, cin»s i

i deque<char> d (s . begin ( ), a . end ( ) ) ;

Creeaza un deque de dimensiune egala ell dimensiunea sirului s si copiaza indeque fiecare caracter din sirul a .

deque<int> a;

Constructorfi clasei deque sunt: similari ell constructorf clasei vector, fiindsupratncarcati constructorul implicit, coustructorul de umplere, constructorul bazajpe un domeniu §i constructorul de copiere. Destructorul distruge obiectul , elibenindmemoria alocata dinamic.

Clasa deque contine functiile begin (), end (), rbegin ()" rend () eusemnificana uzuala. lnccpand cu C++ II exists si functiile corespondente careretumeaaa c on e t;__iterator (cbegin (), c end (), crbegin (), crend ()).

Atarurl de functi ile uzuale size () , empty f) si max_size () in clasa deque

sunt definite functiile membre publiee resize () si, inccpand eu C+ + 11,shrink_to~fit (), in mod similar eu eele din clasa vector. Punctiilecapaci ty () §:i r ee er-vet ) nu sunt disponibile.

Accesul la elementele unui deque se rcalizeaza in mod similar eu accesul laelementele unui vector eu ajurorul operatorului de indcxarc l l Si a functiilor mcmbreat (), front(), back ().

r-r-

r-

r-e-

r-;i

l ,

r-

,~

r-r-

~

rc

r:

r-

,.

Page 76: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

,~

(campion 2(04)

Exemple

Cerinja

Scrieti tin program cafe sa dcterm inc, dupa fiecare pas, lungimca celei maiscurte subsecvente regulate (formate din caracrere consecutive ale secvcntei) Carecontine paranteza inserata Ia pasul respecriv.

Date de inirare

Fisierul de iesire secvreg. out conpne N Jlnii. Pe cea de a i-a linie va fiafi~ata iungimea celei mai scurte subsecvente regulate care contine paranteza inseraraIa pasul i. Daca nu exista 0 astfel de subsecventa, pe linia i yeti afisa o.

Restrictii

• Lungimea secventei initiale de paranteze este S 100 000• 1::; N s; 100 000

i.....j

....J

, 0

~

....J

15l

b. push_back (a) j

CONTAIN ERE SECVENTIALE

)a. push__back (c)

return 0 i

int la_sfarsit(char c)int ret;if ( la.empty() && ldeschis(c) && a.back()==pereche(c)

{ret=b.back()+2; /iretin lungimea s~cventei reg~~dLeb.pop_back(); a.pop_back()//elimin secventa regulata formatab[b.size()-l]+=ret;//actualizez in b lungimea secventei regulate

return ret;

ifstream fin ( "secvreg. in") j

of stream fout (" secvreg. out")deque<char> ai

deque<int> bistring Si

inline bool deschis(char c){ return c==' (' I I c==' [ '; )inline char pereche(char c)

(if (c==-') I) return I (' i

if (c==' ( ') return '} I ;

if (Co;=- I ] ') return ,[ I j

if (c== I [ ') return ,] I ;

int la_inceput(char c)int ret;if (la.empty() && deschjs(c) && a.front()==pereche(c) )

{r-e tcb . Er-orrt; () +2; / y r-e t S.n lungimea secventei regulat,e

a.pop__front() j b.pop~froJ1t(} j .•

b[OJ += r-e t:

----forinata deja), apoi actualizam,in b lungimea secvenlei care [ncepe pe ultima poziue.curnuJand lungimea sccventel regulate eliminate. In caz contrar, inseram in a la finalcaracteruJ ddt, iar ill b inseram la final valoarea 0 (fiiudca aceasta este lungimea

secventei regulate formate eli caracterul ddt).Cand trebuie sa mseram Ia tnceputul cozii a 0 paranteza deschisa, iar Ja IneeputuJ

cozii a era paranteza jnchisa corespunzatoare. se formcaza 0 secventa regulars cu 2mai mare §i executiiru aceleasi operatii ca in cazul precedent, dar la Inceputul cozilor

cu dubla prioritate ,

ffinclude <fstream>#include <deque>using n~espace std;

PROGRAMAREA iN UMBAJUL C/C ++ PENTRU UCElJ

secvreg. in secvreg.out secvreg.in secvreg.out( ] 0 rJ ) a3 0 3

21 ) 2 0 )

6a ) a (

a ( a (

150

Fisierul de inn-arc secvreg. in contine pe prima lillie secventa iniliala deparanteze. Pe cea de-a doua linie a fisierului de inn-are se afla un nurnar natural N ccreprcztnta numarul de pasi. Fiecare dintre urmatoarele N Jinii contine un nurnarnatural A si un caracter C separate printr-un singur spauu. Dad! A este 0 (zero)atunci caracterul C este inserat Ia Inceputul secventei ; daca A esre 1 atune! caracterulC este inserat la sfarsirul secventei.

Date de iesire

Soltqie

Vom utihza doua cozi eu dubla pnoritatc :

1. coada cu dubfa prioritare a eu clemente de tip char in care inseram succesivcaracterele din sirul initial, apoi pe cele specificate in operatiile din flsicr ;

2. coada cu dubla prioritare b eu elemente de tip int; b [i ] = lungimea secvcnjeiregulate care Incepe la pozitia i.

Initial inseram in ordine toate caracterele sirului citit in coada ell dubla prior-irate a.Pentru a pastra ordinea, fiecare nou earacter va 11 inserar ia sfarstrul cozri. Candinseram 0 paranteza inchisa Ia sfarsirul cozii, jar pe ultima pozlpc ill a estc parantezadeschisa corespunzatoare, deducem ca se formeaza 0 sccverua regutara ell lungimcacu 2 mal marc dedit eea deja existents pe accasta poztuc. Prin urmare,' eliminantdin cozile a, rcspectiv b clcrncntelc finale (adica climinam din a sceventa regulata

Page 77: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

15" PROGRAMAREA IN LlMBAJUL C/C++ PENTRU LJCEliCONTAINERE SJ:-XVENTIALE 153

\

• string 5;

cin»s;:: list<char> d(s.begin(}, s.end());

Creeaza 0 lista de dimensiune egala cu dimensiunea ~irului s si copiaaa in llsta

fiecare caracter din sirul s.

list<int> a;

Creeaza 0 Esdi ell 0 clemente de tip into

list<int> a(l'OO, 0);

Creeaza 0 Ilsta ell 100 de clemente de tip in t ~i illitializeaza ell 0 toatc

elementele.

i

i,l .

~

, .

r-'

~

I

i

return ret;)

a.push_front(c)j b.push_frant(O);return OJ

int main ( )char c :int i, paz, n;fin»s;b.push_back(O);for (i=Oi i<s.size(); ++i) la_sfarsit(s[i]);fin»n;for (i=O; i<n; ++i)

{fin»poz»c;if (paz) fout«la_sfarsittc)«'\D';

else fout«la_inceput(c)«'\n';)

fout. close () ;return 0;

Exemple

Functiile membre care returneaz/i iteratori

Clasa list contine functiile begin (), end () , rbegin (), rend () euficatia uzuala, [ncepand eu C++ 11, exista ~i functiile eorespondeme careneazll const_i terator (cbegin () , cend () , crbegin () , crend ()).

semni­retur-

,, ,

!

r-r-! ,

r--t

i,

i

~

5.3. Clasa list

Pentru a utiliza aceasta clasa trebuie sa ineludem fisierul antet list:

#include <list>

Clasa list implementeaza 0 strucrura de date care perrnite inserarea ~i extra­gerea elementelor din strucrura in mod eficient, indiferent de pczijia acestora,precurn sl parcurgerea clementelor in ambele scnsurt. Ca irnplernentare , elementelecontainerului list sum organizate ca 0 Iista dubJu lnHin!uita. )teratorii pentrucontainerul list: sunt bidirectionali, ceca ce "inSean1na ca nu avem acces direct Jaelementele unei liste , dar putem parcurge elementele in arnbele sensuri. Un posibildezavantaj al aeestui container este memoria supjimentara neccsara pentru memo­rarea legatur-ilor tn lis~a.

Constructorii ~i destructorul

Constructorii clasei list sunr similari ell construciorfi claselor vector ~i

deque fiind supraincarcap constructorul implicit, construetorul de umplere. eon­structorul bazat pe un dorneniu si eonstruetoruJ de copiere. Destructorul distrugeobiectul , eliberdnd memoria alocata dinamic. Exceptand constructorul implicit, toriconstructorf sl destruetorul au complexitate liniara,

Functiile membre referitoare la dimensiunea iistei

in c1asa list sunt disponibiJe numai functiile uzuale size (), empty () ~i

max_size () .

AccesoriEste posibil accesul doar la primul ~i la ulrirnul element allistei (functia front ()

retumeaza 0 referinta la primul element, iar functia back () returneaza 0 rcterlnta Ja

ultimul element a1 listei}.

Functiile membre care modijica lista

Ca pentru or-ice container, sunt supraindircari operatorul de atribuire =, functiamembra swap (), fuuctia clear (), functiile insert () sl erase () . Ascmanarorell cele din clasa d ecrue sum definite fuuctiile rncmbre .puahLbac k () ,push.__front (), pop._back (), pop_front (), assign (). emplace (i.

emplace_back () ~i emplace__front ( ) .

Operatiile specifice

Clasa container list: contine functii mernbre publice care permit efectuarea uno!'

operatii specifiee ell liste :

Page 78: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

ir..

'-'154 PROGRAMAREA iN UMBAJUL CIC-H PEl\'TRU UCEU CONTAIN ERE SECVENTIALE 155

void remove (const value_type& val);

Puncna remove () elimlna si dlsrruge in limp liniar toate elementele dill Hsracurenta egale cu valoarea val.

,,

-'

'-!

void sort ()template <class Compare>void sort (Compare comp);

Ordoneaza elemcutele listei curente crescator considerand operatorul < (pentruprima forma), respectiv considerand eriteriul specificat de prcdicatul binar camp(pcntru a doua forma), mutand elementele listei. Complcxitatca algoritmului de sor­tare este O(N log N), unde cu N am notat numarul de clemente din liSla.

• reverse ()

void reverse ()

• sort ()

Realizeazf interclasarea listei curente cu -lism x , mutand elementele din x in \istacurenta pe poz.itiile corcspunzatoarc. Evident, sc consldcra ca initial elementele din!ism curenta si elememele din lista x sunt deja ordonate -crescator considcrandoperatorul < (pentru prima forma), respectiv ordonate conform criteriului specificatde predicatul binar camp (pemru a doua forma). Interclasarca se realizcaza in timpliniar.

iterator

list& x ) j

list& X, iterator i) ;

list& x, iterator prim,

remove (-)

• splicer)

void splice(iterator paz,void splice(i'Cerator paz,void splice{iterator poz,u L tim) ;

Functia spl j ce () muta in containerul curenr, Ja pozma indicata de iteratorulpoz, clemente din lista x. Prima forma mura toate elementele din x, a doua formamura dear elementul indica1 de iteratorul i, iar a treia forma muta elementele din xaflate in domeniul [prim, ul tim) . In urma accsrci operatii dimensiunea listei curemel)i a Iistei x se rnodifica. Functia splice () se executa in thup constant pentruprimele doua forme, respectiv in timp liniar, functie de dimensiunea dorneniuluipentru a treia forma.

• remove If (J Inverscaza in timp liniar ordinea elementelor din Iista curenta.

temp2ate <class Predicate>void remove if (Predicate pred)

.Puncna remove_i f () cllmtna §i distruge in (imp liniar toate elementele din Iistacurenta pentru care predicatul pred are valoarea true.

• unique ()

void unique();temp1ate <class BinaryPredicate>void unique (BinaryPredicate binary-pred);

Dupa apelarea primei forme a functiel unique ( ) , lisra curcnta nu va mai contineclemente consecutive de valori egale (duplicatele fiind eliminate). Dupa apelareacelei de a doua forme a functiei unique (), Iista curcnra nu.va mal contine elementeconsecutive pentru care predicatul binar binary_pred sa returneze valoarea true.Dintr-o succesiune de valor! pcntru care binarY_'pred rerurncaza true pentruoricare doua valori consecutive, se pastreaza doar prima valoare, celelalte fiindeliminate. Elemcntele eliminate sum distruse. Complexuatea functiei unique () cstellniara.

• merge ()

Operatorii relationali

Opcratorti rclationali au fest supraincarcati pentru clasa f orward_l i s t,

compararea realizandu-se din punct de vedere lexicografic.

Aplicatia 6. Coment

Elevii de clasa a XIJ-a au un sisrem propriu de a-si rransmite comentariile laromana. in urma tndejungatel lor colaborari, si-au format un sistem de relatii astfelmeat, orieare ar fi doi elevi, unul primestc comentarii de Ja celalalt. Evident, oricecornentariu primit poate fi transmis mai departe.

Cerinja

Presupunand ca In clasa a XII-a sunt N elevi , numerotati distinct de la 1 la N, :;;ica sisternul de relatii dintre elevi esre cunoscut, scrieji un program care sa gnseasca 0

modalitare prin care un comentariu, rransmis de unul dintre elevi , sa ajunga pe la torielevii 0 singura data.

Date de intrare

'--'

void merge (list& xl;

template <class Compare>void merge (1 is t& x , Cornper c comp) i

Ftsierul de intrare c omeri t . in confine pe prima linie numarul natural N,

reprezcntand numarul de elevi. Pe urmatoarcle N* (N-I) /2 linii se aila pcrech i x yde nurncrc naturale distincte cuprtusc intre 1 -~i N, cu scmnificatia c;J elcvul xtransmite comentani elevul ui y.

Page 79: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

Olimpiada Municipala de Informatica Iasi , 2002

Restriqii

Exemplu

• 2 .s; N .,;. 100• Daca ex ista mai multe solutii , se va determina una stngura.

157CONTAIN ERE SECVENTlALE

citire()Dc t e rrru.ne ()Scrie() ;return ,0';

int main ()

Inseram pc y pe acest drum intre Xi si Xi+l, obtinand un drum elementar ell

lungimea cu 1 mai mare; procedeul se repeta cat timp drumul nu estehamiltonian.

Yom reprezenta graful prin matrice de adiacenta deoarece numarul maxim devarfuri din graf este relativ mic (100) si este necesar sa identificarn arce atilt infuncjie de extremitarea lor initiala, cat si in functie de extremitarea lor flnala. Drumulva fi un obiect de tip list denumit d, deoarece sunt necesare operatii de inserareeficiente ill diverse pozitii. Pentru a verifica eficient daca un varf apartine sau nudrumului curent vom utiliza un vector<booJ.> denumit uz (valoarea falsesernnificand faptul ca varful nu aparjine drumului).

Programul implementeaza procedeul descris in demonstratia existentei drumuluihamiltonian.

#include <fstrearn>#include <list>#include <vector>#define NMaxVf 101using narnespace std;

void Ci tire ()veid Deterrnina();void Scrie ()

int n;bool G[NMaxVfJ [NMaxVfJvector<bool> uz;list<int> dj

~~X 1 ------lJr.. ,.' ---+ Xi ---+ Xi+l ------lJr.. .•. ---+ Xk

_ exista arc de Ia 'y Ia Xl-; (in caz contrar , drumul nu ar fi maximal. deoarece amputea extinde drumul in dreapta, adaugand pe y dupa xJ ;exista eel putin 0 pereche de varfuri consecutive pe drum x x", astfcl incatcxista arcul (Xi,y) si arcul (y,Xi+l) (in caz contrar nu am putca pleca dinXl cu arce catre y si sa ajungem in Xk cu arce plecand din y) :

cement. in cement. out4 2 4 3 11 21 43 12 43 24 3

PROGRAMARBA iN LIMBAJUL CIC ++ PENTRU UCEU156

Soliqie

Putem asocia problemei un graf orientat in care varfur-ile sunt elevii; cxista arcde la varful x la varful y daca elcvul x transmite comentarii elevului v . Din enuntulproblcmei deducem ca graful esre complet $i antisimetric (oricare ar fi doi elevi x ~i

y exista exact un arc Intre x ~i y), adica este graf rurneu, Problema solicitsconstruirea unui drum hamiltonian III acest graf (drum care trece prin fiecare varf algrafului exact 0 data). Putern demonstra ca In 'or icc graf turneu exista un drumhamiltonian. Demonstratia este constructiva $i va sta Ia baza algoritmului nostru.

Vom alege un varf oarecare din graf (de exemplul varful 1) ~i construirn un drumelemental' maximal pornind din acest varf. Initial' drumul. este format dintr-un singurvarf xj e L. Cartimpeste posibil, 'exrindem drumul in dreapta (mai exact, determinantun varf y care nu apartine drumuJui si pentru care exista arc de la ultimul varf de pedrum la y ~i adaugam pe y Ia sfarsitul drurnului}. In mod similar, extindem cat limpeste posibil drumul in stanga (determinam un varf y care nu apartine drumulut sipentru care exista arc de la y la primul varf aJ drumului -51 'il inserarn pe y pe primapozitie pe acest drum).

Sa notarn cu Xl, X2, ... , Xk drumul elementar maximal astfel creat, Exista douacazuri posibile :

1. drumuI creat contlne toate varfurile grafului ; 'in acest caz ne-am atins scopuJ: amconstruit un drum hamiltonian;

2. drumul creat nu confine toate varfurile grafului ; In acest caz cxlsra un varf y carenu apartine drumului .. Referiter la acest varf y putem face urmaroarele afirmati i :

e,i-ista .~rc dc'la XJ la y(in caz con~rar, drumul nu ar fi maximal, ci ar putea fiextins in stanga inserand pc y Inaintea lui xJ;

Date de iesire

Fisierul de iesire c omeri t . ou t; contine pe prima linie 0 succcsiune de N numer­naturale distincre cupnnse inrre 1 .)i N, reprezentand ordinea 111 care elevi i prime.sccomentariul,

r

r-'

-

r

Ii

~

~

, ,

r-i ,

r-L

Page 80: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

J58 PROGRAMAREA IN UMBAJUL CIC++ PENTRU LlCEU CONTi\INERE SECVENTIA1_E 15~

~

void -Cd t Lr-e (l{ifstream fin {vcomen r . in") ;int x, y, ffi, i;fin»n;u2~vector<bool>(n+l,falsel

m:::::n*(n-ll/2;for (i=O; i<m; ++i)

{fin»x»y; G[x] [yJ:::::true;fin. close ()

)

void Serie ()(ofstream f ou t; ( "coment. out" ) ;list<int>::iterator it;for (it:::::d.begin(); it!=d.end(); ++it) fout«*it«'fout«' \11';

fout.close(); )int cautpred(int vi){for (int i=1; i<=n; i++l

if (!uz[i] && G[i] [vf]) return i­return 0;

)int cautsucc(int vf){for lint i=1; i<=nj i++)

if (!uz[i] && G[viJ [iJ) return i;return 0-

void Determina ( ){int X;list<int>: :iterator it;Ilinitializam drumul eu varful 1uz[1]=true; d_push_back{l) j

Ilextindem drumul catre dreapta, cat timp este posibildo

{x=cautsuce(d.back() I;if (x) {d.push_baek(x); uz[x]=true;)

}while (x)/lextiLdem drumul catre dreapta, cat timp este posibildo

{x=cautpred(d.front()};if (x) {d.push_front(x); uz[xJ=true;)

}while (x);for (X~2i x<=n; x++)

if (! u z l x l I I Ix nu apartine d r-umu Lu i.{I/caut pozitie de inserarefor (it~d.begin(l; G[*it] l x L, +-liL);

/Iinserez pe X i_n poziLia curentad.insertlil,xl

)

5.4. Clasa forward_list

Clasa forward_list a fast introdusa in STL lnccpand cu C+ -I- ] 1 si, pentru ao utiliza , trebuie sa includem fisieru! antet forward_list:

)i #include <forward_list>

Clasa forward_list implementeaza 0 strucrura de date care per-mire Inscrarea~i extragcrea elementelcr In timp constant, indiferem de pozlna acestora. Ca imple­mentare, elementele containerului forward_list sunt organizate ca 0 Iista simpluinHinruita.Cu alte cuvinte , spre deosebire de La s t , unde fiecare element conjineadoua Iegaturi (una catre urmarorul element din lisUi si una catre precedentul elementdin lista), in forward_list se retine doar 0 singura legarura, catrc urmatorul cle­ment din Jista. Prin urmare, se reduce dimensiunea memor-iei supfimcnrarc neccsarapentru rnemorarea legarurilor.

Iteratorii containerului forward_list sunt iteratori de Inaintare (forwarditerators), prin urmare parcurgerea clcmcntelor este posibila doar Inrr-un singur sens(de Ja inceput catre sfarsit). .

Constructorii, destructorul ~i operatorul de atribulre ::: sunt similari clasei La.nt..

Vern evidentia In conunuare diferentele specificc clasei forward_list, pcntrudiferitele categoni de functil.

Functiile membre referitoare fa dimensiunea listei

Containerul forward._i.ist este singurul container standard care, din motive deeficienta, nu dispune de funcjia size (). Astfel , lIU mai este neccsara retinerea ~i

acrualizarea permanents a dimensiuuii curente a listei, Singurele fuucjii disponibilereferiroare 1£1 dimensiunca coutainerului sum empty () §i maxsize () . Pentru a aflanumarul de clemente din listii se poate utiliza algoritmul distance. De exemplu ,dace FL este un obtect de tip t'orward_list, pentru a deterrnina in variabila nrnumarul de elemente din Iista FL putem apela functia di stance avand ca parametr iinceputul §i sfarsltul listci :

I' nr=distance(FL.begin(), FL.end())

~

-'

-'

,~

~

-'

, ,

'-'

-'

~

Page 81: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

160 PROGRAM AREA iN LIMBAJUL CIC++ PENTRU L1CEU CONTAINERE SECVENTIALE 161

r

l j

r--'

l ,

-I .

r-',

Accesori

Este posibil accesul dear la primul element al listei urillzand functia f ron t ( ) ,

care rerurncaza 0 refermta la primul element.

Functiile membre care returneaza iteratori

Clasa forward_list contine functiile uzuale begin (), end (), cbegin ()si cend () cu semnificatia uzuala. in plus, sunt definite doua functii denumitebefore_begin (), respectiv cbefore_begin () care rerurneaza un iterator,respectiv const_i tera tor care indica pozitia dinaintea primului element din lista.Evident, acest iterator nu poate f dcrefcrentiat, ci poate fi folosit pentru a indicaaceasta pozitie in apeJuri ale functi ilor emplace_after (), insert_after (),erase_after () sau splice_after ().

Functia rerumeaza un iterator care indica poz.itia elemcntului care urmeaza dupaultimul element eliminat.

• errrpLe c ejaf t e r ()

template <class ... Args>iteratar empJ.ace_.af~er(const_it_eratorpaz, Args&& .. p) i

Functia emplace_after () construieste un clement (urilizand consrructorulcorespunzator parametrilor specificati dupa itcratorul poz) $i insereaza elementulcreat dupa eel indicat de poz.

Observatie

Functiile insert_after () $i emplace_after () pot fi utilizate $i pentruinserarea unui element 1a incepurul listei, daca iteratorul paz indica pozitla pre­cedenta primului element din lista (tteratorul returnat de functia be£~re_begin ()).in mod similar poate fi sters din lists primul element cu functia erase_after ().

" erase_af t e r ( )

Functiile membre care modified lista

Asemanator clasei list sunt definite functiile membre push_front (),pop_front (), assign (), emplace (), empLac eif r on t; (), resize (), swap ()si clear (). Urmatoarele funcjil sunt specifiee clasei forward__list :

• insert_after ( )

i~erator erase_after (canst lterator paz) i

i t.e r a t o r e r a s e __after (const_ L t.e r a t.o r- pOL,const lteratar ultim)

Funcna e-ra sej a.f t e r- (.) elimina din lista cleniCJ1tul de dupa ccl indicat deiteratoruJ paz (prima forma), respectiv elemcmele din dOlllcniul (paz, ul tim).

forward_list& 1"1,);

forward_list& FL,

spl ice_after (const__ i terator poz,splice_after (const_iterator poz,

const_iterator i)isplice_after (const_iterator poz, forwa:::-d_list& 1;'L,

const_iterator prim, const_ltel-aLor u Lr Lm)

vciid

yoid

void

Operatiile specifice

Clasa container forward_list contine functiile membre publice remove () ,remove_i f ( ) , sort ( ) , reverse ( ) , unique ( ) , merge () cu efect similar celordin clasa list. Functia splice () a fost inlocuita cu functia splice_after () :

• ap l t ce j e f t er- ()

Observatie

Deoarece nu este necesara parcurgerea listei in ambele sensurt. pentru imple­mentarea solutiei problemei Content am fi putur utiliza $i 0 lists simpJu inIantuita(Eo rwar d j La e t). Desigur, ar fl trebuit sa retinem permanent poz.iria precedentacelei in care realizarn inserarea, ceea ce ar fi condus la un cod mat putin elegant.

Functia ap Lc.cej af t ert) mum 111 containerul curent, dupa elementul indicat deiteratorul poz, clemente din lista FL. Prima forma muta toate clementcle dill FL, adoua forma mura doar elemcntul indicat de ireratorul i, tar a treia forma muraelementele din FL aflate in domeniul [prim, ultim). in urma acestci operatii dimen­siunea listei curente si a listei ·FL se modifica.

l

. ~I !I

insert_after(const_iterator paz,const value_type& val);

insert_after (const_iteratar paz, size_type TI,

const value_type& val);<class InputIterator>insert_after(const_iteratoL paz,

InputIterator prim, Inputlterator ultim}lnsert_af~er(const_lteratorpoz,

initializer_lis~<value_tYPe>ill

iterator

templateiterator

iterator

Punctia insert_after () Iusereaza in lista curenra.vdupa elementul indicat deiteratorul paz, un element cu valoarea val (prima forma), n elemente ell valoareaval (a doua forma), copii ale elementelor din domeniul [prim, ul t.d.m) (a treiaforma) sau copii ale elementelor din lista de initializare li (ultima forma). Functiarerurncaza ca rezultar un iterator care indica pozijia primuiui element inserar.

~ iterator

t

II

ri :

!

r

r

r-I

nI

r, .

I

~

J

Page 82: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

I

j

,,,.., DnrV-,n" "A" Dr:: A, iN LIMBAJUL C/C+-j PEN'rHl) L1CEU CONTAINERE SECVENTIALE 163

'«vl.capacity()«'\n' ;

Funcriile membre care modified containerul array

5.6. Exercitii §i probleme propuse

Operatorii relationali

Pentru clasa array sunt supraincarcati toti operatcrii relationali, compararearealizandu-sc din punct de vedere lexicografic.

,

:......;

, i" .~

"-!

, 1

,~

d.100 1001.0 10.

c.vector<float> v1;vl.resize(lOO) ;

a.vector<float> vl(IOO);

2. Care dmtre urmatoarele secvente creeaza un vector eu 1 00 componente reate :

b.vector<float> vl;v1.reserve(lOO) ;

d. vector<float> vl;vl=vector<float> (lOO) ;

1. Ce va afisa pe ecran urmatoarea secventa de instructiuni :

vector<char> v1;vector<char> v2(lOO);vl=v2;v L [0] ==' s ' ;co~t«v1.size{)«'

vl.resize(10) ;cout«v1. size () «' '«vl. capaci ty ()«' vn ' ;

a. Nimic, deoarecc aceasta sccventa produce b.eroare la executie (v1 este vid, prin urmare 0 0nu ne putem referi la vl ! 01) ; 1.0 10;

c.100 10010 100;

Ca pentru orice container, este supraincarcara functia membra swap () careinterschimba in Limp liniar elementele a doua containere. In plus, este definita functia

membra fill () :

I void fill (const value_type& val) ;

Atribuie tuturor elementelor din container valoarea val.

Accesori

Clasa array contine functiile begin () , end ( ) , rbegin () , rend () , cbegin () ,cend ( ), cr-beqLn ( ) , crend (), eu semnificana uzuala.

Functiile membre referitoare la dimensiune

Clasa array a fast introdusa incepand ell C+ + 11 si poate fi urilizara dacaincludem fisierul antet array:

1\ #include <array>

Accasta class hnplcmcnreaza a succesiune de dimensiune flxa fermata din ele.'mente de acelasi tip, srocate tntr-o zona continua de memorie. Aceasta structure estefoarte asemanatoare eu tablourile unidimensionale din limbajul C, dar dispune de 0

serie de functii membre care fae posibila utilizarea acestora 111 mod similar cueelelalte containere standard.

Spre deosebire de clasa vector, memoria ajocata elementelor unui. array estefixa , nu se aloca dinamic, Prin urmare, dimensiunea unui array nu poate f modi­fleets dinamic ~j nu este necesar sa fie stocata intern.

Declararea unui obiect de tip 'array:

array<Tip, Dim> ob;

Functiile membre care returneazd iteratori

5.5. Clasa array

undc Tip reprezinta tipul comun al elementelor, iar Dim dimensiunea flxa (nurnarulde elemente).

De exemplu, pentru a declara un array a cu 10 clemente de tip int:

array<int, 10> a;

Singurele functii membre referitoare la diincnsiune sunt size (), empty () ~i

max_size {}. Punctiile size () ~i l.TIax_size () rerurneaza aceeasi valoare, dimen­siunea fixa specificata la declarare.

Accesul Ja elementele unui array se realizeaza in mod similar cu aceesul laelementele unui vector, cu ajutorul operatoruiui de indexare [J si a functiilormembre at {}, front (), back (). Este de asemenea implementara functia membradata () care rerurneaza un pointer can-e lnceputul zonei de mcrnor-ie care conuncelementele containerului.

3. Ce se va afisa pe ecran dupa executarea urmatoarei secvente de instructiuni ,

dad! de la tastatura se introduce Mama are mere.

striYlg Sj

cin»sjvector<char> v1(s.begin(}+1, s.end());cout«v1. size ()«' "<cv I . capacity {)«' \n '

~

Page 83: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

'')4 PROGRAMARFA iN LIMBAJUL C!C++ P£NTRU L1CEU CONTAINERE SECVENTIALE 16S

list<int>: :iterator it;for (it=Q; it<v.size{); ++it)

cout«*it«'

vl.insert{vl.begin()+2,s.begin{), s.end());cout«vl. size () -cc ' '«vi. capaci t.y ()«' \n' ;vl.erase(vl.end()-l) ;c ou t c-cvL . size ( )«' \ <ev L. capaci ty () «' \n' ;for (int i=O; i<vl.size{); i++) cout«vl[i];

4. Presupunand ca este necesara 0 srrucrura de date secventiala care sa permits inse.rari ~i extrageri de elemente doar de la inceputul sau sfarsitul secventei, carecontainer rcprezinta cea mai eficienta implementare? Justificati raspunsul.a. vector i b. deque;c. list; d. Nlciunul dimre acestea.

5. Care dintre urmatoarele secvenje afiseaza elementele listei v?

1: list<i.nt> v·

r-r-

li~

IrI .

a.

~ for

b.

tint i=O; i<v.size()cout«v[i]«'

++i)

v2.reverse() ;list<int>: :iterator itl=vl.begin(), it2=v2.begin{)itl++; it2++;v1.spliee(it1, v2, it2, v2.end(») i

8. Ce se va afisa pc ecran in urma executiei urmatoarei secvente :

deque<int> d;for (int 1=1; i<5; ++i) d.push_back(i};deque<int>: :iterator it=d.begin(}+2;d.erase(itl,-cout.«*it« '

9. Considerand urmaroarca definitie a functiei La f e L ()

bool lafel(char el, char e2)(string s("aeiouAEIOU"),-return s. find (el) <string: : npos&&s. find (c2) <string =; rrpos :

Ce coutine lista d dupa execurarea urmatoarei secveute ?

string s ("Mamaia si Aida vorbeau n eaosvj :list<char> o(s.begin(), s.end())id. unique (lafel) ,-

10. Pentru care dintre urmatoarele declaratli, constructia it+l este valida ?

Care dintre urmaroarele instructiuni elimins primul element din containeruldeque<int> d:

,r

c.

I:list<int>: :iterator it;~ for (it=v.b:9in(); it<v.end(): c ou t c c e Lt;« c ' ;

++it) 11.

a.vector<char>; :iterator it;c. deque<int>::iterator it;

b. list<double>= :iterator it;d. Niciuna dintre variautele precedeme.

6. Ce elemente contin listele v1 ~i v2 dupa e;.ceutarea urmatoarel secveute :

int i;list<int> v1;for (i=1; i<5; ++i) vl.pusD_back(i);list<int> v2;for (i=1; i<9; i+=2) v2.push_back(i);v L. merge (v2) ;

7. Ce elemenre contin listele v1 ~i v2 dupa executarea urmatoarei secvente :

int i;list<int> vI;for (i=1; i<5; ++1) vl.push_back(i)J.is·t<.int> vz .for (i=1; i<8; ++i) v2.push_back(i)

b. d.erase(d,front(»)d. d.pop () ;

a. d.pop_front();c. d. erase (d. begin () ) ;

J2.

14. Utilizand clasa specializata vector<bool>, implernentati operatiile eli multimide numere naturale <VMAX (reuniune , intersectie , diferenta, diferenta simctrica).Comparati operatiile astfel implementate ell varianta ee utilizeaza vector<int>~i algoritmii standard de lucru cu multimi din STL.

15. AnneVasile jcaca (din nou ! ) jocul sau preferat eu impuscaturi. Pcrsonajul Sal! are 1a

brau N arrne, a~c~~te in N husc spectate, uumerotate de la 1 Ia N.· Anna. din husa Lare puterea pb j (1"";i.<N).

Considerand llsta list<char> d , utilizati functia membra unique () pcnrru 3

elirnina din lista spatule redundanrc.

13. Considcrand vcctorul vector<int> v, scricti 0 secverua de instructiuni caresa elimine toate elementele pare din vector. Real izatl aceeas i operatic pentrulista list<int> d, intr-o maniera diferita. Peutru care dintre cele douacontainere eliminarea se realizeaza mai eficient ?

++it}

d.

~' list<int>: :iterator it;: for (i t.=y..begin ( ) it! -ra . end ( ): c ou t c-c e Lt;«.c ' j

r

l i

,.

,.

!

Page 84: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

166 PROGRAMAREA iN LIMBAJUL CIC++ PENTRU LICEU CONTAINERE SECVENTIALE 167

I

J

in camera armelor a gasit Manne, asezate pe pcretc, in M locadi. numerotate de la11a M. Pentru flecarc anna j (l:S:jS:M) este cunoscuta puterea sa PCj_

Vasile poate inlocui arme pe care Ie are la brau ell anne aflate pe perete incamera armelor. La 0 inlocuire el ia arma de pe perete din locajia j (l,:::';j'::;M) ~i 0

pune Ia brau in husa i (l.:'O:i::::N), iar arma din husa i 0 pune pe perete in locatia j,

Cerinta

Scrieti un program care sa determine sum a maxima a puterilor armelor pe care Ieva avea Ia brau Vasile dups efecruarea Inlocuirilor.

Date de intrare

Fisierul de intrare anne. in coniine pe prima linie numereJe naturale N M,reprezentand numarul de arme pe care Ie are la brau, respectiv numarul de anneaflate in camera armelor. Pe a doua linie se afla N numere naturale pb i pb2 •••

pbN rcprezcntand in ordine puterile armeJor pe care Vasile Ie are la brau, Pe a treialinie se afla M nurnere naturale pel PC2 ... PCM rcprezcntand in ordine puterilearmelor aflate in camera armelor. Numerele scrise pe aceeasi linie sunt separate prinspatiu.

Date de iesire

Flsierul de iesire arme . ou t va contine 0 singura linie pe care va fl scrisa sumamaxima a puterilor armelor de la braul lui Vasile, dupa efectuarea inlocuirilor.

Restrictii

• 1:s;. N, M s: 1000

• Puterile armelor sunt nurnere naturale s: 1 0 0 00.

Exemple

arme.in anne.out3 2 163 1 74 5

Ohnjpiada Judeteana de Infonnanca, 201216. Segm

Sa consideram N scgmente Inchise situate pe axa OX. Pentru fiecare segment secunose extremitarea initiala x §i extrcmitarea finala v.

Cerinpi

Sa se determine a multime fermata dintr-un numar minim de puncte distincte deabscise intregi situate pe axa OX, eu proprietatea ca orice segment conrine eel putindoua punete din multime.

Dale de intrare

Pisierul de Intrare s egm. in contine pe prima linie numarul :natura"} I\J. Peunnatoarele N Iinii sunt descrise cele N segmeme, cate un segment pe 0 linie. Pentru

fiecare segment sunt specificate doua numere naturale separate prin spatiu x y. reprezentand extremiratile segmentului.

Date de iesire

Pisierul de iesire e eqm . au t va contine doua linii. Pe prima linie este scris unl1umar natura] MIN, reprezentand nurnarul minim de puncte din multimea deter­minata. Pe cea de a doua linie sunt scrise MIN numere naturale in ordine strictcrescatoare, separate prin spatiu , reprezentand abscisele punctelor din rnultime.

Restricjii

• 1 ~ N s: 3000o < x < y < 10 6

• Daca exista mai multe solutli, aflsan oricare dintre acestea.

Exemple

eesrm, in segm.out

5 51 10 5 10 12 23 2410 121 101 1023 24

.campion 2009

17. CampusUn sir de numere se nurneste campus daca indephneste simultan conditiile :1. a. contine ~D numar impar de elemente ;2. b. elementul de la mijlocul sirului esre mai mare sau egal cu toate elementele

care i1 precede ~i mai mic sau egaJ cu toate elementele care II succeda.

D~ exemplu, sirul (1, 6, 2, 8, 18, 28, 9) este compus.Secventa ah a;,:, a3, ... , ai se numeste prefix de lungime i al sirului a.

Cerirua

Sa se determine lungimea celu! rnai lung prefix compus al unui sir de numere.

Dale de intrare

Fisierul de intrare campus. in contine pe prima linie un nurnar natural Nreprczeutand numarul de valori din sir. Pe cea de a doua l.inie sunt scrise N numereintregi separate prin cate un spatiu. reprezentand sirul.

Date de iesire

Fisierul de icslrc campus. out va contine 0 singura linie, pe care va fi scris uusingur nuruar natural reprezentand lungimea maxima a unui prefix compus,

u

:.....J

-'

u

~

....J

....J

Page 85: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

..169

coxrAINERF SECVENTIALE

168 PRQGRAMARFA CN LIMBAJUL CIC++ PENTRU LICEU

.campion 2008

1 4 3 8 10 8 9 7 2 11

Restrictii

N , 1 000 000

ai':::;; lO",pentruoricel:Si::;;N

.campion 2008

ExplicafieVectorul initial : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15·s 2 11 afi~ea:lli suma clcmentelor de la pozitia 2 la poznia \11: 2+3+4+5+6+7+8+9~10+11=65I 10 15 inverscaz1i elemcmele din subsccventa de la pozit

ia

10 la pozitia 15. Se obtine vectorul :1 2 3 4 5 6 7 8 9 15 14 13 12 11 10I 1 10 inverseaza elementele din subsccvcnta de la pozit

ia1

la pozitia 1.O. Se obtine vectorul :15 9 8 7 '6 5 4 3 2 1 14 13 12 11 10S 5 1 0 afi~eaza suma elemcme10r de la pozi~ia 5 la pozi!ia

10 Inclusiv : 6+5+4+3+2+1=21

Exemplusecvop.in I secvop.out

15 4 16 5

S 2 11 2 1

I 10 15I 1 10S 5 10

(1) ~i

Explicatii

Exista doua prcfixe compusc :(1.4.3.8.10.8.9).

campus. out.

7

campus. in

l ~.;

a ~

Exemplu

10

18. Secvop

va f scris unrrebuie sa' fieo 'singura linie pe care

minim de purcelusi ce

4 I Numa-Tul minim de purcelu:;;i ce trcbuie sa fie spani

estc 4.

.calnpion 2010

chei.. out E'( fica ;e2 Cheile de la purcelu:;;ii 1 :;;i 3 sc afla in purceJu~ul 2. Chcia-de la

purceluljul 2 sc afla in purcclulju] 1. Cheia de 1a purcelu~uJ 4 seafla in purcelm;,;ul 4. Numarul minim de purcelu~i ce trcbuie sil fiespaqt cslC 2 (spargem purcclu~;ul 2 $i purcelu~ul 4).

34

2

Exemple~I chei..:i..n

42124

i41

. 19. CheiVasile l,i pastreaza economiile in N purcelu,i-pu,culila de ceram1ca

neagra.purcelush sunt numerotali de la 1 }a N. Fiecare purcelus are un capac care poate fideschis cu cheia corespunziitoare. In purcelu~i Vasile a pus bani, dar 5

ichelle de la

purcelu'ii. Desigur, Vasile line minte in care purcelusi a pus cheile .Fiindca vrea sa-si cumpere 0 masina noua, Vasile are nevoie de toti banii din

purcelu,i. Pentru a obline banii dintr-un purcelus el poate sparge purcelu,u] sau

poate deschide capacul ell cheia (daca 0 are).

CerinlaCunoscfmd

distribulia cheilor in purcelusi, sa se determine nnl11arnl minim depurcelusi pe care trebuie sa ii sparga Vasile astfe1 incat sa poata obtine toti banii.

Date de intrareFi'iierul de intrare chei. in contine pe prima linie un numar natural N,reprezentand nwnarul de purcelu,i. Pe fiecare dintre mmatoarele N linii este scriscare un numar natural cnprins mtre 1 .,i N; numarul de pe linia i +

1reprezinta

nnmarul purcelusulv' in care este plasata chela de la purcelusul i.

Dale de ie~ireFi§ierul de iesir'e chei. cu t va contine

singur nurnar namral reprezentand nurnarulsparri pentru a obline toti banii.

Restricfie• 1 :::;~N s:;. 100000

e inverseaza subsecvema din vector care incepe ia pozitia St ~i sc rcrmina Iapozftia Dr (lSStSDrSN). De exemplu, pcntru N=10, aplicand operajia I 2 7obtinem vectoru! 1 7 6 5 4 3 2 8 9 10'

Sc afiseaza suma elementelor din subsecventa care Incepe pe pozijia St §i setermina pe pozijia Dr (l':<:;St~DrSN). De exemplu, pentru N=10, aplicand S 2 7sc aflseaza 27.

1 :; K :5. 5000a < N S 10 9

in ti§ierul de intrare se atla eel putin 0 opera!ie de scriere .

Restric!ii

I St Dr IS EJeCT

s St Dr

Fie N un Hilmar natural ~i A un vector. Initial A [ i ] = i, pentru or-ice i = L 2, "',N. Asupra acestui vector se pot aplica operatii de doua tipuri :

Operatic

Cerinpi

Scrieti un program care sa execute 0 secvenja data de operaIii.

Date de intrare

Fisierul de intrare s ecvop _in contine pe prima linie doua nurnere naturaleseparate prin spatiu N §i K (unde Neste dimensiunea vectorului, iar K este numarulde operatii ce trebuie sa fie executate). Pe urrnatoarele K linii sunt scrise K operatii,care 0 operatic pe 0 linie.. Aceste operatii sunt scrise in -ordlnea hi care trebuic sa fieexecutate. 0 operatie este descrisa primr-un caracter (I sau s) urmat de spariu, apoide indicele St, apoi de spatiu, 'apoi de indicele pr (lSStSDrSN).

Dare de ie~'ire

Fi§ierul de ie§ire secvop. out va contine atatea linii Cate operatii de tipul 2(operaIii de scriere) se afla in fi§ierul de intrare. Pc linia i va fi scris rezultatul afi§atde eea de-a i-a operatie de scriere din fi§ieruJ de intrare.

••

,...,

~

~

Page 86: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

CLASELE ADAPTOR 171

6. Clasele adaptor

Clasele adaptor pentru containere sunt definite pe baza unci alte clase container,asigurand 0 functionalitate restransa pentru aceasta. Exista trei clase adaptorpredefinite in STL, bazate pe containere secventiale : queue (coada), stack (stiva),§i priori ty_queue (coada ell prioritate).

6.1. Clasa adaptor queue (coada)

Clasa adaptor queue este definite pentru a realiza operatiile specifice uncistructuri de date de tip FIFO (First In First Out). Intr-o astfel de structura ­denumita coada - elementele sunt inserate Ia un capat al acesteia (sfarsitul cozii) ~i

. extrase de la celalalt capat (inceputul cozii).Pentru a utiliza aceasta class trebuie sa includem fisierul antet queue:

#include <queue>

Declaratia clasei adaptor queue:

template <class T, class Container=deque<T> > class queue;

Observati ca aceasta clasa sablon are doi paramem :- T - reprezlnta tipul elementelor containerului ;_ Container - reprezinta clasa container care este utilizata pentru memorarea

elementelor : implicit aceasta este clasa deoue.

Constructorii si destructorul

Pentru clasa adaptor queue sunt definiti constructorul implicit, constructorul decopiere ~i destructorul, care distruge obiectul, eliberand memoria alocata d inamic.

Exemple

queue<int> Ci

Creeaza a coada denumita C cu 0 elemente de tip in t. Containerul utilizat pentrustocarea elementelor cozii este eel, implicit, adica deque.

queue<pair<int, int> > cp;

Creeazf 0 coada denumita Cp eli 0 elemente de tip pair<int, int>.Containerul util izat pentru stocarea elementelor cozii este eel implicit.

queue<string, list<string> > Csir;

Creeaza 0 coada denumita Csir eli 0 clemente de tip string. Containerulutilizat pentru stocarea elementelor cozii este list<string>.

string sir = "gigel" i

deque<char> dlsir.begin(), sir.end{));queue<char> Cc{dcoada);

Am creat 0 coada denumita CC cu elemente de tip char, pe care am initializat-oell continutul containerului deque d. Initializarea a fost posibila deoarece a fostutilizat constructorul de copiere al clasei d eque, care este clasa container suport, inacest caz.

Functiile membre referitoare la dimensiunea containerului

Sum definite functiile uzuale size () !}i empty (). Functia size () rcturncazanumarul de elemente din coada, iar functia empty () returneaza valoarea logicatrue in cazul in care coada este vida.

Accesori

Pentru a coada este permis accesul doar la primul !}i la ultimul element dincoada ~ functiile membre fran t () si back () rctumcaza 0 referinta la primul ,respectiv la ultimul clement 'al cozii:

Functiile membre care modified containerul

Avand in vedere faptul ca -accasta clasa implementcaza structura de date de tipFIFO, sunt definite doar doua functii membre care modifies containerul :

• push ()

void push (canst value_type& val) i

Insereaza un element cu valoarea valla sfarsirul cozii.

• pop()

void pop (.)

Elimina si distrugc primul element din coada.

-'

'-~

, :'-'

~

~

~

~

Page 87: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

[ncepand cu C+ + 11 este definita si funcna membru emplace () care COo­struieste si insereaza un element la sfarsitul cozii, precum ~i functia membra swap ()care interschimba coada curenta ell cea specificata ca parametru.

!ri,

172 PROGRAMAREA IN LIMBAJUL CtC ++ PENTRU LlCEU CLASELE ADAPTOR

Restricjle

• intotdeauna exists 0 succesiune de mutari care duce Ia configuratia flnala.

Exemplu

173

Operatorii relationali

Pcntru clasa queue sunt supraincarcati rot! operatorii relationali, eompararearealizandu-se din punet de vedere Iexicografic.

magic.in magic.out Expliccuii

1 2 3 4 2 1 2 3 4 A 5 1 3 4 D 6 1 3 4

5 6 7 8 5 6 "I 8 ==> 6 2 7 8 ==> 5 2 "I 8

613 4

5 2 7 8

Observatii I (.campion 2007)

,~

r-:

r-

r-

rr:

r-

1. Toate operatiile asupra eontainerului se executa III timp constant.2. Incepand ell C++ 11 este definita ~i functia independents swap () care schirnba

intre ele continurul celor doua containere queue indicate ca parametri.

Aplicatia 1. Magic

Jocul Tabla Magid. este compus din opt piese patratc. numcrotate cu valor ile de1a 1 la 8, dispusc pe deus linii , 'similar unui tablou bidimensional cu 2 linii si 4eoloane. 0 configuratie posibila este eea din figura unnarcare :

t±B±H--U6 3 2J2J"Sunt posibile rnodificari ale configuratiei prin utilizarca urmatoarelor mutar-i :~ Mutarea A: Parratele depe pozitiile T[l] IlL T[11 121, ~'[2] [lL

. T"r 2 J [2 J se rotesc in sensul acelor de eeasornic.Mutarca B: Patratele de pe pozitiile T[l] [2]. Til] [3J. T12] [2].T [2) [3 J se rotesc in sensul acelor de ceasornic.Mutarea C: Patratelc de pe pozitiile T [1 J [3 J. T [1) [4 J. T [2 J [3 J •T [2] [4] se rotesc ill sensul acelor de ceasornic."Mutarea D: Patratele de pe pozitiile T [1] [1] -5i T [2] [1] se inrerschimba.

Cerinpi

Scrieti un program care sa determine numiirul minim de mutari necesare pentru aajunge de la 0 configuratie initiala Ia 0 configuratie finala.

Date de intrare

Fisierul de intrare magic. in contine pe primele doua linii cate 4 valori repre­zentand configuratia initiala, iar pe urmatoarele doua linii cate 4 valor! reprezentandconfiguratia: finala.

Date de iesire

Fisierul magic. out va contine 0 singur~' liniepe care se va serie nU111arul minimde mutari necesare pentru a transforma contigun1lia iniliala in configuraIia finaHL

Solutie

Yom util iza 0 coada pentru a retine toate configuratiile posibile care se pot obtinepornind de la configuratia initiala.

La inceput, coada va contine doar configuratia initiala. AIgoritmuI de generareconsta in aplicarea urmatorilor pasi :_ Extragem din coada configuratia curenta ;

Pentru fiecare dintre cele 4 mutar i posibilc generam noua configuratie. Dacaaceasta noua configuratie nu a fost generata anterior, atunci 0 inseram in coada ,marcam faptul ca am introdus-o in coada ~i retinem totodata inca 0 configuraticparcursa in plus, adica numarul de mutari necesare pentru obtinerea acestei noiconfiguratii.

Algoritmul se opreste atunci cand extragcm din coada conflguratia final a, acestlucru fiind intotdeauna posibil.

Pentru a verifica daca 0 configuratie este deja In co ada C, am definit functiape.rmjor d () , care asociaza oricarei configuratii un numjlr natural unic. Ne bazam pcfaptul ca orice configuratie este de fapt 0 perrnutare a rnultimii -[ 1. , 2, 3, 4 J 5, 6, 7 , 8},numarul total al configuratiilor posibile fiind 8! (40320). Functia perm_ord ()asoclaza unei permutan numarul de ordure al acestcia dadi am genera permutanlcmultimii {l ,·2 J 3,4,5,6 J 7, 8} In ordine lexicografica. .

Pentru a retine multimea configuratiilor dejagenerate utilizam un veccor-eboo i >

viz (viz [x] =true cand configurana cu numarul de ordine x a fast deja generata).Programul complet arata astfel :

#include <cstdio>#include <queue>#include <algorithm>#include <vector>#define Nmax 10#define InFile "magic. in"#define OutFile "magic.out"using namespace std.i

struct Element {int conf, nri

} st, fin;

Page 88: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

174 PROGRAMAREA iN UMBAJUL C/C++ PENTRU LICEUCLASELE ADAPTOR 17S

queue <Element> Qjvector <boel> viz(50000, false);int ST[Nmax], FIN [Nmax] , f[Nmax];

void perm_ord (int prJ, int &nr){ :tnt i, ], pwr[Nmax];nr =: 0;for (i :::: 0; i < Nmax; i++) pwr[iJ :::: 0;for (i :::: 1; i <= 8; i++)

{nr += (p[i] - pwz-Lp l ri Ll - II * f(8-i];for (j ::: p [i J + 1; j <= 8 i j ++) pwr [j] ++;

copy (Y, X);t=Y[3J; Y[3]=Y[2J ,Y[2]=Y[6] ,Y[6JoY[7J; Y[71"t;

perm_ord {Y, y.confl;if (!viz[y.conf])

{ Q.push (y); viz[y.conf] = true; }

/Imiscare tip Ccopy (Y, XI;t=Y[4]; Y(4J=Y[3J ,Y(3]=Y[7j ,Y[7J=Y[8]; Y[8J=t;

perm~ord(Y, y.conf);if (!viz [y.·conf])

{ Q.push (y); viz[y.conf] = truei }//miscare tip Dcopy (Y, X) iswap (Y[l], Y[5]), perm_ord (Y, y.confl i

w

~

Aplicatia 2. Alee

int main (){int i;freopen (InFile, "r", st:din) i

freopen (OutFile, "W " , s t.dou t j

for (f[OJ=i=li i<Nmaxi ++i) f[iJ=f[i-1J*i;for (i=l; i<=8; ++il scanf .('.'%d", &ST[i] ),;for (i=l; i<=8i ++i) scanf ("%d", &FIN[i] l;perm_ord(ST, st.conf); perm_ord(FIN, fin.conf};printf ("%d\n", ca t cu r t r l .return 0;

Parcul orasului a fast neglijat mult timp, astfel ca acum toate aleile sunt distruse ,Prin urmare, anul acesta Primaria si-a propus sa faca reamenajari. parcul are formaunui patrat cu 1atura de n metri §i este inconjurat de un gard care are exact douaportio Proiectantii de la Prirnarie au realizat 0 harta a parcului ~i au trasat pe harta unearoiaj eare imparte pareul in nxn zone patrate eu 1arura de 1 metru. Astfel hartaparcului are aspectul unei man-ice patratice eu n linii si n eoJoane. Liniile st respectivcoloanele sunt numerotate de la 1 1a n . Elementele matricei corespund zonelorpatrate de latura 1 metru. a astfel de zona poatc sa contina un copac sau este libera.Edilii orasului doresc s~ _pavez,e ell un numar minim de dale patrate cu latura de1 metru zoneJe libere (tara copaci) ale parcului, astfel incat sa se obdna 0 aleecontinua de la 0 poarta la alta.

void ord_"perm (int or-d , int p [] ){ int i, ], a, ny, pwr[Nrnax], v[Nrnax];for (i :::: OJ i < Nrnax; i++) pwr[i]=v[i]=O;for (i :::: 1; i <= 8; i++)

{ a=ord/f [8-iJ;nr=O;for (j ::: 0; j < 8; j ++)

if (!v[jJ){if (nr == a)

( p[i]=j+l, v[j]=l; break; )nr++; }

ord -= (p Ii] -pwr [p Ii] J -ll *f [8-i];for (j=p[i]+l; j<=8; j++) pwr[j)++;

void copy (int A[], int B[J){ for (int i = 1; i <= 8; i++) A(iJ=B[i];

:tnt calcuI ( ){Element X, y;int t, X[Nmax], Y[Nmax];Q.push(stli viz[st.conf] :::: true;while c : Q. empty ( ) )

{x = Q.front() iQ.pop();I/extrag configuratia curentaif (x.conf == fin.conf) return X.Dri /Iam gasit

else{ord-perm (x.cont, X);y.nr = X.Dr + 1;Ilmiscare tip Acopy {Y. X) i

t=Y[2J; Y[2J=Y[lJ ,Y[1]=Y[5], Y[5]=Y[6J; Y[6]=t;

perm~ord (Y, y.conf);if .('!vj.zLy.conf])

{ Q.push (y); viz[y.confJ = true;Ilmiscare tip B

if (!viz [y. conf] 1{ Q.push (y); viz[y.conf]

return 0;

true; }

w

Page 89: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

176 PROGRAMAREA iN L1MBAJUL etc ++ PENTRU LICEU CLASELE ADAPTOR 177

queue<pair<int, int> > Ci

Vom parcurge matricea incepand eli pozttia prime! porti.

a[ixJ [iy] = 1; //prima dalaC.push (make_pair (ix, iy)) ;/Iplasez in coada

La fiecare pas vom extrage din coada 0 pozitie

Soliqie

Este 0 problema "clasidi" a carei rezolvare se bazeaza pc algoritmul lui Lce'.Vom utiliza 0 matrice A in care initial voru retine valoarea 0 penrru zonele bbcre,

respectiv valoarea - i pentru zonele in care se afla un copac.Ulterior, pe masura ce exploram matricea in scopul dercrminant unci alei de

lungime minima vom retine in matrice pentru pozitiile explorate un nuntar naturalcare rcprczinta distanta minima de la pozitia primei porti la pcz.itia rcspccriva(exprimata ill numarul de dale necesare pentru construirea aleii).

Pozitiile din matrice care au fast explorate Ie vom retine intr-o coada , 'ill ordineaexplorarii lor. Deoarece idemificarea unei poz.itii se face prin doue coordonate (Iinie ,coloana), un element al cozii va fi format dintr-o pereche, deci coada este definita~~: .

'pai r-c i.n r , int> XXi

xx = C.front(); I/determin primul element din coadaC.pOP(}i /Ielimin primul element din coada

Vom explora toti cei patru vecini liberi neexplorati ai pozitiei extrase ~i ii yomintroduce in coada. Cand exploram un vecin, retinem 'in matricca A pe pozitia sadistants minima calculata prin adaugarca Ia distanta curenra a valorii 1.

Procedeul se repeta cat timp coada nu este vida si poz.itia in care se afla cea de-adoua poarta nu a fast explorara. Rezultatul se va obrine In matricca A, pc pozlna celeide a doua portio

Programulcomplet arara astfel :

#include <cstdio>#include <queue>using narnespace std;

r

!

rI ,

rI~,

c-

l ;

r

rI

r-'

Cerinpi

Scrieti un program care sa determine numarul rmnun de dale necesare penrruconsrruirca unci alei continue de la 0 poarta la ccalalta.

Date de intrare

Fisierul de intrare alee. in contine pe prima linie doua valori naturale n $i m,separate printr-un spatiu , reprezentand dimensiunea parcului, respectiv numarul decopaci care se gasesc in pare. Fiecare dintre urmatoarele m linii contine dire douanumere naturale x $1 y, separate printr-un spatiu, reprezentand pozitiile copacilor inpare (x reprezinta linia, iar y reprezrnta coloana zonei in care se afla copacul).Ultima linie a fisierului contine patru numere naturale xl yl x2 y2, separate princare un spatiu, reprezentand pozitiile celor doua porti (xl si y1 reprezinta linia l;irespectiv coloana zonei ce contine prima poarta, iar x2 si y2 reprez.inta linia §irespectiv eoloana zonei ce contine cea de-a doua poarta).

Date de iesire

Fisierul de iesire alee _out va contine a singura linie pe care va fi scris unnumar natural care reprezinta numarul minim de dale necesare pentru construirea aleii.

Restriqii

• 1 ~ n :::;: 175

• 1 :<; m < n *n• Aleea este continua daca oricare doua placi consecutive au a larura comuna.• Aleea tncepe ell zona unde se gaseste prima poarta si se termina cu zona unde se

gaseste cea de-a doua poarta.• Poz.itiile porti1or sunt distincte si corespund unor zone Iibere.• Pentru dateJe de test exists intotdeauna solutie.

Exemplu - - --alee.in alee.out Exptlcruii

8 6 15 o modalitate de a construi aleca cu nurnar minim de dale cste :

2 7 000 ----- .3 3 -- DO ~~x-

4 6 -- ,,0 ----

5 4--- OOx ---- xO ---

7 3 ---- DO -7 5 -- xODx - -1 1 8 8

-~~~-- 00

(cu X am marcar copacii, cu - zoncle Iibcre. iar cu 0 dalelc aleii).

const int dx[5] = {O, -1, 0,const int dy[5] = {O, 0, 1,queue<pair<int, int> > C;Lzrt;' a[178] [178];int ix, iy, ox, oy, x, Yiint n t W;

1, 0);O. -1);

(Olimpiada Jucctcana.dc Informatica, Iasi , 2007)J. Pentru aprofundarca algoritmului lui Lee puteti utlliza sofrwarc-ul educational .Atgorinnut tui Lee",

prezcntat pc Arhiva cducalionaUi .campion' Omp: Ilcampion.CdLi;ro/arhiva/l."O prczcman: dctaliata astructurilor stiva ~i coada eu aplica\ii PUlc~i consulta in capilOlul 5 din volumul I al lucrilriiProgramarea in limbajul C/C+ -+ pcntru liceu.

Page 90: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

~

178 PROGRAMAREA iN UMBAJUL C/C++ PENTRU LlCEU CLASELE ADAPTOR 179

2. 0 prczeutare deraliata a algoritmului Bellman-Ford poate fi consuhata in capitolul 1 din voJumulal III-lea al lucrarti Programarea in limbajul C/C+ + pentru liceu.

Aplicatia 3. Algoritmul Bellman-Ford optimizat

Algoritmul Bellman-Ford" deterrnina drumurile de cost minim de la un varf dingraf 1a fiecare dintre ceJelalte varfuri, identificand eventualele circuite de cost negativ.in forma lui "standard", complexitatea algoritmului Bellman-Ford este Orn'), undeell n am notat numarul de varfuri din graf.

Implementarea algoritmului Bellman-Ford poate fi optimizata utilizand 0 coada.

Reprezentarea informatiilor

Vom reprezenta graful prin liste de adiacenta eli costuri. Mai exact pentru fiecarevarf x din graf retinem arcele ell extremitatea initiala x tnrr-un vector de perechide numere intregi (pair<int, int»; primul numar din pereche (first)reprezinta extremitatea finale a arcului, iar al doilea numar din percche (second)reprezmta costuI.arcul:ui respectiv,

int main (){:i.nt k , i, j;pair<int, int> xx, YYiFILE *f :::: fopen("alee.in", "r");FILE *g :::: fopen (" alee. out" I "w");

fscanf (£, "%d%d", &n, &m);for (k :::: 1; k <= m; k++l

( fscanf(f, "%d%d", &i, &j); ali] [jJ = -1;fscant Lf , "%d%d%d%d" J &ix, &iy, &ox, &oy);f c Lo s e I f ) ;for (i :::: 1; i <= n; i++) /Ibordare

ali] [O)=a[i) In e t j e a l O'l [iJ=a[n+1) [iJ=-l;a[ix] [iy] :::: 1; Ilprima dalaC.push{rnake-pair(ix, iy)); //pun in coadawhile (!C.empty()&& a[oxJ [oy]==O)

(xx=C.front{l; C.pop(); /Iextrag element din coadafor (k :::: 1; k <= 4; k++l

{yy.first :::: xx.first + dx[kJ;yy.second :::: xx.second + dy[k];if (a[yy.first] [yy.secondJ==O) lie liber

(a [yy. first] [:yy. second] ::::a[xx.first) [xx. second] + 1;

C.push(make-pair(yy.first, yy.second»);}

)

costuIxO la x ,

~

-J

~

'1

. ,

~ vector < pair<int, int> > G [NMAX] i

Costurile drurnurilor minirnele vom rctine in vectorul dmin (drnin [x]drumuJui minim de la varful xO Ia varful x; daca nu exista drum de Iadmin'lx] ==INF, unde INF este 0 consranta suficient de mare).

! int drru.n [NMAXJ ;

Yom utiliza 0 coada C, in care inserarn varfurile grafului, pe masura ce calculamcosturile drumuriJor minime.

#include <cstdio>#include <vector>#include <queue>#define INF 1000000000#define NMAX 50001using namespace std;int n , xO;vector < pair<int,int> > G[NMAX];int drnin [NMAX] j ..

int nr [NMAX] ;bool negativiqueue<int> Ci

void citire() i

void bellman_ford();void afisare();

int main ().{ citire()bellman_ford ( ) ;afisare{);

~ queue<int> C;

Pentru a detecta daca exista circuite de cost negativ, trebuie sa contorizam de careori a fast introdus in coada fiecare varf. Pentru aceasta vom utiliza un vector nr,

. nr [x J reprezentand de care or! a fast introdus in coada varful x. Daca nr [x J »ri

deducem ca am identificat un circuit de cost negativ (variabiJa Jogica n ecet t.v retineacest lucru).

! int nr [NMAX] ;

Initial: &nin[x]=INF, pentru orice x * xO si drriin[xO]=0 l)l inseram incoada C varful de start xO. Cat timp in coada C mai exista varfurt si nu am identificatun circuit de cost negativ :- extragem un varf x din C ;

parcurgem lista de adiacenta a lui x si incercam sa optimizam costuriledrumurllor varfurilor y care sunt extremitati finale ale arcelor care pleaca din x.Varfurile y pentru care costul drumului de Ja xO la y a fost optimizat suntintroduse in coada ($i contorizam acest lucru in nr [y ] ).

//scrie rezultat)

fprintf(g, "%d\n", a[ox] [oy]);fclose (g) j

return 0;

Page 91: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

180 PROGRAMAREA iN LlMBAJUL CIC++ PENTRU LICEU CLASELE ADAPTOR 181

~

!

r

r

r

ri '

r-'

return 0 i

void ci tire ( ){int it ro, X, y, c;FILE * fin=fopen("bellmanford.in", "rIO);

fscanf (fin, "%d %d 'sd" I &n, &rn, &xO) i

for (i=O; i<m; i++J{ fscanf(fin, "%d %d %d", &x, &y, &c);G[x] .push_back(make-pair(y,c)) i }

void bellman_ford(){vector< pair<int,int> > : :iterator it;int .i , x;for (i=l; i<=n; ++i) dmin[iJ=INF;dmin[xOJ=O;C , push (xO ) ;while (lC.empty()&& !negativ)

{x=C.front(); C.pop();

for (it::: G[x] .begin(); it != G[x] .end(); ++it)if (dmin[it->first] > dmin[xj+it->second)

{ dmin[it->first]=dmin[x]+it->second;nr[ it->first ]++;C.push{it->first);if (nr[it->first»n) negativ=true;

2. Complexitatea teorerica a algoritmului Bellman-Ford este de O(n -m), insa inpractice se comporta mult -mai bine, devenind comparabil cu algoritmul luiDijkstra.

6.2. Clasa adaptor stack (stiva)

Clasa adaptor stack este definita pentru a realiza operatiile speciflce uneistructuri de date de tip LIFO (Last In First Out). intr-o astfel de strucrura ­denumita stiva - elementele sunt inserate §i extrase la un singur capat. denurnit varfulstivei.

Pentru a utiliza aceasta clasa trebuie sa includem fisierul antet s t ack'.

#include <stack>

Declaratia clasei adaptor stack:

template <class T, class Container~deque<T> > class stacki

Observati ca aceasta clasa sablon are doi pararnetri :- T - reprezinta tipul elementelor containerului ;- Container - reprezinta clasa container care este utilizata pentru memorarea

elementelor; implicit aceasta este c1asa deque.

Constructorii si destructorul

Pentru c1asa adaptor stack sunt definiti constructorul implicit, constructorul decopiere, precum si destructcrul care dlstruge obiectul, eliberand memoria alocata.

Creeaza 0 lista L ell 50 de elemente avand valoarea 0, apoi creeaza 0 stiva SL ell50 de clemente de tip int, copiind elementele din lista creara. Operajia de initia­lizare a stivei ell elementele din lista a fast posibila deoarece clasa container suportpentru stiva SL este list.

Creeaza 0 stiva denumita S ell a clemente de tip into

stack<pair<int, int> > sp;

Creeaza 0 stiva denumita Sp ell 0 elemente de tip pair<int,

list<int> L{50, 0);stack<int, list<int> > SL(lista);

I'I

r--«

I:r 1., ,

I:

void af isare ( )

{FILE * fout=fopen("bellmanford.out", "w");if (negativ)

fprintf(fout,"Circuit de co·st negativ!\n");else{ for (int i=l; i<=n; i++)if (i!=xO)

~fprintf(fout,"%d ", dmin[i] !=INF?d.rnin[i] :0);fprintf (fout, "\n");

)

fclose{fout) ;)

Observatii

Daca dorim sa reconstmnm drumurrje, este necesar ca pentru fiecare varf y sarejinern prec [y] = varful care il preceda pc y pe drumuJ minim de Ia xO la y ;(varful xO nu are precedent, deci p r-ec .[xO] :::: 0) .. Cand costul drumului minim dela xO la un varf y se schimba, remiem in p~ec [y] v~j:fuJ x care reprez.intiiextrcmitatea initialf a arcului care a determiuat optimizarea.

[

Exemple

stack<int> S; '..'

int>.

Page 92: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

Accesori

Operatorii relationali

AplicaJia 4. Reaqii

Singurul element dintr-o stiva la care avem acces este eel din varful stiVClFunctia membra top () rerurncaza 0 rcferinrg catre elementuj din varful stivei,

r 1

~

!

i~

L..J

i,..J

..J

183

Configurauc

6 (3,2,1,4,5)

(6,3,2,1,4,5)

632145~

6 13,2.11 14.51

1 6 3 12 , 11 4 563 (2,1) (4,5)

CLASELE ADAPTOR

Configurapa initiala

Reactioneaza substanja 3 ell substanta (2 ,1)

Reactioneaza substanja (3,2,1) ell substanja (4,5)

Reactioncaza substanta 2 ell substanta 1

Reactioneaza substanta 4 ell substama 5

Reactioneaza substanta 6 cu substanta (3,2,1,4, 5)

Acjiune

4

5

6

2

3

1

Erapa

Nu din orice secventa de substante se poate obtine in urma reactiilor a substantanalii stabila.

Cerirua

Scrieti un program care sa determine pentru 0 secventa data de substante daca inrrna reactiilor ce se produe conform regulilor din enun; rezulta 0 substanta stabila,

Date de intrare

Cu substanteje din secventa s se vor efecrua diferite experimente. in timpul unuixperiment pot reacjiona doua substante alaruratc s , si Si+l doar daca numerele lore ordine sunt consecutive. in urma reactiei se obtine 0 noua substarna. fermata dinubstanre[e care au reactionat, notata (Si, Si+l). Mai mult, substantele cbtinute poteacpona daca ele sunt alarurate, iar prin reunirea subsecventelor de subsrante ce Ieompun se objtne un interval. Experimentul este declarat reusit daca in final, urrnandegulile de mai sus, se obtine 0 singura substanta fermata din toare cele n substanten secventa s, aceasta fiind declarata stabila.

De exemplu, pentru n==6 substante ~i secventa 8=6,3,2,1,.4,5 se poate procedastfel :

Fisferul de intrare reactii. in contine pe prima linie numarul natural n, numa­ul de substante. Pe cea de-a doua linie se afla un numar natural m, reprezentandumarul de secvente de care n -substauje din fisierul de intrare. Ptccare dintrermatoarele m linii contine care n numcre naun-ale-distincte: separate pr'in care unpatiu, rcprczentand 0 secventa de n substante.

Date de iesire,

Fisierul de iesire reactii. out contine, pentru fiecare secventa de substente dinsierul de intrare, care 0 linie, pe care este afisata valoarea 1, daca pentru secventa

espectiva se poate obtine 0 substanta stabila, sau valoarea 0, in caz contrar.

RestriCJii

• 2 ::;·n ::; 15000• 1'::; m :s; 20

.. La un moment dat pot reactiona doar doua substanle,

.-

,,,I

(

r(

,1

I

I

1

I

1,

j

I

--PROGRAMAREA IN LIMBAJUL C/C++ PENTRU LICEU182

Pentru clasa stack sunt supraincarcari Tori 'operarorii relationali, - compararearea1izandu-se din punct de vedere lexicografic.

lncepand cu C+ + 11 este definita §] funcua indepcndenta swap () care schimbatntre ele continurul eel or doua eontainere stack indicate ca paramctri. Acesteatrebuie sa fie de acelasi tip, chiar daca dimensiunea lor difera.

Functiile membre referitoare la dimensiunen containerului

Sunt disponibiie functia size (), care rerurneazs numarul de clemente din stiva§:i funcjia empty ( ) , care rerurneaza valoarea true in cazul in Care stiva este vida.

Functiile membre care modified containerul

jntr-o stiva sunt permise doua operani :

• inserarca unui element Ja varful stivei

l"void push (canst value_type& val);

Insereaza un element ell valoarea valla varful stivei curente.

• extragerea eJementului din varful stiveiI void pop ( ) ;

Elimina ~i distruge elementul din varful stivei. Aces! element este ultimul care afost inserat in stiva.

Ca ~j in cazul adaptorului queue, incepand cu C+ + 11 sunt definite functiamembra emplace ( ) , care creeaza si insereaza un element la varful stivei, ~i functiamembra swap ( ) , care interschirnba stiva curenta cu stiva specificata ca parametru..

Sa consideram 0 seCVenta de n substanre chimice S==S1, 52, ... , Sn. SubstanteJeSunt numerotate distinct de 1a 1 1a n §i fiecare substanra apare in secvel1ra 5 0 singuradatil. Sa consideram 0 subsecvenra Sij==Sj8i+I...Sj §i sa nota111 cu minij $i maXij celmai mic, respectiv cel mai mare numar din subsecventa. Subsecvenla respectivaconstituie un i.ntervaI dadl en contine toate nUln~rele naturale cuprinse lntre minij .;;imaxij·

Page 93: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

reactii.in reactii.out Explicatii

6 1 stabila4 0 nestabila6 3 2 1 5 1 stabila4 1 stabila3 4 1 6 52

2 3 1 5 46

6 2 3 1 45

Se utillzeaza 0 srlva S, ale carci clemente sunt subsecvente P, p+l, ... I p+k alemultirnii {l, 2, ... ,n}. De fapt, un element al stivei va avea doar doua com­ponente. elementul minim §i respectiv elementul maxim din subsecvenja. In general,pentru a adauga 0 substanta s la stiva S, se verifica daca substanta din varful stivei sformeaza 0 noua substanta irnpreuna ell s, eli alte cuvinte daca reuniunea celor douaseturi de valor! este 0 substanta (conform regulii). In caz afirmativ, se extrage sub­stanta din varful stivei S, se formeaza noua substanta, apoi se repeta pasii anteriori(verificare, extragerc, formare substanta noua). Daca reuniunca a doua seturi devalori (substante) nu formeaza 0 noua substanta, arunci ultima substanta nou-obtinutase pune in varful stivei s.

Astfel , setul de substante este parcurs 0 singura data; se considera initial fiecareelement ca fiind 0 subsrarna separara ~i se adauga fiecare dintre aceste substante la S,in modul descris mai sus.

Daca, -la terminarea'- parc-urgerii -serului de valori, stiva -5· contine un singurelement (0 singura substanta), adieu valorile 1 ~i n, substanta flnala este stabile.

Programul complet arara astfeJ : _

#include <£stream>#include <stack>using namespace std;struct SUBST Iisubstanta 'r-e t a.nu c a prin minim si maxim

{ int minim, maxim; };stack<SUBST> S;FILE *f. *g;int n, m, x, Substanta;SUBST SVarf, SNoua;

Aplicatia 5, Ceiati

)S. push (SNoua) ;

185CLASELE ADAPTOH

Jfprintf(g,"%d\n",S.size()====1?1:0);

}

fclose(f}; fclose(g);return 0;

~oid Reuniune(SUBST R, SUBST &Rx)llcombina cele 2 substanteRx.minim == min (Rx.minim, R.minim);

Rx.maxim == max(Rx.maxim, R.maxim);

}else I/este prima substantaS.push(SNoua); 110 pun direct in stiva

int main ()f::: fopen("reactii.in", "r")j

9 ::: fopen ( II reactii. out", "w");

fscanf (f, "%d%d", &n, &m);for (; In; --m) I/ia pe rand fiecare configuratie

{while{!S.empty(») S.POP(}i IIGolesteStivafor (Substanta=lj Substanta<==nj ++Substanta)

{ fscanf(f, "%d" , &x);

SNoua.minim::: x; SNoua.maxim == x;11 retinif (!S. empty (» I Idaca am e Lernen t e in stiva

( SVarf:S.top();while (OK (SVarf, SNoua)) /Idaca DA

( S.pop();Reuniune(SVarf, SNoua)if (! S. empty ( ) )

Svarf ::: S.top(};elsebreak;

Terraland este un regat care se extindc permanent. Frontiera regatului este unpoligon convex, in varfunle caruia sunt construite cetari pentru apararea segmenrelorde frontiera adiacente. La fiecare extindere a regatuJui frontiera se modifica : seconstruiesc cetap not, iar unele cetati. construite anterior i~i pierd rolul de puncte deaparare. in toate cetatile se afla garnizoanc. Pentru a micsora cheltuielile pentruintretinerea armatei, MegaBit, regele Terralandului, a decis sa demobilizeze garni­zoanele din cetatile care nu mai au rolul de puncte de aparare (nu se mai afla pefrontiera regarului).

(Olimpiada Nationala de Informatica, Galaji, 2009)

PROGRAMAREA iN LIMBIVUL C/C-t--t- PENTRU LICEU

Exemplu

Solutie

184

r

n

r-

r

rI,,

r

n

,,

!I

I

~

bool OK (SUBS']' R, SUEST Rx) _ /Iverifica daca se pot combina{ return ! (R .maxi.m-eL! :::Rx_mi~im&&Rx. ma.x.i.m-s L! :::R'. minim)

I---

Page 94: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

186 PROGRAMAREA IN LIMBAJUL C/C ++ PENTRll LICEU CLASELE ADAPTOR 187

,

i-j

Cerinpi

Scrieti un program, care va determine din care cetati vor fi demobilizate garnizoa­nele.

Date de intrare

struct pUDet { double x~ y, tg;} aux;int TI, i, paz, p, pI, p2;double xmin, ymin;veetar<punct> v (Nmax) ;stack<int> ~;

L.J

Prima linie a fislerului de intrare cetati. in conune Ull numar intreg N ­numarul de cetati din Terraland. Urrneaza N linii cc contin cate doua numere intregiXi ys , separate prin spatiu - coordonatele cetatilor.

int arie (doublex3, double y3){ double ariareturn (aria >=

xl, double yl, double x2, double y2, double

(x3-xl) * (y2-yl) - (x2-xll * (y3-yl);0); )

~

Dale de iesire

Fisierul de ieslre cetati. out va contine 0 singura linie pe care va fi afisatnumarul de cetati din care pot fi demobilizate garnizoanele.

Restrictii

• 3 S; N S; 10000• _10 9 ::; xi, Yi S; 10 9

Exemplu

cetati.in cetati.out Exptiouie10 52 13 4

6 36 6

~o.8 510. 311 712 69 1115 8 I

(vcampion 2009)

Soliqie

PuncteJe care au rol de aparare sunt varfurile infasuratorii convexe. Pentru adetennina infasuratoarca convexa vom utiliza algoritmul lui Graham',

Programul cornplet arars astfel :

#include <estdio>#inelude <algoritrun>#inelude <stack>#inelude <vector>#define Nmax 10010using namespace std;

3. 0 prezemarc detaliata a algoritmului lui Graham poate f consultara in capitolul 6 din volumulal Ill-lea al Iucrarii Programarea in fimbajuf CIC+ + pouru liceu.

I;

int cmp(punet a, punet b){ return a.tg < b.tg; }

int main (l{ FILE * f ::: f open {vce t a t L, in", "r") i

FILE * 9 = fopen("eetati.out", "w") i

fseanf (f, "%d", &n);fscanf(f, ''%If %If'', s-v l t l .cc , &v[l] .yl;poz ::: 1; xrnin ::: v[l] .Xi ymin = v[l] ·Yifor (i ::: 2; i <= ni i++)

{ fscanf Lf • ''%If %If'', &v [i] . x , &v [i ] . y) ;if(v[i] .x<xmin ) I (v[i] .x:::=xmin && v[i] .y<ymin»)

poz = i, xmin = v[i] .X, ymin ::: v[iJ ·Yi

aux::: v[lJ; v[l] ::: v[poz]; v[pozJ ::: aux;v(l].x :::: 'v l Lj v y :::;0; Ilpun v[l] in originev[n + 1] ::: v[1]; Ilinchei in acelasi punctS.push(O); Ilfietiv pe paz aS.push(l); 111 pe prima pozitiefor (i :::: 2; i <::: n; i++) Ilpentru celelalte puncte

{ v[i] .x-::: xmin; v[i} .y-::: ymin; Iitranslatez punctulif (~.T[i_J.._x=;:-: _0) v[,i~ .tg:=1-«30illtangenta infinit

else v[i] .tg ::: v[iJ .y/v[iJ .Xi Iitg caleulata)

sort(v.begin() + 2, v.begin() + 1 + TI, cmp)illardonezfor (i ::: 2; i <= n + 1; i++l II'pentru fiecare punc t;

{ S. push (i) ; Ilpun punctul in stivap=S.top() i S.pop(); Ilconsider ult:imele 3 punctepl"S.toP(); S.pop();p2=S. top () ;while (S.size(»l &&

arielv[pl] .x,v[pl] .Y,v[p] .x,v[p] .y,v[p2] .x,v[p2] .yl){S.push(p); /Ielimin punctul din rnijlocp=S.top(); S.pop(); //consider iar ultimele 3pl=S.topl); S.pop() ;//puncte

p2=S.t"p() ;)

S.push(pl); I/repun pe stiva ultimele 2 punete

....,J

--.;

,

W

w

.J

1

1

..J

i~

_0

~

11

Page 95: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

188 PROGRAMAREA iN L1MBAJUL C/C++ PENTRU L1CEU CLASELE ADAPTOR 189

~

"I ,

r-«

"I!

\-.,

~

S .push (p);}

fprintf(g,"ld\n", n-(S.size()C2));fclose(f); fclose(g);return 0;

6.3. Clasa adaptor priority_queue

Pentru a utiliza aceasra clasa trebuie sa includern fislcrul ante! queue:

#include <queue>

Containerul adaptor priority_queue implementeaza 0 strucrura de dateabstracta denurnlta coada cu prioritate care perrnite executarea eflcienta a operatiilorde inserare a unui element §i de extragere a maximului. Eiemenrele containerululsunt structurate ca un max-heap",

I:template <class T, class Container=vec~or<T>,

; class Compare=less<typenarne Container: : value_type> >; class priority_queue;

Din declaratia clasei observati ca exista trei tipuri specificate ca paramerru :

T - reprezinta tipul elementelor srructuni ;Container - rcprezinta clasa container care este utilizata pentru mernorareaelementelor : implicit aceasta este clasa vector; clasa container utilizata trebuiesa dispuna de iteratori cu acces aleator.Compare - rcprezinra criteriul utilizat pentru compararea elementelor - 0 functiesau un functor care cornpara doua clemente si rerumeaza un rezulrar de tip boo 1 ;implicit acesta este operatorul <.

Constructorii si destruetorul

Constructorii clasei priori ty_queue SUn[:

• Construcrorul de initializare :

~ explicit priority_queue (canst Compare& comp = Compare(),r: canst Contain~r& ctnr=Container{));

• Ccustrucrorul bazat pe un domeniu

template <class Inputlterator>priority_queue (InputIterator prim, Inputlterator ultim,

const Compare& camp = Compare(),canst Container& c~nr = Container());

4. Accasta structura de date cste deraliar prezenrata in capitoJul 3 din . voiumuJ aJ HI-lea al IucrarfProgramarea In limbaju! C/C + + pentru iiccu,

'1

I

Constructorii initializeaza criteriul de comparare, precum ~i un obiect container.Al doilea constructor insereaza in container elementele din domeniul [prim, u Lt Lm) ,apoi apeleaza algoritmul make_heap () pentru a organiza elementele din containerca un max-heap.

Exemple

priority_queue<int> pql;

Creeaza 0 coada cu prioritate vida; elementele sunt de tip int si containerulcare le stocheaza este cel implicit, adica vector; criteriul de cornparare este eelimplicit (operatorul <).

priority_queue<int, vecrorc t n t>-. greater<int> > pq2";

Creeaza 0 coada eu prioritate vida; elementelc sunt de tip int si containerulcare Ie stocheaza este eel implicit, adica vector; criteriul de comparare estefunctorul greater (care utilizeaza operatorul »; astfel se obtine un min-heap.

string s ( "Ana are mere") ;priority_queue<char> pq3 (s.begin(),s.begin+S);

Creeaza 0 coada eu prioritate in care plascaza primele 5 caractere din sirul s si leorganizcaza ca max-heap; containerul care Ie srocheaza esre eel implicit, adicavector; criteriul de comparare estecel implicit (operatorul -c},

struct Punet{

double x, Y;friend beel operator «canst Punct&, . canst Punet&)

) ;

heel operator «const Punct& pl, censt Punct& p2){ return pl.x<p2.x I I pl.x==p2.x && pl.y<p2.y; }

Am definit un tip denumit Punct (reprezentand un punct pr in coordonatele salecarteziene) si am supraincarcat operarorul < pentru tipul Punct.

Ii priority_queue<Punet> pq4;

Creeaza 0 coada Cll prioritate vida cu clemente de tip Punc t; se utihzcazacontainerul implicit (vector) ~i operatorul -c pentru comparare.

class ComparPunct{public:bool operator () {canst Punct& pl, const Punct& p2J{ return p L _x<p2 . x I I pl. x""""p2 . x && pJ . y<p2 . y; }

} ;

a alta varianra de implementare ar fi sa definim un functor de coml?~lrare apunctelor.

l- priority_queue<Punct, deque<Punct>, comparPunct> pq5;

Page 96: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

~.J

Functiile membre publice

Am creat 0 coada ell prioritate cu elemente de tip Pun c t., oontaineruj utilizatpentru stocarea elementelor este deque, iar compararca se realizeaza eu fuuctonnComparPunct.

Observatii jinale

1. Elementele dintr-un priori ty_queue fiind structurate ca un heap, operatiilepush () si pop () se executa in tirnp logaritmic. Pentru stack si queue acesreoperant se executa in timp constant. -

2. Niciuna dintre clasele adaptor stack, queue ~i priori tY_Queue nu dispunede iteratori.

3. Opera{iile definite pentru clascle adaptor utilizeaza funetii ale clasci containerSUpOTt. De exemplu, pentru toate cele 3 clase adaptor standard, clasa containersupon rrcbuie sa aiba definila funqia push_back()'(utilizatade-funqia push()ale claselor adaptor). Clasele stack §i priori ty_queue utilizeaza pentru

Clasa adaptor priori ty_queue are 0 inrerfatg simpla, foarte asemanatoare cuinterfata cIasei queue:

hoel empty() canst;

Rerumeaza true daca numarul de elemente este O.

size_type size() canst;

Returneaza numarul de elemente.

const value_type& top{) canst;

Returneaza 0 referinta la primul element (eel ell prioritatea maxima).

void push (canst value_type& va~) ;

Insereaza vaJoarea val; functia apeleaza push_back () din containerul suport,apoi apeleaza push_heap () pentru a restaura proprieratea de heap.

[ void pop ( ) ;

Extrage elementul eu prioritatea maxima; este apelata functia pop_heap ( ) , apoipop_back () pentru containerul suport.

~ template <class ... Args> void emplace (Args&& ... args)i

Functie spccfflca C++ 1'1, creeaza un element (apeland constructorul adecvat infunctie de parametrii specificati) §i insereaza elementul creat.

11 void swap (priori ty_queue& x) noexcept;

Interschimba coada eu prioritate curenta cu coada eu prioritate x, transmisa caparametru (functie disponibila incepand cu C++ 11). Incepand cu C++ 11, estesupraincarcata funcpa swap () si ca functie indeperrdenta (nernembra a clasei).

~

,,,u

I i~

~

l.....J

'.-;

, ',

I I

'-

, '

191

pe care va fi aflsata

CLASELE ADAPTOR

2 :5 N :5 10000, N parPentru orice pilot, 1 ~ a < c ::; 100 000•

Fisierul de iesire pi loti . out va contine 0 singura liniesuma minima necesara pcntru a plati salariile celor N piloti.

Restricfii

Aplicatia 6. Piloti

functia pop () funcua clasei suport pop_back ( ) , in timp de clasa queue utili­zeaza pentru functia pop () funcj!a clasei suport pop_front (). In ceea ceprivcste accesul la elemente, pentru clasa adaptor queue sunt necesare functiilefront () si back (), pentru clasa stack este necesara functia back (), iarpentru priori ty_queue este neccsara funcpa front () .

4. Operator-ii relational i nu sunt supraincarcati pcnrru priori ty~queue, dar sumsupraincarcati penrru stack si queue, considerand ordinea lexicografica.

Vasile are 0 companie de transport aerian, Pentru a se mentine pe piaIa, eI trebuicsa reduca cheltuielile cat mai mult posibil.

La compania sa exista N piloti (N par). Pilotii sunt numerotati de 1a 1 la N inordinea crescatoare a varstei (pilotul 1 este eel. mai tanar , pilotul N eel mai batran).

Vasile trebuie sa formeze N/2 echipaje. Un echipaj este format din doi pilot!(capitanul si asistentul sau). Capitanul trebuie sa fie mai in varsta dedit asistentulSail. in contractu] fiecarui pilot sunt prcvazute coua salarii: unul pentru cazul in careel este capitan al echipajului, celalalt pcntru cazul in care el este asistent. Evident,pentru orice pilot salariul sau de capitan este mai mare decat salariul sau de asistent.Salariile pot sa difere de la un pilot la altul. Chiar se poate intampla ca salariulcapitanuiui sa fie mai mic decat salariul asistentului ssu.

Pentru a chelrui cat mai putini bani pe salariile pilotilor, Vasile trebuie sa deter­mine 0 distribuire optirnala a pilotilor pe echipaje.

Ceriruii

Scrieti un program care sa determine suma minima neccsara pentru a platisalarille pilotilor.

Date de intrare

Fisierul de intrare pd Lo t a. in contine pe prfma linie un numar natural N repre­zentand numarul de piloti. -Pc urrnatoarele N linii:- sunt infot-matii despre salariilepilotilor. Pe linia i + 1 se afla doua numere naturale c :;Ii a separate printr-un spatiu(c reprczinta salariul pilotului i pe post de capitan, iar a reprez.inta salariul piJotuluii pe post de asistent).

Date de iesire

PROGRAMAREA TN UMBJ\JUL CIC++ PENTRU L1CEU190

Page 97: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

192 PROGRAMAREA IN LIMBAJUL CIC '~-'1 PENTRL! ucn.1

CLASELE ADAPTOR '93

r-

r-«

r-

ri,

Exemple

piloti.in piloti.out. piloti.in piloti.out6 32000 6 3300010000 7000 5000 30009000 3000 4000 10006000 4000 9000 70005000 1000 11000 50009000 3000 7000 30008000 6000 8000 6000

(vcampion 2004)

Solutie

Metoda de rezolvare este Greedy.Primul pilot trebuie sa fie asistent (fiind eel mai tanar). Dintre 'pilotii 2 $i 3 unul

trebuie sa fie asistent. Dintre pilotii 4, 5 si eel care a dimas dintre 2 ~i 3 unul trebuiesa fie asistent. Deci la fieeare doi pilot! cititi trebuie sa aleg unul dintre cei existent!care sa fie plasat pe post de asistent (alegerea se face dintre toti pilotii citip deja §icare nu au fost stabiliti ca asistenti). Criteriul de alegerc : diferenta dintre salariuJsau de capitan ~i salariul sau de asistent sa fie maxima.

Pentru a determina suma totals minima necesara pentru a plati salariile pilotilor,vom utiliza 0 variabila rez. Cand citesc un pilot, voi considera ca el este capitan $ivoi adauga salarful lui de capitan la r ez , iar diferenta dintre salariul sau de capitan §isalariul sau de asistent a vel insera intr-un max-heap H. Dar dupe fiecare doua citiritrebuie sa aleg un asistent. In acest scop, voi extrage maximul din max-heap-ui H.Din rez voi scadea maximul extras (ceea ce inseamna ca pilotul corespunzatordevine asistent)".

I, #include <fstream>II #include <queue>

using narnespace std;.of-s t.r eem fout ( "pi loti . out" )ifstream fin ("piloti. in") ;

priority~queue<int> Hi

int main (void){int n , rez = 0, capitan, asistent, ijfin»njfor (i=Oj i<n; ++i)

{ fin » capitan » asistent;rez += capitan;H.push(capitan-asistent) ;if'li%2==01

{ rez -=H.top()i H.pop()

5. 0 implcrucntarc tara SlL poare f cousultata in capiLolul :3 din volumul al Ill-lea at lucrari iProgramarea In limbojut CIC-+- -l- pennu ticeu,

}fou t « rez < '\n I j

fout. close ()return OJ

Aplicatia 7. Ksecv

Fie un sir ab a2, ... , a., de Nnumere intregi 1?i K un numar natural. 0 secventaai, a r-a , a , ... => , ••• , aj din sir spunem ca este x-secvenra daca exista eel mult ,Knumere strict mai mad decat ai.

De exemplu, pentru N=10, sirul a=3,6,4,2,l,lO,9,S,8,-Z Si K=3,

. 6, 4,2, 1, 10,9, 5, 8 este x-secvenja pentru ca sunt exact 3 numere strict mai maridecat 6. La fel, 5, 8 17 este x-secventa pentru ca sum doar doua numere strict maimari decat S. .

Cerirua

Scrieti un program care sa determine inceputul §i sfarsitul penrru cea mai lungax-secventa din sir.

Date de intrare

Eisierul de intrare ksecv. in contine pe prima linie numerele naturale N !;i K, iarpe a daua linie elementele a , a2 ... aN ale strului. separate pr in care uu spatiu.

Date de iesire

Fisierul de iesire ks ecv . aut va contine pe prima l.inic doua nurnere naturaleincmax si sfmax separate pr'intr-un spatiu, reprezentand indicii de inceput si desfarsit a1 x-sccventei de lungime maxima. Dacs sunt mai multe solutii , se va scrieaceea pentru care incrnax este minim.

.Restriqii

• 3 ::; N < 100 000

• 1 :s; K :5: N

• '-10 9::; ai ::; 10 9

, pent~u orice i intrc 1 §i N.

Exemplu

k s ecv . in ksecv.out Explicatii

10 3 2 9 Cea mai lunga j-sccvcnts estc cea care incept

3 6 4 2 1 10 9 5 8 ') la pozitia 2 si se inchcie la poxitia 9, adtca 64 2 1 10 9 5 8, in accasta secventiilcxistand 3 numcrc strict rnai mart dedit 6.

( .campion 2011)

Page 98: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

194 PROGRAMAREA iN LlMBAJUL C/C+-+ PENTRU LJCEU CLASELE ADAPTOR 195

~

Solutie

Vom parcurge sirul a element ell element ~j la fiecare pas i mcercam saconstruim cea mai lunge K-secvenla care incepe ell ai' Pentru aceasta trebuie Satinem evidenta elementelor strict mai mari decat ai' Cand numarul acestor clementeeste egal ell K (sau am terminat de parcurs sirul a) atunci am obtinut 0 x-secvenjsrnaximala, 0 comparam eli cea mai Iunga K-secventa si 0 retinem daca este cazul.Apoi incercam sa construim 0 alta x-secventa. Pentru a nu obtine un algoritm patratic,in constructia secventei urmatoare ne vom baza pc secvenja curenta, Sa no ram eli xincepurul x-secventei curente §i ell a , elementul curent pe care il analizam din sirula. Exista doua cazuri posibile :

• x~ai' in acest caz nu arc sens sa consrruim x-secventa care incepe cu ai,deoarece lungimea acesteia nu va fi mai mare decat lungirnea maxima curenta.

• x-ca, . In aces! caz vom construi x-secventa care incepe cu ai. in k-secvenjacurenta noi aveam K elemente mai mari decat x. Dintre acestea uncle sun! maimari decat ai, altele nu. Elementele care sunt mai rnari decat ai Ie contorizam insecventa care va incepe cu ai, dar celelalte nu. Pr'in urmare, trebuie sa _eliminamdin structura de date in care tinem evidenta elementelor > x din secventa curentape cele mai mid (adica .cele care sunt :5 a.j). Deducern ca structura de date incare retinern cvldenja elernentelor > x trebuie sa permits executarea eficienra adoua operatii : extragerea minimului si inserarea. Prin urmare trebuie sa fie unmin-heap. Revenind: extragem din min-heap eel mai mic element, cat timpacesta este ,5;;ai' Apoi completam secventa care incepe cu ai (adica adaugsmelemente la sccventa atat limp cat min-heap-us nu are lungimea > K). Accasta vadeveni secventa curenta, iar procedeul descris se repcta.

#include <cstdio>#include <queue>#define NMAX 100000using namespace stdiint n , k ,: Lqma.x , incmax, sfmax;int a [NMAX] ;priority_queue<int, vector<int>, greater<int> > H;

int main(){int i, x, sf;FILE * fin=fopen("ksecv.in","r");FILE *fout=fopen ("ksecv. out ", "w'") ;

fscanf (fin, "%d %d", &n, &k) i

for (i=O; dcn : i++) fscanf (fin, "%d" ,&a[i] 1x=a[O]-l; 8f=0;for (i=O; i<n; i++)

if (a[i]>x) /Ieonstruim 0 k-seeventa incepand eu ali]{//eliminarn din heap elementele <-= a[iJwhile (!H.empt.y()" && H:top()<'=a[i]} H.pop()

/Iadaugam elemente cat timp e posibil

while (sf<n)if (a[sf]<=a[i]) sf++;

elseif (H.size()<kl {H.push(a[sf]) i Sf++i}

else break;/Icompar lungimea seeventei curenLe cu 19maxif (lgmax«sf-i»)

{lgmax=sf-i; incmax=i+l; sfmax=sf;}xe a [iJ;)

f p r Lntf (fout, "%d %d\n", incmax, sfmax)fclose (fout) ;return 0;

Aplicatia 8. Algoritmul lui Kruskal optimizat

Algoritmul lui Kruskal'' construieste un arbore partial de cost minim pentru ungraf neorientat conex ~i ponderat.

Metoda utilizata este Greedy: cat timp este posibil , selcctam 0 muchie de costminim care nu a mai fost selectata si care nu formeaza cicluri cu muchiile dejaselectate. Nurnarul de muchii selectate va fi n-l (unde eu n am notat numarul devarfuri din graf).

Pentru a selccta eficient 0 muchie de cost minim, vom organiza muchiile ca unmin-heap, in funcne de cost.

Pentru a testa dace 0 muchie formeaza cicluri cu muchiile deja selectate, trebuiesa tinem evidenta componentelor eonexe formate eu muchiile deja selectate. Pentru 0

implemencare eficienta vorn utiliza algoritmii Union-Find7 optimizati,

Reprezentarea informatiiior

1. Vom defini un struct denumit Muchie in care retinem extremiratile uncimuchii $i costul aeesteia. Supraincarcam operatorul > pentru comparareamuchiilor (deoarece dorhn sa organizam muchiile ea un min-heap).

2. in coada cu prioritate H retinem muchiile grafului, organizate ca un min-heap infunctie de cost.

3. In vectorul sol vom retine muchiile ce forrneaza arborele partial de cost minim;in costmin retinern suma costurilor muchiilor selectate.

4. Pentru a reprezenta cornponentele conexe ale grafului(care sunt multimi disjunctede muchii), vom considera ca fiecare componenta conexa este Ull arbore. Repre­zentam arborii prin referinte ascendente (mai exact, pentru fiecare varf x retinemtat a [x] = nodul par-inte al lui x, respectiv a dadi x este radacina arborelui).Operatia Find (xl determina radacina arborelui din care face parte x (~i. pentru

6. 0 descrierc dClalialll ;;i a impJememare pcntru algoritmuLlui Kruskal purctic9nsulta !n cupilolul I dinvolumul al Ill-lea al lucrarii Programarea in limbajul C/C+ + penrru licel/.

7. Reprezeniarca multimilor disjunctc ~i implcmentarea oplimizata a algoritmilor Union-Find se afla incapiiOlul 3 din volumul al III-tea al lucrarii Programarea in limbajul C/C+ -I- pemru liceu.

; !

U

r ~

~

G

~

....j

~J

~

~

....j

....j

Page 99: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

196 PROGRAMAREA iN LlMBAJUL C/C++ PENTRU LTCEU

I!~

CLASELE ADAPTOR 197

,,

t :

,...,

r"'

,

rI ,

I,r

eficienta, compreseaza drumul de la x la radaclna). Opcratia Union (c r . c2)unifica arborii corespunzaron componenteJor conexe ci si c2 (radacina arboreluiell inaltimea mai mica devine fiul radaclnii celuilalt). Pentru a implernenjgoperatia Union eficient este necesar sa redncm ~i inaltimea fiecarui arbore format(h lx l = tnalrimca arborelui eli radacina x).

#include <fstream>#include <queue>#define NMAX lOOlusing n~espace std;

struct Muchie{int X, Yidouble coat; i

friend bool operator > (const Muchie&,const Muchie&)} ; .

bool. operator > (const Muchie& ml, const Muchie& m2){ return ml.cost>m2.cost; }

priority_queue<Muchie, vector<Muchie>, greater<Muchie> > Hi

veetor<Muehie> sol;int tata[NMAXJint h [NMAX) ;int n;double eostrnin;

void Citire();void Afisare();int Find (int);void Union (int, int};

int main (l{int c'L. cz •Muehie rn;c i t d r e t j •while (sol.size()<n-1)

Ileat timp nu am se1eetat cele n-1 muchii{Ilextrag din H muehia de cost minimm=H. top I ); H. pop ( ) ;Iidetermin componentele conexe din care fac parteIlextremitatile muchiei se1ectate mcl=Find(m.x); c2=Find{m.y);if (cl!=c2)

11m nu formeaza cic1uri cu muchiile se1eetate{I/selectez aeeasta muchie

oo s t.mi n-r em . cost; sol. push_back (m) ;

Ilunific c cmpo erreri t e Le correxe ale ~e?Ctr~;:nitatilo:;;-

8nioniel, c2)"; .

Afisare ()return 0;

void Citire(){Muehie m;int i, nrm;FILE * fin=fopen ("kruskal. in", "r tl

) ;

fscanf(fin,"%d%d", &n, &nrm);for (i=O; i<nrm; i++)

{fscanf (fin, "ltd %d %1£", &rn.x, &m.y, &rn.cost);

H . push 1m); }

void Afisare (){FILE * fout=fopen{"kruskal.ou,t", "w"};fprintf(fout, "%.21f\n", costmin);for (int i=O; i<n-l; i++)

fprintf(fout,"%d %d\n",solli) .x,sol[i} .y)felose(fout)

}

,int Find tint xl{int r=x;I/determinam radacina arboreluiwhile (tata[r)l r=tatafr]!!comp~esam drumulint y=x, aux;while (yl=r)

{ aux=tata ly l : tata [y]'=r; 'ye a ux :return y.

void Union (int el, int c2)(if (h[clJ>hlc2]) tatalc2]=cl;~e~se

{tata[cl)=c2;if (hlcl]=~h[c2]) hlc2]++;

Aplicatia 9. Algoritmul lui Dijkstra optimizat

Algoritmu1 lui Dijkstra" deterrnina un drum de cost minim de la varful de start xOla fiecare dintre celelalte varfuri ale unui graf ponderer dat.

R. 0 descrlerc dctafiata st 0 implcmcruarc pcntru algoritmul lui Dijkstra putcti consulta in capltoluldin volumul al Ill-lea al lucrarii Programareo tn Iinmajut OC+ + pentru ticeu,

Page 100: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

p~

L..j

198 PROGRAMAREA iN LIMBAJUL C/C +-1 PENTRU LleEU CLASELE ADAPTOR 199

-Compsi-vr- este functorul care compara doua varfun :

Pentru a reconsritui drumurile, este necesar ca pentru fiecare varf x sa retinemprec [x] = varful care Il preceda pe x pe drumul minim de Ja xO la x; (varful xOnu are precedent, deci prec [xO] =0).

int prec [NMAX] ;

Yom utiliza 0 coada cu prioritate H, in care inserarn varfurile grafului pe masurgee acestea sunt parcurse, astfel Incat Ia fieeare pas sa putem exrrage varful pentrucare dmin este minim (min-heap).

priority_queue<int, vector<int>, ComparVf> H;

Reprezentarea informatiilor

Yom reprezenta grand pr in liste de adiacenja eli costuri. Mai exact penrru fiecarevarf x din graf retinern arcele eli extreruiratea initiala x intr-un vector de perechide numere intregi (pe t r-c f.n t, int»; primul numar din pereche (f irst) ..reprezinta extrernitatea flnala a arcului, iar a1 doilea numar din pereche (second)reprezinta cosrul arcului respccttv.

fl vector < pair<int,int> > G(NMAX] i

Costurile drumurilor minime Ie vom reline in vectorul drnin (drnin [x] = cosnudrumului minim de 1a varful xO la varful x; daca nu exista drum de la x 0 Ia x,dmin [xl =INF, unde INF este 0 constanta suficient de mare).

int drnin [NloIAX] ;

Initial:

dmin [x] =INF, pentru orice x if:- xO §i dmin [xO] =0 ;prec lx l =xO, pentru orlce x if:- xO §i pre.c [xO] =0;inseram in coada ell prioritate H varful de start xn.

Cat timp in coada ell prioritate H mai exista varfuri :extragem un varf vfmin din H (varful situat la distanja minima de xO) ;parcurgem lista de adiacenta a varfului vfmin si incercam sa optimizam costuriledrumurilor varfurilor care sunt extremitati finale ale areelor care pleaca din vfmin.

#include <cstdio>#include <vector>1finclude <queue>#define INF 1000000000·ildefine N1'-1AX' 5000.J.

: i

~

...;

~

"-'

,~

void citire();void dijkstra();void afisare();

)void ci tire (){int i, ill, X, y, Ci

FILE * fin=fopen("dijkstra.in","r")fscanf (fin, "%d %d %d", &n, &m, &xO);for (i=O; i<m; i++)

{fscanf(fin,"%d %d %d_~t,.&x., &y, .. &c)j

G[x] .push_back(make-pair(y,cJJ; }

void dijkstra (){int i, vfmin;for (i=l; i<=n; i++l {dmin[i]=INF; prec[i]=xO;}dmin[xO]=O; prec[xO]=OiH.push(xO) ;while (!H.empty())

{vfmin=H.top(); H.pop();for (i=O; i<G[vfminJ .size{); i++)

Ilparcurg lista de adiacenta a lui vfminif Ldm.i n [G [vfmin] [i] . first) >

dminlvfmini+G.[vfmin) [i] .secor~d) Iloptimizez

cmtn tc Lvru-Ln lLi I .first]dmin lv Erru.n l +G [v f mi.n j [i J • second;

int main ()(

citire() ;dijkstra ()afisare () ;return 0;

using namespace std;

int n, x Oi

vector < pair<int,int> > GtNMAXJLnt; dm.i.n lNVJl;I...X]int prec[NMAX]FILE ",. fout;

class ComparVf{public:hool operator () (const int& x . const int& y){ return dmin[x] >dmin [y] ;

) ;

priority~queue<int, vector<int>, ComparVf> H;

" }

I

x, const int& y)I'class ComparVf

{public:: hool operator (l (const int&

{ return dmin[x]>dmin[y]I };

Page 101: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

200 PROGRAMAREA IN UMBAJUL CIC++ PENTRU LICEU CLASELE ADAPTOR 201

prec[G[vfmin] [il .firstJ=vfmin;H.push(GLvfmin] [i] .first) i

)

Ce se va afisa pe ecran In cazul In care declaratia obiectului C este :

a. s t a ok-c Ln t.> c;b. priori ty__qu eue-c Lrrt.> C;

void drum tint xl{if (x )

{drum(prec[x}) ;fprintf(fout, "%d

)

x)

2. Scrien 0 secventa fermata dlntr-un numar minim de operatii push ( ) , pop () ~i

afisarea-elementului de Ia varf (top ( ) dupa executia careia. plecand de Ia 0

stiva initial vida, obtinem pe ecran cuvantul mama.

3. Care dintre urmatoarele secvente afiseaza elcruentele din coada eu prioritate H?

~ priority_queue<int>H;

Observatii

1. Acelasi varf poate fi inserat in coada ell prioritate H de mai multe ori. Ca urmare,implementand astfel algcritmul lui Dijkstra , dimensiunea rnemoriei necesarepentru coada eli prioritate H este de Ojm), unde ell In am notat numarul de arce dingraf. Memoria ueccsara pentru H ar putea fi de O(n) (unde ell n am notat numarul'de varfuri. din graf), doar dace atunci cand cptimizam cosrul drumului catre unvarf y nu il inseram III H, ci verlflcam deca el exista sau nu in H. Daca y nuexista In H, il inseram. Daca y exista deja in H, nu il inseram, ci II prornovam inheap pe y, conform noii sale valori. Peutru aceasta ar trebui sa implemcntam noioperatiile eu heap-ul pentru a putea reline §i pozitia fiecarui element In heap.

2. Complexitatea aIgoritmului lui Dijkstra implementat ell heap este O(m log n).

drnin [i ] I ;

d.

b.

, .i++) cout«H[iJ«'

b.

a.

Ii for (int i=Oi i<H.size()

c.

~ while (! H. empty ()) COli t«H. pop ( ) «' ';

d.

c.

t list<string> L (5, "mama ") ;~ queue<string, list<string> >~ H (Ll ;

f. priority_queue<int>: :iterator it;t for (it=H.begin(); it!=H.end(); ++it) cout«*it«'

~ while (! H . empty ( }) {cout«H. top ( ) «' '; H. pop ( ) ; }

4. Care dintre urmatoarele declaratii pentru obiectul H sunt corecte ?

a.

l priority_queue<int, list<int> > Hi

r priority_queue<int, deque<int>, greater> H;

5. Care dintre urmaroarcle afinnatii sunt adevarate ?a. Grice clasa poate fi utilizata drept clasa suporr pentru containerul adaptor queue.

b. Operatorul de indexare nu este supretncarcat pentru clasa adaptor stack.c. La declararca unui obiect de tip queue u-ebuie sa specificam tipul elemen­

telor, containerul suport, precum si criteriuJ de comparare a elementelor.d. Pcntru toate containerele adaptor standard din STL inserarea si exrragerea

elernentelor din container se real izeaza In timp constant.e. Niciuna dintre afirmatiile precedente .

j string 5 ( "mama" ) ;__~ .. stack<char> H(s) ~

II

I

void afisare ( ){fout=fopen ("dijkstra. out" r "W") ;

for (int i=l; i<=n; i++)if (il=xO)if (dmin[i]==INFl

fprintf (fout, "O\n");el.se(

fprintf(fout, "%d:drum(i) ;fprintf (fout, II \n") ;

)

fclose (fout) i

)

6.4. Exercitii §i probleme propuse

1. Sa consideram urmatoarea secventa de operatii :

C.push(7);C.pushllOI ;C.push(2) ;C.pushI131 ;C.push(251;while r : C. empty ( ) )

'{ -cou t cec . top ()«'

C .pop (); )

r­,

)

r­,

r-

!

r!

r-'

!

Page 102: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

202 PROGRAMAREA iN LlMBAJUL C/C++ PENTRU LlCEU

III'!""

CLASELE ADAPTOR 203

6. Implementati parcurgerea in latime (BFS) a unui graf, util.izand c1asa queue.

7. Implernentati algoritmul lui Prim de determinare a unui arbore partial de Costminim, optimizandu-I prin utilizarea unui heap. Pentru implementare, uttlizaj,clasa adaptor priori ty_queue.

8. Implementati algoritmul Ford-Fulkerson de detenninare a unui flux maxim intr-oretea de transport, util izand biblioteca STL.

9. Swapo porantemre corecta se obtine aplicand una dintre urmatoarele reguli :

sirul vid este 0 parantezare corecta ; .daca s este 0 parantezare corecta, atunei (s) este a parantezare corecra, iarcele doua paranteze ( !ji ) care incadreaza sirul s sum denumite pararuezepereche :daca 51' 52' ... , 5",- sunt paranrezan corecre atunci sirul 5 15 2... Sk obrinutprin concatenarea acestora este 0 parantezare corecta.

De exemplu sirurile (), () (), (()) !ji (() () ) () reprezinta parantezari corecte,'in timp ce ) t , () () ( !ji (() () ) ) ) nu sunt parantczari corecte.

Fie 5 un sir care rcprezinta 0 parantezare corccra. Pentru fiecare dintre paran­tezeIe pereche din sirul S asociem un cost egal cu diferenta dintre pozitia pe care seafla in S paranteza inchisa §i pozida parantezei deschise pereche. Poz.itiile in sir leconsiderarn numerotate incepand cu 1. Costul total al unci parantezari corecte ilreprezinta suma costurilor tuturor parantezelor pereche din aceasta.

De exemplu , sirul (() ()) este format din trei paranteze pereche, situate pepozitiile 2 si 3, 4 si 5 si respectiv 1 si 6. CostuI total al parantezarii este 3-2+5-4+6-1~7.

Numim operatic swap imerschimbarea a doua paranteze situate In sir pe pozitiialarurate. Aceasta operatic cstc validd doar dad! siru I nou obtinut este la randul sau 0

parantezare corecta ~i daca noua parantezarc are costul total strict mai mic decat ceainitiala.

Cerillrli

Scrieti un program care cite§te 0 succcsiune de N caractere reprezenrand 0parantezare corecta !jl detcrmina :

a) Costul total asociat parantczarii dtite ;b) CostuI minim a1 unci parantezari obtinute prill efectuarea unci singure operatii

swap valide asupra paramczarii citite ;c) Numarul de posibilitati de a efectua 0 singura operat.ie swap valida asupra

parantezarii ini\iale pemru a ebtine cestuI dcterminat conform cerintei b).

Date de irurare

Fi~ierul de intrare swap. in contine pe prima linie numarul natural N $i pc a doualinit~· 0 succcsiune de N caractere rcprezeritano. 0 parantezarccorecta,

Date de iesire

Fisierul de iesire swap. out va conpne pe prima linie un numar natural repre­zcntand costul parantezarii citite. A doua linie va contine un numar natural repre­zemand costul minim deterrninat conform cerlntci b) sau valoarea -1 cand nu sepoate efectua nici ·0 operatie swap valida asupra parantezarii citite. A treia linie afisierului va contine un numar natural reprezcntand raspunsul la certnta c) sau 0 dacanumarul afisat conform cerintei b) a fost -l.

Restrictie

• 2 :0:;; N .s. 90000

Exemplu

swap. in swap. out Explicajii

8 6 Pemru ccrinta a) costul paramezarii estc 2-1+6-3+5-4+8-7~6.

II I I I I I I 4 Executand 0 operatic swap inrre parantczclc de pc pozitiile 4 s! 5 se

1 obtinc strul () ( ) () () care are costul 4, aceasra fiind singura posibi-litatc de a obtine acest cost.

Olimpiada Nanonala de Informatica pentru Gimnaziu, 2013

10. ValetVasile lucrcaza 'intr-o pareare. Sarcina lui este sa scoata masinlle clientilor din

parcare. Terenul de parcare este dreptunghiular, format din nxm zone ideruicc ,aranjate pe n linii si m coloane. Lini ile sunt numerotate de Ia 1 la n , iar coloanele dela 1 la m. Iesirea din parcare este in coltul parcarii si are coordonatele (1, 1). infiecare zona se poate afla 0 masina, un stalp sau poate fi ribera. Parcarea este.plina,singura zona libera fiind iesirea din ,parcare. Prin urmare, este foarte complicat sascoti a masina din parcare. Pentru a-s! face loc, Vasile poate muta 0 masina din zonaIn care este plasatji 'in una dintre zonele invecinate , dace aceasta este libera. Evident,stalpii nu pot fi mutati. doar mastuilc. Doua zone sunt invecinate daca se afla pcaceea~i linie, pe coloane consecutive, sau pe aceea~i coloana,_p.e Jinij consecutive.

Cerinr li

Scrieti un program care sa determine numarul minim. de mutari de ma~ini pc earetrebuie sa Ie execute Vasile pentru a seoate 0 ma!jina din parcare, daca acest lucrueste posibil.

Date de intrare

Fi~ierul de intrare valet. in contine pc prima linie numerele naturale n ~i In

separate prin spatiu. Urmcaza n linii, fiecare continand cate In caracterc din 1l1ultimea{ , . " '#', 'c', 'X'}. CaracteruI '.' indica zona libera. Caracterul '#' indicaun staip. Caraeterul 'c' indica 0 ma$ina pareadi. Caracterul 'x' indica ma$ina pccare Vasile trebuie sa 0 sceam din parcare. in fi~ierul de inrrare exista un singurcaracter 1 x' :;;i un .siJ1gur caracter _' . ' . plasat in ccltlil, (,I" 1,) . ~.J "p'-!rcarii.

'-'

--

~

~

~

-'

~

L.....!

~

Page 103: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

'C:~.

204 PROGRAMAREA IN LIMBAJUL etc+-+ PENTRU LICEUCLASELE ADAPTOR ')05

c-'

Date de tesire

Fisierul de iesire valet. out va contine 0 singura lillie pe care va f scrisnumarul minim de mutar-i pe care trebuie sa Ie efectueze Vasile pentru a scoatemasina din parcare, daca acest lucru este posibil. in caz contrar, pe prima Iinie se vascrie cuvantul imposib:i.l.

Restriaie

Exemplu,-~

predecesor.in predecesor.out10 6

8 12 2 4 3 10 9 7 5 6

.campion 2009

.campion 2011

• 1 ~ n , m -s; 50

Exemple

11. Predecesor

Considerarn un sir de N numere naturale distincre al, e a, "" aN' Pentru fiecaretermen ai defluim predecesorul sau, daca exisra, ca fiind cel mai din dreapta terrnenaj, cu j<i si aj<ai· De exemplu, pentru sirul 8, 12,2,4,3,10,9,7,5,6,numarul 8 este predecesorul lui 12, 3 este predecesorul lui 5, in tirnp ce 10, 4 §i 2nu sunt predecesor-ii niciunui numar.

Cerinta

Scrien un program care determina care numere din sir nu sunt predecesori ainiciunui ali numar.

Date de intrare

"Eisierul de'<intrare predecesor. iti·'CbnIine pe prima Iinie numarul 'natural Nreprezentand nurnarul de termeni ai sirului. Pe urtuatoarea linie se gasesc, separatiprin cate un spajiu, termenii al, a2, "', aN ai ~irului.

Date de'iqire

Fi~ierul de ie§ire predecesor. out.va contine 0 singura linie pc care va fi scrisun singur numar natural reprezentand nWllaruJ de termeni ai l}irului care nu sumpredecesori ai niciunui alt numar.

RestriCfii Fi~ierul cezar. in contine pe prima linie doua valori n k separate printr-unsatiu reprezentand numarul total de senatori §i numarul de stdizl pe care circuJalectiea gratuita. Pe urmatoarele n-l hnii se afla cate doua valori i §i j separateprintr-un spatiu, eu semnifieatia di intre casele i §i j exista strada .

12~ Cezarin Roma antlca exista n case senatorialc distincte, care una pentru fiecare dintre

cei n senator! ai Republicii. Casele senatoriale sunt numerotate de la 1 la n , intreoricare ooua case existand legaturi directe sau ,indirecte. 0 legatura eSI(' dirccta dacaea nu mai trece prin alre case scnarorialc intermediare. Edilii au pavat uncle dintrelegjltur'ile directe dintre doua case (numind 0 astfel de legatura pavata " strada"),astfel incat intre oricare doua case senatoriale sa existe 0 singura succesiunc de strazlprin care se poate ajunge de la a casa senatoriala Ia cealalta.

Tori senatorii trebuie sa participe la sedtntelc Senatului. in acesr scop, ei sedeplaseaza cu lectica. Grice senator care se deplaseaza pe 0 strada plateste 1 banpentru ca a fast transportat ell lectica pe acea strada.

La alcgerea sa ea prim consul, Cezar a prornis ca va data Roma cu 0 lecticagratuita care sa circule pe un numar de k strazi ale Rornei astfel incat orice senator'care va circuIa pe straaile respective sa poata folosi lectica gratuita tara a plati.Strazile pe care se deplascaza lectica graruita trebuie sa fie legate intre eIe (zborul,metroul sau teleportarea ncfiind posibile la acea vreme).

in plus, Cezar a promis sa stabileasca sediul salii de sedinte a Senatului intr-unadintre casele senatoriale af1ate pe traseul lecticii gratuite. Problema este de a alegecele k srrazi ~i arnplasarea sediului salii de sedinte a Senatului astfel incat, prinfolosirea transportului gratuit. senator ii, in drumul lor spre sala de scdintc. sa facaeconomii cat mai Insemnate. in calculul costului total de transport, peutru totisenatorii, Cezar a considerar di fiecare senator va calatori exact 0 data de la casa sapana la sal a dG_~epiIl!~ a S.~,!~LUJt!i.

Cerinpi

Scrieti un program care determina costul minim care se poate obline prin alegercaadecvata a eelor k strazi pc care va circula lectica gratuita §i a locului dc amplasare asaW de §edin!a a Senatului.

Date de ilurare

valet. in valet.out valet.in I valet.out3 3 imposibil 2 3 7.#X .eXeee eeee#e

3 ~ N S 500 000

1 ~ ai S 1 000 000 000, pentru ariee l:;i~N

••

r-

r-.

r-'

l;

,.....," .

,-I

Page 104: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

i'206 PROGRAMAREA IN LIMBAJUL etC ++ PENTRU LICEV

~

Date de iesire

Pe prima linie a fisierului cezar. out 'se va scrie costul total minim altrausportarii tllturor senatorilor pentru 0 alegere optima a celor k strazi pc care vacircula tecrica gratuita si a Iocului unde va fi amplasara sala de sedinte a Senatului.

Restrictii

'-'

w

1 < n S 10000, O'<k-cna s L, j5n, ii'j

Strazile din fisierul de intrare rcprezinra doua strazi distincte.

Exemple

•••

cezar.in

13 31 2

2 3

2 87 8

7 5

5 4

5 6

8 9

8 1010 11101210 13

cezar.Qut

11Explicatii

Costul minim sc cbtine. de exemplu, pcntru alegerea celor 3 straziintre casele 5 -7 I 7 - 8 , 8-1 0 ~i a salii de scdinte a Senatufui incasa 8:

6

Exista gi alte alegcri pentru Care se obtinc solujia 11.

Olimpiada Judeteana de Informatica 2007

7. Containere asociative

In biblioteca STL sunt definite patru containere asociative sortate: set, mul tiset,map !}i multimap. [ncepaud eli C++ 11, biblioteca STL include §i containereasociative nesortate: unordered_set, unordered_multiset, unor-der-ecjmap~iunordered_multimap.

in cadruJ containerelor asociative elementele nu sunt identificate prin pozitiaacestora in cadrul containerului, ci prin intermcdiul unci clzei. in cazul containerelorasociative sortate , elementele sunt stocate in ordinea cheilor , conform unui criteriude comparare specificat. Pentru containerele asociative, operariile de inserare, ster­gere si cautare se realizeaza foarte eficient.

7.1. Containerele asociative sortate set i?i multiset

Containerul set stocheaza clemente distincte intr-a anurnita ordine. Vom denumi uncontainer de tip set multime. Elementele trur-o multlme sunt identificate prin valoarcalor. Cu alte cuviruc, in cazuJ containerului asociativ set, cheia ~i valoarea coincid.

Containerul rnultiset este asemanator , diferenta constand in faprul di valorilenu sunt distincte (ele se pot repeta). Vom denumi un container de tip rnul tisetmultimultime.

Pentru a utiliza aceste clase trebuie sa includem fisierul antet set:

#include <set>

Declaratia clasei set:

~

/1

~

~

, '

~

, ,

template < class T,class Compareclass Alloe

> class seti

= less<T>,allocator<T> >

~

Clasa sablon set are trei ripuri specificate ca pararnetri:T - tipul valorilor stocate ;Compare - criteriul urilizat pentru cornpararea elememelor (implicit se utilizeaza -......J

operatorul -c) ;

Alloe - tipul obiectului utilizat pentru alocarca memorlei pentru elementelecontaincrului ; implicit acesta esrc allocat:or<T>.

Page 105: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

Exemple

set<int> c;

Constructorii si destructorul

class Cornplnt{public:heel operator(} (censt int& x, canst int& y){ return x%10<y%10;

} ;

209CONTAlNERE ASOCIATIVE

T'.1serare

FunCfiile membre care modificii containerul

Accesori

Containerele set/mul tiset contin functiile membre begin (), end () ,rbegin ( ), rend () care returneaza iteratori cu semnificatia uzuala. [ncepand cuC+ + 11, sunt definite ~i functiile cbegin (), cend (), crbegin (), crend { ) ,care returneaza~const i terator. Reamintim ca elernentele acesior containere suntconstante (nu pot fi ll1odificate),' deci neraroni indica elemente coustantc.

De asemenea, retineti ca elcmentele cot1tainerelor set./mul tiset sunt ordonate(conform criteriului de sorrare specificat la dec1ararc). Prin urmare, primul elemental containerului este primul conform ordinii specificate ("cel mai mic"). iar ultimulelement este ultimul conform ordinii specificate ("eel mal mare"). ..

Vom declara $i vorn popula un vector a de numerc de tip int:

vector<int> a;a. push__back (12) ; a. push__back (102) ; a. push_back (56) ;a_push_back(213) ;a.push_back(2121 ;a.push_back(14);

a.push_back(151 ;a.push_back(56};

Vecrorul a contine acum valorile 12, 102, 56, 213, 212, 14, 15, 56.Vom crea doua multimi utilizand cOllstructorul bazat pe un domeniu :

.15et<int> cl (a.begin{), a.end(»);.' set<int, Comp Lnt.> c2{a.begin{) I a.end());

in cl vor fi plasate elementele distincte din vectorul a, 'in ordine crescatoare,considerimd ordinea definita de operatorul -c : 12 14 15 56 102 212 ,213. incz vor fi plasate elementele din vectorul a, elemcnte distincte luand in considerareultima cifra, in ordinea crcscatoarc descrisa de compInt: 12 213 14 15 56.

! multiset<int, Complnt> c3 (a.begin(), a v errd L) ,;

In c3 sunt plasate toate elementele din vectorul a, in ordine crcscatoare. luand in

considerare doar ultima cifra : 12 102 212 213 14 15 56 56.

Functiile membre referitoare la dimensiunea containeruluiPentru c1asele set/multi.set sunt definite funqiile empty (), size () ~i

max_size () , cu semnificatia uzuala.

II1 ~ pair<i terator I bool> insert (canst value_type& val! ;

I I " ' If' "! nsereaza un element cu vaJoarea val. Pentru contalneru set unc!Ia returneazai. 0 pereche de valori. prima valoare din pereche (firsc) fiind un iiCralOr care indica

I, elementul nOll inseraf (sau pozitia celui cchivalent .Cll acesta existent III set); a doua

valoare din pereche (second) este true daca inserarca s-a re.aIizat cu succcs,I respectiv false dad inserarea 11U a fast efectuata deoarece 0 valoare cchivalenta

I,

TPROGRAMAREAIN .LIMBAJUL CIC++ PENTRU LlCEU208

Pentru clasele set /mul tiset sunt definiti constructorul implicit (care creeazaun container vid), constructorul bazat pe un domeniu (care creeaza un container illcare copiaza elementele dintr-un domeniu spccificat), constructorul de copiere ~i

destructorul , care distruge obiectul, elibcrand memoria alocata dinamic. Incepand cuC+ + 11, sunt definiti constructorul de initializare (care creeaza un container in careplaseaza elementele specificate tntr-o lista de initial izare) si constructorul de mutarc(care creeaza un container in care muta elementele dintr-un container specificat).

Declaratia este stmllara ~i pentru multiset.Criteriul de sortare specificat trebuie sa fie antisimerric (daca Compare {x , Yl

este true, atunci Compare (y I x} este false), tranzitiv (dad Compare (x, y)

este true si Compare (y, z) este true, atunci Compare (x , z) este true) ~i

ireflexiv (Compare (x, x) este false). Acelasl criteriu de sortare este utilizat ~i

pentru a verifica daca elementele sunt distincte (x §i y sunr considerate cgale dacaatat Compare (x , y) , cat si Compare (y I x ) au valoarea false).

Clasele set $i mul tiset nu permit modificarea elementelor stocate incontainer, insa permit inserarea unui element si extragerea unui element.

Iteratorii containerelor set/mul tiset sunt bidirecuonali.Desi standardul STL nu specifica explicit acest lucru, elementele containerelor

set/mul tiset sunt organizate intern ca un arbore binar de cautare echilibrat (maiexact, un arbore rosu-si-negru). Acest lucru permite ca operatiile de cautare, inseraresi extragere sa se realizeze in timp logaritmic.

Creeaza 0 multirne (set) denumita C cu 0 clemente de tip into Ordinea.:!ementelor este cea implicita, defiuita de operatorul -c.

I, string s (vmarna" ) ;~ set<char> d (s _begin () I S. end () ); ..

Creeaza un container de tip set in care plaseaza caracterele distincte din §irul s,ordinea caracterelor fiind cea impIiciUi «). Continutul comail1erului s este am.

f multiset<char> d(s.begin(), s.end(»;

Creeaza un container de tip mul tiset in care plaseaza toate caracterele din $irul 5,

ordinea caracterelor fiind cea implicita «). Continutul containerului ms este aamm.Sa consideram c1asa CompInt, care permite compararea a doi intregi considerand

doar ultima cifra :r

r-'

rI

,-

r-r-

.~

r-'

Page 106: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

--'

--'

--'

J

_.

, !

-1

w

'--"

u

-211CONTAINERE ASOCIATIVE

Operatiile de cdutare

iterator find (const value__ cype& val) const;

Exemplu

Yom deflni uns et; si un multiset pe carele initializam eu caracterele dintr-un sir :

string Sir t ' abr-acadeb.ra" ) ;set<char> s(Sir.begin(), Sir.end()) j

multiset<char> ms(Sir.begin(}, Sir.end()}

Putem parcurge multirnea s ~i multimulrimea ms , afisand caracterele:

set<char>: :iterator s_it;multiset<char>:: iterator ros_itjfor (s_it:::s.begin() s it!=s.end() ++s it)

cout«*s_itjoout c c tVn ' ;for (ms_it=ms.begin() ms it!=ms.end(}: ++ms_itl

caut«*rns_it;oou t.c ' vn ' ;

Cauta in set/multiset valoarea val ~j rerumeaza un itcrator care indica 0

:pozitie pe care se afla aceasta valoare. Daca valoarea val nu a fost gasita, functiareturneaza iteratorul end ( ) .

l size_type count (const value_type& val) const;

Returneaza numarul de elemente din container echivalente (din perspectivacriteriului de sortare) cu valoarea val. Pentru set, aceasta functie poate returnadoar 0 sau 1, deoarece valorile sunt distincte. '

i iterator lower_bound (const value_type& val) const;

Retumeaza un iterator care indica pozitia primului element din container care nuil precede pe val (acest element contine 0 valoare echivalenta eu val sau mai maredecat val, considerand criteriul de sortare specificat la declarare). Daca toateelementele din container preceda valoarea val, atunci functia returneaza iteratorulend( ).

!"iterator upper_bound (const value_type& val) constj

Retumeaza un iteratbr care indica pozitia primului element din container care itsucceda pe val (acest element contine 0 valoare mai mare dedit val, considerand

.criteriul de sortare specificat Ja declarare). Daca un astfel de element nu exista,atunci functia returneaza iteratorul end") .

pair<iterator,iterator> equal_range(const value_type& val) canstj

Functia rerurneaza 0 pereche de iteratori. Prunul iterator din pereche (first)este lower_bound () . iar al doilea iterator (second) este upper_bou:rl:.r? () .

~~'T'~", ~.

I-I1val) ;const value..~ t.ype&(it.eratar paz,

PROGRAMAREA IN UMBAJUL C/C+-I PENTRlJ LICEU

iterat.or insert

210

exista deja in container. In cazuJ in care containerul este de tip muLt.d s e t , inserareilse realizeaza Intotdeauna, prin unnare functia nu rcrurncaza () pcreche de valorj cidear iteratorul care indica pozitia elcmcntuluinou inserat.

Insereaza un element cu valoarea val, .incepand cautarca pczipel de inserare ell

pozitia indicata de iteratorul paz. Pozijia paz reprezinta dear a indicatie pcntrufunctia insert, ca pozitie de inceput a cautarii, si daca pozitia pe care trebuieinserata valoarea val este dupe paz, atunci inserarea este oprimizata.

template <class Inputlterator>void insert (Inputlterator prim, Inputlteratar ultim) ;

Insereaza in containerul set/multiset elementeJe din domeniul [prim, ultim).

template <class ... Args>pair<iterator,bool> emplace (Args&& ... p);

Disponibila din C++ 11, functia empl ace () creeaza si apoi insereaza un elementin container.

void swap (set& x) ;void swap (multiset& x);

Functie menibra care interschimba containerul curent cu contalnerul x rransmls caparametru.

Elirnina din set/mul tiset toate elemeutelc din domeniuJ [prim, ul tim) .

void clear();

Elimlna toate elemenrele din container.

• Interschimbare

template <class ... Args>iteratar emplace_hint(const~iteratorpoz, Args&& ... p)j

Dispcnibila din C+ + 11, functia emplace_hint () crecaza si apoi insereaza unelement In container, cautarea pozitiei de inserare incepand cu pozitia indicata deiteratorul po z.

• Extragere

·~·void erase (iterator poz) j

Extrage din set/multiset elcmentul indicat de iteratorul poz.

size_type erase (const value_type& val);.",--.

Cauta in set/multiset valoarea val si extrage din set/mul tiset toateelementele care au aceasta valoare. Functia returneaza numarul de elemente eliminate(pentru containerul set 1 sau 0, dupa cum valoarea a fost sau nil gasita).

void erase (iterator prim, iterator ultim) j

Page 107: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

Pe ecran se va afisa :

Daca executam aceeasi secventa pentru caracterul p (care nu apare in sir), objinem :

Aplicatia 1. Sea

rrrr

213CONTAINERE ASQCIATIVE

sea.in sea. out Explicatii

5 1 Vaporul I ramane pc mare

4 1 1 Vaporul2 ramane pc mare §i distrugc vaporul 1

8 6 -1 Vaporul 3 esre distrus de vaporuJ 27 5 -1 Vaporul 4 estc distrus de vaporul 2

3 4 2 Vaporul 5 ramane pc mare, impreuna cu vaporul 29 3

Exemple

Pregatirea lotului national de informatica 2004

Date de iesire

Fisierul de iesire sea. out va conrinc N linii. Pe Iinia i se va scrie -1 dacavaporlll i estc distrus in momentul aparitiei sau un numar tnrreg strict poz.itivreprezentand numarul de vapoare de pe mare dupa aparitia vaporului i in cazcontrar.

Restrictii

1 ,; N ~ 200000Coordonatele sunt numere intregi strict pozitive mai mid sau egalc ell 260000Nu vor exista doua vase cu aceeasi coordonata x sau eu aceeasi coordonata y.

Soliqie

Un vas va fi reprezenrat prin percchea coordonate1or sale (x,y). Multimea vaseloro vom reprezenta ca un s ec . Perechilc vor f ordonate implicit strict crescator dupacoordonata x (abscisa). Cum nu exista doua vase .Cll aceeasi abscisa, la ordonarecoordonata y nu conteaza,

~ set< pair<int, int> > Vase;

Cand citim un vas (X-t Y ) , cautamtn set prlmul vas (xl,yl) pcntru care x L>x(acesta se obtine iu timp Ioganuuic cu functia 1..1-pper_bound ( i ).

Daca un astfel de vas exista §i ordonata sa yl>y, atunci acest vas va distrugcvasu1 (x, y) §i afisam -1. Sa obscrvam ca este sufident sa facem comparana cu(xl, yl) =upper_bound () . Dad! am presupune prin reducere 1a absurd ca existaun alt vas (x2, y2) cu x2>xl>x si y2>y>yl, atunci vasul (x2, y2) ar fi trebuit sadistruga vasul (xl, yl) , dec! acesta ar fl fost eliminat din set la un pas anterior.

Sa analizam acum ce se inrampla daca (x I y) nu cste distrus de un alt vasexistent in set. in acest caz, va trebui sa eliminam din set toate vaseIe pe carevasu1 rx . y) Ie distruge. Vom parcurge multimca in sens invers, incepand de 13upper_.bound () spre inceput (aid sunt vase1e (xl, yl) cu xl<x) ~i Ie vom ~terge

(ell functia erase ()) pe cele pentru care yl<y.$i aid trebuie sa mai facem 0 observatie: dind intillnim un vas (xl, y1) pentru

,care x1<x ~i yl>y, .nu are Tost sa-continua-m parcurgerea, ne oprim, deoareceinaintea acestul ·vas· nu mal 'pot- exista---vase care ar putea fi -distruse de (x, y)

PROGRAMAREA IN LIMBAJUL CIC++ PENTRU LICEU

Pe ecran se va aflsa :

212

Pe mare va avea loc 0 importanta batalie tnrre N vapoare. Vapoarele sun!considerate niste puncte si sunt date prin coordonatele ]01" carteziene x si y. Dinmotive greu de inteles, vapoarele nu pot ataca dedit vapoarele care se afla la stanga~i mai jos (rnai exact, un vapor la pozitia xl, yl poate ataca alt vapor Ja pozitiax2, y2 daca ~i numai daca xl>x2 lji y1>y2). Pentru ca aceasta baralie are lac inzona Triunghiului Bermudelor, vapoarele apar (se teleporteaza) pe rand in zonabataliei. Vapoarele sunt numerotate 1, 2, ... , N in ordinea aparitiei lor. in momemuJin care un vas apare, daca exista alt vas care a aparut deja ~i care poate sa 11 atace peeel nou, vasul nou este distrus instantaneu. Daca nu, vasul eel nou ramane pe mare ~i

distrugeioate vasele pe care Ie poate ataca.

Cerinja

Dandu-se coordonatele la care apar pe rand -vapoarelc, sa se afle pentru fiecarevapor daca este distrus sau nu in mornentul aparitiei sale, si daca nu este distrus, sase precizeze numarul total de vapoart;: ramase pe mare dupa eparitia sa.

Date de intrare

Pe prima linie a fisierului de intrarc sea. in Sf; afla uumarul natural N repre­zentand numarul de vapoarc ee vor aparea pc mare. Pc tiecarc dintre urmatoarele Nlinii sunt descrise in ordine pozitii1e vapoarelor. Mai exact pc cca de a i-a liniedintre cdc N se afla doua numerc intregi separate prin spatiu reprezentandcoordonatele x _yale vaP9rului i (l~i~N).

bbcc

abcdraaaaabbcdrr

Putem determina lower_bound () ~i upper_bound () pentru caracterul b inambele conrainere :

s_i t=s .lower_bo~nd( 'b ' ) i ms_i t e s . lower_bound ( I b' )cout«*s_it«*ms_it«'\n'is_it=s.upper_bound('b')j ms_it=s.upper_bound('b'lcout«*s_it«*ms_it«'\n'i

~

r-i

-

:-

,....

, ,

r

,....

, ,

Page 108: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

r ~

c..;

214 PROGRAM AREA iN LIMBAJUL CIC++ PENTRU LICEU CONTAIN ERE ASOCIATIVE 215

Mesterul Vasile are 0 firma de microprocesoare. Pe 1 ianuarie el isi planificaactivitatea pentru urmatoarele n zile. Analizand graficul de productie pentru celen zile, Vasile stie ca in ziua i firma sa poate produce eel mult Pi micropro­cesoare, costul de productie al unui microprocesor fiind CPi (l~i~n). Analizandsituatia comenzilor, Vasile stie ca in ziua i el trebuie sa livreze exact nr-,microprocesoare (l~i.:s;:n). Microprocesoarele care nu sunt livrate pot fi trimise Iadepozit pentru a fi utilizate ulterior. in noaptea dintre zilele i §i i+J. pot fi ,depozitate eel. plUlt"d i microprocesoare , costul depozitar ii unui microprocesor 'jfiind cd i (l~i<n). I

set< pair<int,int> > Vase;int main ()

FILE *fin = fopen("sea.in", "r");FILE *fout = .fopen{"sea.out", "w"l;int x, y, n, i;set< pair<int,int> >: :iterator' It, It2, Itl;fscanf(fin, "%d" , &n);for (i=O; i<n; i++)

{

(deoarece ar fi fast distruse de (xl, yl) la un pas anterior). Deducem ca vasele caretrebuie eliminate forrneaza un domeniu (care se terming eu upper_bound () ~i Potfi sterse toate deodata,

Implementarea utilizand tipul set din STL devine foarte simpla $i are complexi_tatea O(N log N).

! #include <cstdio>#include <set>using n~espace std;

rII Competition, 2011~

~

-'

-'

~

-'

w

, i

-

Soliqie

Metoda utilizatil este Greedy.Parcurgem in ordinc ccle n zile. Pe parcurs construim un mul tiset de perechi

(cost, cantitate). La trecerea de la ziua i catre ziua i+l, trebuie adunata latoate elementele din mu.I c Ls e t; .valoanea c dj , in .zma .i. adaugarn Ill. mLJI t.a a c t;

costul de productie CP.i, si extragem din multi set variarua optima de a satura

cererea nr i .

Fisierul de intrare micro. in contine pe prima linie numarul natural n . Peurrnatoarele n linii se afla informatii despre productie §i comenzi. Mai exact, pecea de a i-a linie dintre cele n se ana [rei numere naturale separate prin spatii :Pi CPi n r , (lsi5n). Pe urmatoarele n-J. linii se afla informatii despre depo­zitare. Mai exact, pe linia i dintre cele n-l (15i:::;n-J.) se afla doua numerenaturale separate prin spatiu d i cd i .

Date de iesire

Fisierul de iesire micro. out va contine 0 singura linie pe care va fi scris unsingur numar intreg : suma minima necesara pentru satisfacerea ruturor comen­zilor sau valoarea -1 dad! acest lucru nu este posibil.

Restrictii si precizari

micro. in micro. out Expticatie

3 116 in prima zi pot fi produse maxim 10 microprocesoarc. la 4 lei10 4 1 inicroprocesorul, ~i trebuie sa fie livrat un singur rnicroprocesor ,2 2 6 Cost pernru ziua 1 : 4 lei. Peste noaptc pot f stocate doar 7 micro-11 10 8 procesoare. La costul de 3 lei bucata.7 ~3 A doua zi sunt produsc doua microprocesoare cu 2 lei bucata ~i

3 5 trcbuie sa fie livrate sasc. Yom livra cclc doua rnicroprocesoareprodusc plus 4 din depozir (stocatc din prima zi). Cost pcntru ziua 2 :2*2+(4+3)*4=32.A treia zi pot fi prod use maxim 11 microprocesoare la cosrul de 10 leibucata §i trebuie sa fie ltvrarc 8 microprocesoare. Este prcferabil sa ~livram B procesoare produse in ziua 3 cu 10 lei bucata. adica in total80 lei. Cost total: 4+32 +80= 116.

• 1 ~ n ~ 100000

'. a ~ Pi, CP,b n r , ~ 10 9, pentru lsisn

• a ~ d i , cd, :5, 10 9 , pentru lC::;:i:5,n-l

Exemplu

Cerintd

, Scrieti un program care sa determine care este suma minima pc care mesterul1- Vasile trebuie sa 0 cheltuiasca pentru productie si depozitare astfel lncat sa1 satisfaca toate comenzile pemru cele n zile.

t -: de inn"are'

fscanf (fin, "%d %d"" &x, &y) i

It = Vase. upper_bound (make-pair (x, Y)) i

if (It != Vase.end() && It->second > Y){ fprintf(fout, "-l\n"); continue; )

if {! Vase. empty ( ) 1{for (I.tl=It2=It, --Itl;

It2!=Vase.begin() && Itl->second < y;It2 = Itl, --Itl);

Vase.erase(It2, It);)

Vase. insert (make-pair (x . y}) ;fprintf{fout, "%d\n", Vase.size());

}

f c Lose t Eou t j ;

return 0;

Aplicatia 2. Micro

I

Page 109: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

"16 PROGR,\MAREA iN UMBAJUL C/C ++ PENTRU LICEU CONTAINERE ASOCIATIVE 2]7

r-'

r-r-

I'

l J

r-t

r

ri

r

De asernenea, trebuie sa luarn in considerare si restrictiile de depozitare: pentru anu depasi d i , extragem din multiset cele mai costisitoare elemente.

ProgramuI cornplet arata astfcl :

#include <cstdio>#include <vector>#include <set>#define NYiliX 100000#define ,~ 1000000000#define PII pair<2ong long, int>ifdefine mp make-pairusing namespace std;

int main (){freopen("micro.in". "rt" , stdin) i

freopen("micro.out", "wt", stdout);int 11, i;scanf ("%d", &n) i

vector<int> pin), cp(n), nr(n), din), cd(n);for (i=O; i<11; i++)

scanf("%d %d %d", &p[iJ, &cp[i], &nr[i);for (i=O; i<n-1; i++)

scanf("%d !I>d", &d[i), &cd[iJ);

multiset<PII > q;

long long costdep = 0, total = 0, rez = 0;for (i=O; i<n; i++) Ilpareurg in ordine eele n zile

{q.insert(mp(cp[i.]-costdep, p[i]));I ladaug microproc.esoarele produee in ziua itotal += p[i];Illivrez eele nr[iJ microprocesoare necesarewhile (!q.empty{) && nr[iJ > 0)

(

Ilpareurg multisetul qmultiset<PII >: :iterator it = q.begin{);PII source = *it;int cate = min (nr [iJ, source. second);Ilvoi livra cate rnicroprocesoaresource. second -= cate;nr[iJ -= cate;rez += cate * (costdep + source.first);Iladun costul microprocesoarelor livrate

q.erase{it) ;

if (source.second > 0) q.insert(source)itotal -::: c;ate;

,

if (nr[iJ > 0) Ilproblema nu are solutie{rez = -1; break; }

//adun costurile de depozitareif (i != n-1)

{costdep += cd[i];Ilextrag din depozit elemente cat timp depasescllcapacitatea de depozitarewhile (total> ali])

{multiset<PII >: :iterator it = q.end();--it;

PII last = *it;q. erase (i t) ;long long cate = total-drilltotal -= last.second;if (last.sec0nd > cate)

(last.second -= int(cate)iq.insert(last) i

total += last.second;

}

printf{"%lld\rl",rez)return OJ

Aplicatia 3. Egal

Toata lumca tl sne pe TractoMarm, cel care numara noduri din arbor i mai repededecat isi numara altii degctelc de la maiui. Zilele trecute , TractoMarm s-a gandit sase "joace" eu N seifuri. Cele N seifuri sum dispuse sub forma unui arbore (grafconex aciclic). Consideram varful 1 ea radacina 'a arborelui. Fiecare seif are asociatao cheie cu care seiful poate fi deschis. Din pacate (sau din fer icire), pot exista douasa~,mai multe seifuri care pot fi deschise eu acecasi cheie.

Ceriruii

Scricti un program care, pentru fiecare seif x, determina care este cheia caredeschide eele mai multe seifuri din subarborele eu radacina in x.

Date de intrare

Fisierul de intrare egal. in conpnc pe prima linie numarul natural N, rcpre­zentand numarul de seifuri. Pe urmatoarelc N-l linii se gasesc catc doua numere xy, semnificand ca exista muchie In arbore intre seiful x §i seiful y. Pe ultima linie seafla N numere naturale, al i-lea numar reprezentand chela care deschidcseifuli.

Page 110: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

~

--'

~

219CONTAINERE ASOCIATIVE

void afisare();

int main (){citire() ;

DFS Ill;afisare () ;return 0;

Mix] [c[x) ]+";maxim=O;for (it=M[x] .begin(); itl=M[x] . end () i ++it}

if (it->second>maxim){maxim=it-,>second; chmax=it->first;

cmax[x]=chmax; nr[x]=maxim;}

void DFS(int x){int i, maxim, chmax;viz [x] =true;for (i=O; i<G [x] _size (); ++i)

{if l!viz[G[x][iJ]){DFSIG[x] [iJ);for lit =M IG Ix][ i] ] . begin I ) ;

it!=M[G[x] [i] ] .end{); ++it)M [x] [i t->first) +=i t-c-s econd.

M [G Ix] Ii] ] . clear I ) ;}

void ci tire (){FILE * fin=fopen("egal.in", "r"};int t . X, y;fscanf {fin, "%d", &N};for {i=O; i<N-l; i++}

( fscanf(fin, "%d %d", &x, &y);

G[x] .push_backlY); G[y) . push_back Ix) ;)

for (i=l; i<=N; i++) fscanf(fin, "%d" , &c[i]);

void afisare ()(

FILE * fout=fopen("egal.out", "w");int x;for (x=l; x<=Nj x++)

fprj,n~f(fout, "%d %d\n", cma~[xl, nrr~])

f c-Lo s eI f du t )

}

1-·------"=

Ii

egal.in egal.out:.

7 1 31 2 3 11 3 2 33 4 2 13 5 1 25 6 1 15 7 1 11 3 2 2 2 1 1

PROGRAMAREA iN LIMBAJUL c/c-r-r pENTRU LICEli

Date de iesire

218

Algoritmiada 2011

in fisierul de iesire egal . o u t vetl afisa N linii. Linia i va contine doua numerenaturale separate prin spatiu, reprezentand cheia care deschide cele mai multe seifuriin subarborele ell radacina i si de care ori apare aceasta in subarbore.

Restrictii

• 1 ~ N s 100 000

• In cazul in care exista mai multe chei ell acelasi numar maxim de aparitu se vaafisa eea minima;

• Memoria disponibila pentru stiva este de maxim 8 MB ]

Exemplu

Soltqie

Pentru fiecare nod x din arbore construim un container de tip map M, undeM [ c J =nr, daca in subarborele cu radacina x cheia c apare de nr ori, Pentruaceasta, vom parcurge arborele DFS incepand ell varful 1. Dupa ce toti fiii varfului xau fast procesati. putem construi ~i containerul map pentru varful x, unificandcontainerele map asociate fiilor. E posibil sa depasim memoria disponibila. prinurmare. dupil ce unificam comainerele fiilor, Ie putem goli. Dar pentru aeeasta, la

--- fiecare nod cc, dupa ce am calculat containerul map corespunzator. dererminam siretinem chela ell nuruar maxim de aparitii,

#include <cstdio>#include <vector>#include <map>#define NMAX 100001using narnespace stdjint Njvector<int> G[NMAX];map<int, int> M[~~]

int c[NMAX] , cmax[NMAxJ, nr[NVillX];vector<boo1> viz(NMAX , false);map<int, int>: :iterator it;

void citire(};void Dr'S (int) ;

: 1

Page 111: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

220 PROGRAMAREA iN LIMBAJUL cic:--. PENTRU LICEU

7.2. Containerele asociative sortate map §Oi mul timap

CONTAIN ERE ASOCIATIVE

Constructorii si destructorul

221

, ,

r-ti

r-r-

r-

~

r

II ,

~, ,

·'r-­I

\ :

Containerul map stocheaza clemente constituite dinrr-o cornblnape fermata dintr-ocheie ~i 0 valoare asociata cheii. Elementele sunt identificate in mod unic prinintermediul cheii (ell alte cuvinte eheile sunt distincte) si sunt ordonate crescator dupacheie, conform unui criteriu de sortare specificat.

Conrainerul rrtuLr.Lmap este asemanator, diferenta constand in faptul di cheile nusunt neaparar distincte, pot exista mai multe elemente cu aceeasi cheie.

Pentru a utiliza aceste clasc trebuie sa includem fisierul antet map:

#include <map>

Declaratia clasei map:

template < class Key,class T,class Compare ~ less<Key>,class Alloe = allocator<pair<const Key,T> >> class map;

Clasa sablon map are patru tipuri specificate ea parametri :

Key - tipul cheii ;T - tipul valortlor ;

- Compare ~ criteriul utilizat pcntru compararca cheilor (implicit se utilizcazaoperatorul <); crireriul de sortare este un predicat binar care primcste ca para­metri doua chei (sa spunem cl, c2) si returneaza true dac5. cl prcceda conformcrireriului de sortare pe c2 ;Alloe - tipul obiecrului utilizat pentru alocarea memoriei pentru elernentelecontainerului ; implicit acesta estc al1ocator<pair<const Key, T>.

Declaratia este-similara $i pentru muLt.Lma'p.

in eazul claselor map/mul timap este definit tipul value_type reprczentandtipul elemeutelor din container, ca pereche cheie-valoare astfcl :

~ typedef pe i r-e.con.se Key, 'r> value__type;

Clasele map si rnuLtimap nu permit modificarea dirccta a cheilor elementelorstocate In container, tara a afeeta integrltatca structurii. Daca este necesara modi­fiearea chcii, extragen din strucrura elemcntul eu chela veche ;:;i inserati un elementeli 110ua cheie.

lteratorii containerelor me.pzmuLtimap sunt bidirectionali.Desi standardul STL nu specifidi explicit acest lucru, elementele comainerelor

map/multimap sunt organizate intern ca un arhore binar de diutare echilibrat.Acest lucru permite ca operatiile de cautare, inserare ~i extragerc sa se realizeze intimp.l?garitTlJic., .._" _.~: . >c

Pentru c1asele rna.p ZrrruLtimap sunt definiti constructorul implicit (creeaza uncontainer vid), constructorul bazat pc un domeniu (creeaza un container in carecopiaza elementele dintr-un domeniu specifieat), constructorul de copiere ~i dcsrruc­rorul, care distruge obiectul, elibcrand memoria alocata dinamic. lncepand ell C++ 11,sunt definiji constructorul de initializare (creeaza un container tn care plaseaza elemen­tele specificate intr-o lista de initializare) ~i constructorul de mutare (creeaza uncontainer in care muta elementele dintr-un container specificat).

Exemple

~.map<string,int> C;

Creeaza un container de tip map in care cheile sum de tip string, iar .valortleasociare cheilor sunt de tip into Elementele sunt stocate in ordinea lexicografica acheilor.

t map<int,string,CompInt> c2;

Creeaza un container de tip map in care cheile sunt de tip int.. iar valorile.asociate cheilor sunt de tip string. Elementele sunt stocate in ordinea cheilordeflnita de clasa CompInt, care permite compararea a doi intregi in functie deultima citra (deflntta in sectiunea precedenta).

Functiile membre referitoare la dimensiunea coruainerului

Pentru clasele ma'p ZrnuLtimap sunt definite functiile empty ( ), si ze () simax_size () , eu semnificatia uzuala.

, Accesori

Containerele map/mul timap contin functiile membre begin (), end ( ) ,rbegin (), rend () care returneaza ireratori eu semnificatia uzuala. [ucepand euC+ + 11, sunt definite si functiilc ebegin ( ), cend ( ), erbegin ( ), crend ( ) ,care returneaza cons t.jd t exa t or . Rearnintim ca elernentele containerclor map/muLtimap sunt ordonate dupa chei (conform criteriului de sortare specificat ladec1arare). Prin urmare, primul element al containerului esre primul conform ordiniispecificate ("cel cu chela cea mai mica"), iar ultimul element este ultimul conformordirrii specificate (.,cel cu chela cca mai mare").

Functiile rnembre care modifica COnlainerul

• lnserare _ .Comainerele map/mul tirnap au supraindircate funqii ni."eni.bre pentru inserare,

ell acela~i format ca 1a clasele set /mul tiset, pentru inserarea unui sillgur element.

Page 112: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

222 PRQGRAMAREA iN LlMBAJUL C/C ++ PENTRU UCEUCONTATNERE ASQCIATIVE 223

Exemplull

Opera/We de cautare

Operatorul de indexare

Vom construi un container de tip map in care eheiJe sunt denumiri ale luniloranului, iar valoarea asociata este un nUIl1ar intreg reprezentiil1d numarul de zile dinluna respectiva :

I: map <string, int> cl i

:, map <string,int>: :iterator it;

; ~

~

..J

-'

: 1

-'

~

cl["ianuarie"]=31ic1["februarie"]=2 8ic1["aprilie"]:::::30;c1["mai"J=31;for (it=c1,begin(); it!=cl.end(); ++it)

cout«it->first«' '«it->seeond«'\n'i

Exemplul2

Vom constru! acelasi container prin inserari succesive, eu functia insert ()

map <string,int> c2;map <string,int>::iterator it2;cz .insert (make-pair ( "ianuarie" , 31) ) ;c2 . insert (make-pair ( "februarie ",28) )e2 . insert (make-pair ( -me i II , 31) ) ;c2 . insert (make-pair ( "aprilie" ,31) ) ;c2 . insert (make-pair (" februarie" , 29) ) ;for (it2=c2.begin(); it2!=c2.end(); ++it2l

cou t c-ec t2->first«" «i t2->second« ' \n ';

Executand aceasra secventa veti observa ea-pentru luna "februarie" se afiseazil28 (deoarece chela "f e'bz-ue r Le" exisra deja in container, nu a mai fast inserata 0

data, intrucat in map chelle sunt distincte).Daca veti inlocui In declaratii map ell rnuLtimap, dupa executarea secventei de

instructiuni , obtineti pe ecran :

aprilie 31februarie 28februarie 29ianuarie 31mai 31

Acest Iucru se inrampJa deoareee intT-un container de tip mul timap putem insera

de mai multe 'ori aeeea§i cheie-,

Dupa execuna acestei secvenje de instructiuni pe eeran va fi afisat :

aprilie 30februarie 28ianuarie 31mai 31

Observati ca lunile au fost afisate in ordinea lexicograflca a denumirii. Operatorulde indexare a inserat cheile in containerul el, iar prin atribuire am setar valoareaasociara cheii. Sa analizam si efectul urmatcarei atribuiri :

r cl [" februarie" ] ~29;

Daca veji aflsa din nou continutul containerului c 1. veri observa ca luna februarienu a fost din nou inserata in container, ci doar S-3 rnodiflcat valoarea asociata,

!

I

de cautare ca la set/mul tiset sunt definite si pentru c1aselefind ( ), count ( ), upper_bound ( ), lower_bound ( ) ,

in cazul claseJor map/mul timap, cllutarea se realtzeaza, evi-

Aceleasi functiimap/multimap:equal_range () .dent, dupa cheie.

Un element specific conrainerului map consta in faptul caoperarorul de indexareeste supraincarcat. Acest operator permite referirea directa la 0 valoare dintr-uncontainer de tip map prin intermedlul cheii asociate.

Fie C un container de tip map. Constructia C [k] reprczmta 0 refcrtnta la valoarea ,asociata cheii k (daca 0 astfel de cheic exista in containerul c). Daca in containerul Cnu exists cheia k, atunci se insereaza in C eheia k §i este rcruruata 0 refermta lavaloarea asociata eheii k. Datorita operatici de caurarc efectuate , execujia aeestuioperator necesita timp logarirmic.

lncepand eu C+ + 11, este definita si functia membra at (), care funcnoneaza inmod similar (prirneste ca parametru 0 cheie §i rerurneaza valoarea asociata cheii).Diferenja eonsra in faptul ca in cazuI in care cheia nu exisra in container, functiaat () "aTUnea" exeeptia out_of_range.

inserarea unui element, indicand 0 pozitie de lncepur a cautarn pozitier de inserare,rcspcctiv inserarea -unui domeniu. Incepand cu C+ + 11, sunt disponibile si inserareaell mutare, inserarea unor elemente dintr-oHsta de initializare, precum -5i funcjiileemplace () ~i emplace_hint () care creeaza §i insereaza un cjemcnt.

• Extragerein clasele map/mul timap este supraincarcata funcpa erase () In mod similar

cu clasele set/multiset:, srergerea unui element a carui pozitie este specificataprintr-un iterator, srergerea elernentelor dintr-un domeniu specificat §i respectivstergerea unui element specificar prin cheia sa (In mul timap vor fi sterse toateelemenrele ell cheia respectiva). Exista de asemenea functia membra clear () caresterge toate elernentele din container.

• InterschimbareFunctia membra swap () interschirnba containcrul curenr cu containerul transmis

ca parametru ,

Page 113: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

214 PROGRAMAREA,iN LlMBNUL CIC++ PENTRU LICEU CONTAINERE ASOCIATJVE 215

i •

De exemp1u:

Pisierul de intrare bacan. in contine pe prima linie numarul natural n, reprezen­tand numarul de vanzari efectuate in ziua respectiva. Urmeaza n linii, pe fiecare liniefiind descrisa 0 sing~r3 vanzare , sub fonna dinenunt.

Date de iesire

Pislerul de iesire bacan. out va contine pe prima linie numarul natural preprezentand numarul de produse distincte vandute in ziua rcspecrfva. Pe urmatoarclep linii sunt descrise produsele vandute, sub forma speclficata in enun] ,

Restrictii si precizari

• 1 -on-o 100000• 1 -0 Nurnarul de produse vanduter; 1000• Numele unui produs contine maxim 20 de caractere (litere mari, litere mici §i

spatii). Evident, un Burne nu incepe Si nu se termina cu spatiu.• La 0 vanzare cantitatea nu depaseste 100 de unitati,

Date de intrare

Cascaval * 2Bere Tuborg * 6Varza * 1Bere Tuhorg * 2Cascaval * 3

in situatia vanzarilor , produsele trebuie sa apara in ordine alfabetica. cate unprodus pe 0 linie. Pe linia corespunzatoare unui produs este scris numele acestuiaurmat de * si apoi de cantitatea totals vauduta din produsul respectiv. Caracterul *trebuie sa fie precedar ~i urmat de cate un singur spatiu.

De exemplu, pentru lista de vanzari precedenta situatia vanzarilor arata astfe1 :

Bere Tuborg * 8Cascaval * 5Varza * 1

Fiindca !}i eu sunt un tip de treaba Si nu e mare 1ucru sa-i fac un program care sagenereze situatia vanzarilor , as vrea sa fac acest Iucru , dar ... niciodata nu am timp.

Cerirud

Scrieti un program care sa citeasca Iista vanzarilor dintr-o zi si care sa generezesiruatia vanzarilor.

'I Cantitatea este exprimata intotdeauna in unitatea de masura specifica produsu1ui.I Nurnele produsuJui este separat de cantitate prin caracteru1 * (asterisc) precedat si!urmet de care un singur spatiu .

IIII

Executand aceasta secventa de instructiuni, obtinem pe ecran :

aprilie 30februarie 29ianuarie 31mai 31

Aplicatia 4. Bacon

Exemplul3

Daca ill containerul cl din primul exemplu am insera cheia Februarie, amobserva ca aceasta chele se insereaza, deoarece comparatla cheilor se realizeazafacand diferenta intre majuscule si minuscule. Pentru a evira 0 astfel de situatie , YOmdefini 110i un criteriu de comparare (Comp S) care compara sirurile, facand abstractiede diferenta dintre majuscule si minuscule:

class CampS{public:beel operator () {censt st:r·ing& x , censt string& y)

{char cx[x.size()+l], cy[y.size()+lJ;strcpy(cx,x.c~str(}); strcpy(cy,y.c_str{)};strlwr(cx); strlwr(cy);return strcmp(cx,cy)<O;

map <string,int, CampS> c3;map <string,int, CampS>: :iterator it3;c3 l " ianuarie"] =31;c3["februarie"J=28;c3 ["aprilie"] =30;c3 ["mai"] =31;c3 ["Februarie" J =29;fer (it3=c3.begin(); it3!=c3.end()·; ++it3)

cout«it3->first«' '«it3->second«'\n';c ou t;«-c' \n' ;,

} ;

Observati ca am transformat sirurile din string in sir ·C, am transformatmajusculele in minuscule (cu functia strlwr O.), apoi am realizat comparareasirurilor transfonnate eu strcmp () . Vom defini acum containerul c3 utilizand acestcriteriu de comparatie. apoi vom insera valori $i vom ohserva ca lunile stocate incontainer sunt distincte :

Bacanul din colt e un tip de treaba. in fiecare seara imi fac cumparaturile 1a el $ide multe ori Il gasesc stand paua tarziu pentru ,.a face casa". Mai exact, el analizeaza1ista vanzarilor din ziua respectiva si totalizeaza aceste vanzari pe produse, obtinandastfel un document denumit situatia vanzanlor.

in -listavanzarilor apare 0 liniepentru ftecarevanzarefacuta sub forma:

nume-produs * cantitate

r,I

r

r

,

,

Page 114: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

'26 r .......:,.:.~"'r... v~11.1'>.D11. ~;~ LINtHAJUL CfC++ PbNTKU LlCEUCONTAINERE ASOCIATIVE 227

Exemplu

bacan.in bacan.out5 3Cascaval * 2 Bere Tuborg * 8Bere Tuborg * 6 Cascaval * 5Varza * 1 Varza . 1

Bere Tuborg • 2Cascaval * 3

.campion 2006

Solutie

Vom citi lista vanzarilor linie eli linie intr-un string. De pe fiecare linieextragem cantitatea §i denumirea produsuhii. Pentru aceasta identificam pozitia paza caracterului separator *, apoi extragem subsirul s 1 care incepe la pozitia 0 si arcpoz-l caractere (acesta este denumirea), respectiv subsirul care incepe la pozitiapoz+2 si tine pana la sfarsitul sirulul (aceasta este cantitatea). Convertim sirul carecontine cantitatea intr-un numar intreg x.

Vom construi un container de tip map V in care cheile sunt denumirile produselor,iar cantitatile sunt valorile asociate.

~ map <string, int> V;

La fiecare linie citita actuallzam cantitatea existenta in containerul V pentru pro­dusuJ respectiv :

V[sl] +=x;

Reamintirn modul de functionare a operatorului de indexare: cheia s 1 este cantatain map; daca ea nu exista este inserata ; V [s 1] reprezinta 0 referinta Ia valoareaasociata acestei chei.

Complexitatea va fi O(N log ND), unde Neste dimensiunea listei de vailzari, iarND dimensiunea situanc! vanzarllor (numarul de produse distincte).

#include <fstream>#include <map>#include <string>#include <cstdlib>using namespace std;

ifstream fin("bacan.in");ofstream fout tvbec an . out") ;

map <string,int> V;

int main ()

I'! {int n , i • paz,'-x;: string s, sl;! fin»n; fin. get () ;

for (i=O; i<n; i++)(

getline(fin, s);poz=s . find ( , * , ) ;sl=s. substr (poz+2) //extrag canti tateax=atoi(sl.data()}; 110 convertesc in intregsl=s.substr(O,poz-l) ;/Iextrag numeleV[sl]+=x; Ilactualizez map

}

fout«V.size()«'\n'map<string,int>::iterator it;for (it=V.begin(); it!=V.end(); ++it}

fout«it->first«u * "«it->second«'\n';fout .close U ;return 0;

Aplicatia 5. RadioLaura a dezvoltat recent 0 pasiune pentru sirurile de caractere generate aleatoriu.

Ca sa ° ajute sa treaca mai usor peste sesiune, prietenii ei s-au gandit sa 0

inveseleasdi si i-au cumparat un astfel de srr de lungime N, continfmd doar litere mid

ale alfabetului englez.De dimineaja, Laura a mceput sa asculte muzica la radio si a auzit M cuvinte,

toate avand aceeasi lungime L, care i-au placut foarte mult. Aceste cuvinte suntformate tot din litere mid ale alfabetului englez. Acum ea ~i-ar dori sa vada, pentrufiecare cuvant, daca acesta apare ca subsecventa in sirul prirnit cadou. Cum cuvintelesunt destul de lungi, Laura nu este sigura ca le-a auzit coreet, dar este convinsa ca nua inteles gresit mai mulr de K litere din fiecare cuvant.

Asadar , voi trebuie sa ti spuncti, pentru fiecare din celcre cuvinte, daca extsta 0

subsecventa de lungime T.J it) _~~rul primit cadou astfel incat cuvantul si subsecven!a sa

difere in cel mult K pozitil. . . "

Date de intrarePe prima linie a fisierului de intrare radio. in se afla patru numere intregi N~ M

L K, avand sernrrificatia din, enunt. Pe urmatoarea linie, se afla N caractereneseparate prin spatii ce reprezinta sirul primit cadou de fata. Pe urrnatoarele M linii,se afla cate L caractere neseparate prin spatii, ce reprezinta cuvintele pc care Laura

le-a auzit la radio (asa cum le-a inteles ea).

Date de iesirePisierul de iesire radio .out va contine M linii. Pe linia 1- (l:S::i~M) yeti afisa 1

daca exists 0 subsecventa in sirul primit cadou de fate care sa difere in eel mult de Kpozitii de al i-.le.:a.C}Jyant din flslcrul de intrare, re~:pectiv 0., in caz contrar.

~

i,

'-"

,

~

1

1u

'-"

: 1

~

Page 115: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

Pregjiurea lotului national de informatica, 2010

Sotujie

Yom analiza succesiv cele M cuvinte. Sa notam eu 8 sirul de lungimc N §i eu Ccuvantul eurent (de lungime L). Yom denumi distanta dimre doua secvente de aceeasllungime numarul de pozitii pentru care earacterele din eele doua secvente sunt diferite.

o prima idee ar fi sa verificam pentru fieeare subsecventa de lungime L a sirului-S daca distauta dintre C si subsecventa respectiva este :;;K. Avand in vedere lungimeasirului S si numarul de cuvinte ce trebuie testate, aceasta abordare este mult preacostisitoare ca timp.

Inceream prin urmare sa reducem numarul de comparatli tntre secvente. Pentruaceasta, vern imparti cuvanrul curent C in K+1 subsccvente de lungime egala cuLg=L! (K+1) (eventualele Iitere ramase la sfarsit le vom ignora). Pentru a reducenumarul de cornparatii tntre secvente, vom compara valorilc hash ale secventelor §i,doar in caz de egalitate a valarilor'·hasli, vomcoinparasecventele, pentru a calculadistants dintre acestea.

Prin urmare vorn caleula valoarea hash pentrn fiecare secventa de lungime Lg dinsirul s. Yom consrrui un container de tip map in care pentru fiecare valoare hashretinem pozitiile de inceput ale secventelor dins care au valoarea hash respectiva.

t map< int, veetor<int> > hash;

Pentru fiecare subsecventa de lungime Lg: din cuvantul eurent C calcularn valoareahash §1 vcrfficam daca aceasta valoare hash apare in contatnerul de tip map hash.Daca C "se potrivcstc" ell 0 subsecventa din s, obligatoriu eel putin una dintre eele K+1subsecvente ale sale trebuie sa se "potriveasca" eu una dintre subsecventele delungime Lg ~le lui s. Daca valoarea hash a unei secvente de lungime Lg din C a fastgasita in containerul hash, atunci parcurgem vectorul asociat aeestei valori hash §iverificam pentru fiecare pozitiedetncepur dinlista dacli secventade lunghhe-L"care IncepcIa pozitia respectiva se "potrive~te" ell cuvanrul curent (in sensul ca distanta este :;;K).

229CONTAINERE ASQCIATIVE

int dist(char *a, char *b, int n)(int sol=O;for lint i=O; i<n; ++i) sol+=a[i] !=b[i];

.. return sol; ..~

Faptul ca sirul initial este geuerat aleator garantcaza ca pentru fiecare valoare hashnu Val' exista multc pozitii de inceput corcspunzatoarc. dec! nu se vor face multecoruparatii Intre secven;e.

#include <estdio>#inelude <map>#inelude <vector>#define NMAX 1000005#define MOD 666013#define LMAX 2505#define BASE 37using namespace std;

}

printf("%d\n", rez);

int N, M, L, K;char S [NMAXJ ;map< int, veetor<int> >·hash;char C[LMA.X];int dist(char *a, char *b, int n);void buildHash(int Lg);boel sePotriveste(int paz);

int main (){freopen("radio.in", "r", stdin);

freopen("radio.out", "w", stdout);vector<int>: :iterator it;int ie, i, j, hashVal, rez;scanf ("%d %d %d %d", &N, &M, &L, &K);

"scanI tv as v • 5);int Lg = L!{K+1};buildHash (Lg) ;for (ic = 0; ic < M; ++ic)

{ scanf ("%s", C);

for (rez=i=O; i+Lg<=L; i~~Lg)

{for (hashVal=j =0; j'<Lg; -++j)hashVal=(hashVai*BASE+(C[i+jJ-'a'})%MOD;

if (hash. find (hashVal) != hash.end())for (it=hash[hashVal] .begin();

it!=hash[hashVal] .end() i++it)rez 1= SePotriveste(*it - i);

1.,,,~

care pe fiecare

radio. in radio.out

10 3 6 2 0

anaaremere 1

roaane 1

aaremerenere

PRQGRA.MAREA iN UMBAJUL C/C++ PENTRULlCEU

Restrictii si precizari

• 1 :s: N :s: 1 000 000• 1 < M :s: 500• 1 :s: K :s: 50• 500 :s: L :s: 2500• Printr-un sir de litere mici generat aleator se intelege un str In

pozttie. oricare diutre Iitere are aceeasi probabilitate de aparitie.

Exemplu

228

,--.

fj

,-

,...

~l

......,!

, j

-.,

.,

~,

Page 116: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

}

bool SePatriveste(int poz){ if (paz < 0 I I paz + L > N) return 0;

return dist(S + poz, C, L) <= K;

void buildHash(int Lg){int hashVal = 0, i, coef=1;for (i=O; i<Lg-l && i<N; ++i)

hashVal=(hashVal * BASE + (S[i] - 'a') % MOD:for (i=l; i<Lg; ++i) coef = coef * BASE % MOD;for (i=Lg-l; i<N; ++i)

{ hashVal = (hashVal*BASE + (S[i]-'a')) % MOD:hash [hashVal] .push_back{i-Lg+l);hashVal = (hashVal - coef*(S[i-Lg+l]-'a'») % MOD;if (hashVal < 0) hashVal += MOD;

230 PROGRAMAREA iN LIMBAJUL C/C++PENTRU LlCEUCONTATNERE ASOCIATTVE

scanf("%s", S);int Lg = LI (K+1)buiIdHash (Lg) ;for (ie = 0; ic < M; ++ie)

{ scanf("%s", C);

for (rez=i=O; i+Lg<=L; i+=Lg){for (hashVal=j=O; j<Lg; ++j)

hashVal=(hashVal*BASE+{C[i+j]-'a'))%MOD;prim=hash.lower_bound(hashVal);ultim=hash.upper_bound(hashVal);for (it=prim; it != ultim; ++it)

rez 1= SePotriveste(it->second - i);}

printf("%d\n", rez);

'31

~

,

'-.!

Putem implementa aceeasi solutie utilizand un mul timap in care inseram fiecarepereche fermata dintr-o valoare hash si pozitla de inceput corespunzatoare,

ji mul timap< int, int > hash;

In acest mod nu mai formam un vector de pozitii de Incepur pentru fiecare valoarehash. In functia buildHash () singura modificare flind rnodul de inserare in container:

void buildHash(int Lg){int hashVal = 0, i, coef=l;for (i = 0; i < Lg-l && i < N; ++i)

hashVal = (hashVal * BASE + (S[i] - 'a'» % MOD;for (i = 1; i < Lg; ++i)

coef = caef * BASE % MOD;for (i = Lg-1; i < N; ++i)

{ hashVal = (hashVal*BASE + (S[i]-'a'») % MOD;hash.insert(make-pair(hashVal,i_Lg+1»;hesfivaI =~ thasbve l - eOEd*(S[i-Lg+l]-'a'») % MOD;if (hashVal < 0) hashVal += MOD;

Cand cautam 0 valoare hash in muLtimap, vom utiliza functiile lower_bound ()si upper~bound () pentru a determina domeniul de aparitie al valorii (in modechiva1ent se putea utiliza funcna equal_range ()). Apoi parcurgem acest domeniusi venflcam secventele pentru fiecare pozitie de inccpur din domeniu. Functiaroain () se rnodifica astfel :

int main (){ freop.en (" radio. in", "r", stdin);

freopen(" r adio.out", "W " , stdout);muLt.dma.p-c Lrrt; , int.;,>.:",:.i.terator it, prim, ultim;

. int ie', i, j,. 'ha~hVai, re~; .'scanf("%d %d %d %d", &N, &M, &L, &K)

! }

7.3. Containerele asociative nesortate

Pentru a utiliza contalnerele asociative nesortate unordered_set Siunordered_roul tiset, trebuie sa inc1udem fisierul antet unordered_set:

~ #include <unordered_set>

In mod similar, pentru unordered_map §i unordered_roul timap, trebuie saincludem fisierul antet unordered_map:

r #include <unordered_map>

in general, toate considerajiile referitoare la containerele asociative sortate ramanvalabile, diferenjele provenind de la organizare interna a containerelor asociativenesortate. Yom mentiona in continuare doar aspectele prin care difera :

1. Elementele dintr-un container asociativ nesortat, evident, nu sunt mentinute rntr-oanumita ordine.

2. Intern, elementele unui container asociativ nesortat sunt organizate sub formaunei tabele de dispersie (tabela hash). Astfel elementele sunt grupate in blocuridenumite buckets, in functie de valo~rea hash calculata pentru cheia elementu1uirespectiv (reamintim ca pentru containerele set Imul tiset cheia ~i valoareacoincid).

3. Datorita modului de organizare sub forma tabelelor de dispersie, accesul la unelement individual a1 containerului este foarte rapid (operatiile fiind mai eficientedecat in cazul containerelor asociative sortate), insa parcurgerea unui domeniu serealizeaza mai pujin eficient.

4. Iteratorii claselor asociative nesortate sunt iteratori de inaintare.

c.:

~

....J

~

, ~

__1

--

Page 117: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

232 PROGRAM AREA iN LIMBAJUL etc ++ PENTRU LlCEU CONTAINERE ASOCIATIVE 233

Constructorii si destructorul

Pentru containerele asociative nesortate sunt supratucarcau constructoru l implicit,constructorul de copiere, de mutare, constructorul bazat pe un domeniu liii construe­torul bazat pe 0 lista de- initial'izare.

Declararea containerelor asocianve nesortate difera de declararea containerelorasociative sortate datorita modului diferit de organizare interne (nu mai estespecificat criteriul de sortare, in schimb trebuie speciflcata functia hash ~i unpredicat care sa permita identificarea egalitatii cheilor).

Deoarece declarajiile containerelor asociative nesortate sum asemanatoare, vornexemplifica doar declaratiile pentru unordered_set ~i unordered_map:

template < class Key,class Hash = hash<Key>,class Pred = equal_tC<Key>,class Allcc = allccator<Key> >

class unordered_set;

Exemple

Functiile membre publice

unordered_set<string> cl;

Creeaza un obiect de tip unordered_set denumit cl CU 0 clemente de tipstring; este utilizat functorul hash () implicit si functorul equal_to pentru corn­pararea cheilor.

~ unordered_set<string> c2 ( {"ana"," ion", "dan"} );

Crecaza un obiect de tip unordered_set denumit c2 initializat cu 3 clementede tip string; este utilizat functorul hash () implicit si funetorul equal_to pentrueompararea eheilor.

~ unordered_set<string> c3 (c2.begin(), c2.end()};

Crceaza un obieet de tip unordered_set denurnit c3 initializat ell elementeledin domeniu! specificat,

Ii unordered_set<string> c4 (c2);

Creeaza obiectul de tip unordered_set denumit c4, copiind elementele din c2.

Containerele asociative nesortate au 0 interfata similara eu containerele asociativesartate. Exista aceleasi functii pentru determinarea dimensiunii ~i aceleasi functii demodifieare a containerului. Datorita faptului ca iteratorii sunt iteratori de inaintare,sunt disponibile numai functiile begin ( ) , end (), cbegin ( ) , cend ( ) . in ceea cepriveste functiile de cautare, sunt disponibile. functiile find ( ), coun t (') ~i

equal_range ( ) .Exista in plus functii referitoare la tabela hasli :

size_type bucket_count() donst noexcept;

Returneaza num~rurde blocuri (liUckets) existe?te in container.

size_type max_bucket_count{) canst noexcept;

Returneaza numarul maxim de blocuri (buckets) ce pot exista in container.

s i.zejr ype bucket_size ( size_type n ) canst;

Rerurneaza numarul de clemente din bloeul cu numarul n din container(n<bucket_count ().

size_type lau clce t; ( const key_type& k ) canst;

Rerurneaza numarul blocuJui din care face parte cheia k.

float load_factor() canst noexcepc;

Rerurneaza factorul de incarcare a contaiuerului (raportul dimre numarul declemente din container sf uumarulde blocuri exisrenre). Factorul de inclircare deter­mini'! probabilitatea de aparitie a coliziunilor in tabela de dispcrsie.

III

i

Declararea containerelor asociative nesortate

••

Parametrii care intervin in declaratie sunt :

Key - tipul cheilor/valorilor stocate in container;Hash - functor unar (sau pointer 1a 0 functie) care primeste ca parametru 0

valoare de acelasi tip cu cheia si rerumcaza valoarea hash calculata pentru cheiarespectiva.; implicit este utiJizat functorul standard hash () (declarat in fisierulantet functional);Pred - predicat binar care primeste ca parametri doua valor! de acelasi tip cucheile si returneaza true daca cele doua chei primite ca parametn suntconsiderate ecbivalente ; implicit este utilizat functorul standard equal_to ( )(declarat in fisierul antet functional), care utilizeaza comparatia eu e e ;

Alloc - defineste modelul de alocare a memoriei; implicit este utilizata clasaallocator.

Declaratia cl~sei unordered_map:

templa~e < class,Key,class T,class Hash = hash<Key>,class Pred = equal_to<Key>,c1ass Alloc = allocator< pair<const KeY,T> > >

class unordered_map;

Observati ca in declaratia clasei uno'rder edjmap intervine inca un tip (T)reprezentand tipul valor-ilor asociate cheilor.

,...,

,...,

: j

,...,

r-t

,...,

. :

Page 118: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

....,..~

234 PROGRAMARE/\ IN LIMBAJUL etc ++ PENTRU LlCEU CONTAINERE ASOCIATIVE 235

void rehash ( size_type n );

Prima forma rerumeaza factorul maxim de incarcare a tabelei de dispersie. A douaforma stabileste z ca faetorul maxim de incarcare a tabelei de dispersie. in cazul illcare factorul de incarcare curcnt este > z, se reconstruieste tabela de dispersie(rehash). Implicit factorul maxim de incarcare esre 1. O.

void reserve ( size_type n ) i

Modifidi numarul de blocuri din container astfel incat sa fie adecvat pentru aretine eel putin n elemenre. Este posibiJ sa apara necesitarea reconstruir ii rabelei dedispersie (daca ri> bucket_count*max_load_factorl.

Daca numarul de blocuri (buckets) este ::::n, se reconstruieste tabela de dispersie(rehash) astfel incat numarul de buckets sa fie < n. Reconstructia tabelei de dispersiese realizeaza automat ori de cate ori factorul de incarcare depaseste facrorul maximde incarcare. Complexitatea acestei operatii este liniara ' in medic, dar poate fipatranca in eazul eel mai defavorabil.

~

-'

i.......'

~

-'

: :~

i.,

b. C.insert(-50,6)id. C.push_back(-50,6);

a.C[-50]=6;c. C.insert(make-pair(-SO,6)j

Dar in cazul in care obiectul C este declarat astfel :

multimap<int,int> C;

4. Care diutre urmatoarele afirmatii sunt adevarate ?a. in containerele set ~i multiset cheile &i valorile asociate coincid.b. Nu este permisa modificarea unei valori intr-un container de tip s e t Zmu Lt.Laet..c. Nu este permisa modificarea unei chei intr-un container de tip rnap ZrnuLtimap.d. Pentru toate containerele asociative sortate, elementele sunt organizate intern

ca un arbore binar de cautare echilibrat.e. Primul element dintr-un set /mul tiset este eel eu valoarea cea mai midi,

conform criteriului de sortare specificat la declarare.f. Primul element dintr-un map/mul timap este eel cu chela cea mai midi,

conform criteriului de sortare specificat 1a declarare.g. EJementele unui container asociativ sortat pot fi pareurse in ambele sensuri.h. Operatiile de cautare, inserare ~i stergere pentru containere asociative sortate

se executa in timp iogaritmic.i. Accesarea unui element intr-un container asociativ nesortat este mal rapida

decat accesarea unui element dintr-un container asociativ sortat.J. Niciuna dintre afirmatiile precedente.

5, Ce se va afisa pe ecran dupa executia urmatoarei secvente de mstrucjiuni ?

map<int, deque<int>, greater<int> > M;~ap .<int,~deque<int>, greater<int> >::iterator it;degue<int> : : ftera'tor i td;M[20] .push_back(3);M[2] . push_back 15) ;M[20] .push_back(300);M[200] . push_back (13) ;M[20J . push_back (1) ;M[2] . push_back (0) ;M[20] . push_back (33) ;M[50] .push__back(ll ;M[200] .push_back(8)for (it=M.begin(); it!=M.end(); ++it)

{cout«it->first«' ';for(itd=it->second.begin() ;itd!:=ic.->second.end() ;++itd)

cout«*itd«'c out,« ' vn ' i

}

6. Ce se va afisa pe ecran dupa executia urmatoarei secventc de instrucliuni '!

multimap<string,int> M;nTL:1timap<string,.int>: :iterator it;l'j. insert (make_pa:i.r ("l-ma", 1)-) iM. insert. (ma k ejpei.i r' l -Xerra " , 2) );"M. insert (make-pair ( "Ana" ,3) ) i M. insert (make_pair ( "Ion" , 4) ) ;M. insert (make-pair ( "Ana" , 5) ) j M_a n ss e r t. (make__pail ( "Dan" , 6) )

3. Considerand urmatoarea declaratie :

map<int,int> C;

Care dintre urmatoarele instructiuni sunt corecte sintactic ?

,\-:-, """'

float max_load_factor() conse noexcepti

void max_load_faccor ( float z ) i

2. Care dintre urmatoarcle declaratii pentru obiectul M sunt corecte?.a.

set<int, list> Mj

b.

7.4. Exercitii §i probleme propuse

d.

1: map<char> Mj

I' map<int, vector<int>, grea ter< in t> > Mj

c.

I, list<string> L (5 I "mama" ) i

: multimap<string, list<string> > M(L) i

1. Sa consideram urmatoarea secventa de operatii :

C.insert(lO)iC.insert(l) iC.insert(5)jC.insert(l) iC.insert(-30)jfor (it=C.begin()i it!=C.end()j ++it) cout«*iti

Ce se va afisa pe ecran in cazul in care declaratia obiectului c este :

a. s e t cirrt.> C i

b. multiset<int> Ci

Page 119: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

Plslerul de intrare stones. in contine pe prima linie un numar natural T,reprezentand numarul deseruri ..de.date derest. in continuare, pe liniile 2i si 2i+leste descris at i-lea set de date de test. Pe linia 2 i este scris numarul natural n , iarpe linia 2 i +1 sunt n numere naturale separate prin spatii, reprezentand dimensiunilecelor n gramczi,

Date de iesire

in fisierul de iesire stones. out se vor scrie T Iinli, tate una pentru fiecare setde date de test. Pe a a-a linie se va scrie un numar natural reprezentand consumu!minim de energie necesara pentru combinarea grarnezilor din al i-lea set de date.

Restriqii

• a < n $: 100000• Numarul de pierre din orice gramada este :S;100.

M. insert (make-pair ( "Dan" I 7) ) ; M. insert (make-pair ( "Dan" , 8) ) i

for (it=M.begin(); it!=M.end(); ++itlcout«it->first«' '«it->second«' \n';

i t=M . lower_bound (" Ana") i

cout«i t->first«' '«i t.r-c-e e corrd-c-c ' vn ' ;it=M. upper_bound ("Ana") i

cout«it->first«' '«it->second«'\n';it=M.lower_bound{ "Dana");cout«it->first«' '«it->second«' \n' ;

Ii it=M.upper_bound("Dana");cout«i t->first«' '«i t c s-s eoond-c e ' vn ' ;

7. Observatia eli in cazul problemei Egal (aplicatia 3) nu este necesar ca in contai,nerul map elementele sa fie ordonate dupa cheie. Implementati mai eficient solutiaacestei probleme, utilizand unordered_map.

8. StonesSe dau n gramezi de pietre, pe care dorim sa le combinam inrr-o singura gramada,

Pentru aceasta, putem alege doua grarnezl ~i sa le combinam obtinand astfel 0

singura gramada, Procedeul se repeta pana cand, in final, obtinem 0 singuragramada. Atunci cand combinam doua gramezr, consurnam energie egala cu numarulde pietre aflate in cele doua grarnezi care se combina. De exemplu, daca vom eom­bina 0 gramada fermata din 3 pierre eu 0 gramada fermata din 5 pietre consumul deenergie va fi egal cu 3+5=8.

Cerinta

Date fiind n gramezi de pietre, determinati eonsumul minim de energie necesarapentru a combina gramezile in una singura.

Date de intrare

237

Expliccuie

---.,.--

Universitatea TIANJIN, Concurs de selectie ACM 2010

CONTAINERE ASOCIATTVE

stones.in stones. out

1 45

4

5 9 6 3

Exemplu

Exemplu

pikachu.in

9. PikachuMiruna §i partenerul ei de aventura, Pikachu, sunt in fata unei noi provodiri. Cele

doua personaje au ajuns Binga un lant muntos 'format din N varfuri asezate in liniedreapta unul dupa altul. Pentru fiecare varf muntos se cunoaste inaltimea lui. Folo­sindu-se de puterile sale extraordinare, Pikachu este capabil sa scada sau sa creascatnaltimea unui varf muntos eu a unitate tnrr-o secunda. Din motive necunoscutemurttortlor de rand, cei doi prieteni vor sa obtina cel putin K varfur'i montaneconsecutive care au aceeasi inaJtime intr-un timp cat mai scurt.

Ceriruii

Determinati timpul minim in care Plkachu poate indeplini aceasta sarcina.

Date de intrare

Fisierul de intrare pikachu. in va contine pe prima linie doua numere N si Kavand semnificatia din enunj. Pe eea de-a doua linie se vor gasi N numere naturalereprezentand inaltimile varfurilor muntoase.

Date de iesire

Fisierul de iesire pikachu. out va contine un singur numar natural T, reprezen­tand timpul minim necesar pentru a obtine eel putin K varfuri consecutive ell aceea§iiinalnme.

. Restrictii si precizari

• 1 s: N s: 105• 1 ::;; K ::;; N• inaltimile munjilor sunt numere poiitive care se pot reprezenta pe inrregi de 32

de biti eu semn• Rezultatul se poate reprezenta pe un intreg de 64 de biti cu sernn

1IJlj.j

I

PROGRAMAREA iN UMBAJUL C/C+-+ PENTRU UCEU236

r--«

:-

~

Page 120: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

1 ~

238 PROGRAMAREA iN LIMBAJUL etc ++ PENTRU LIeEU

~

t,

....1

!~

~

2. Programarea orientatd pe obiecte fn C++

I. c; 2. d; 3. a; 4. b, c; 5. c; 6. b; 7. a, b , c; 8. c; 9.· a.cu d ~i C cu d; 10. b;11.d.; 12.b; 13.a,c; 14.b; 15.b; 16.b; l7.b; 18.d; i9.c; 20.c,e; 21.d;22. d; 23. b, c; 24. c, f; 25. a.

8. Solutii ~i indicatii

1. Principiile programarii orientate pe obiect

1.e;2.c.

28. EuclidVom incepe cautarca solutiei de 1a sfarsn : ultima impartire trebuie sa aiba restul O.

Aceste doua numere vor fonna primele elemente ale sirului de solutie : (ei §i e2)' Inconcluzie, ea este divizibil ell el.

Luand in considerare ca ne i~tereseaza cea mai mica pereche cu aceasta proprietate c>ej e L §i e 2 = 2 .

Conform penultimului pas al algoritmului lui Euclid e3 mod e 2=el' Adica neintereseazacea mai mica ...valoare pentru e) mod 2.=:_1 ==> e3=3.

Din asta va rezulta ca e .. mod e3=e2. Adica e 4 mod 3=2 §i cea mai mica valoarecare Indeplineste conditia este e4=5.

. Se observe ca sirul se poate defini ell recurenta e , =1, e 2=2 , ek==- ek-l+ eJ.: ..2 $i,,,, elementele sale sunt numere Fibonacci: 1, 2, 3, 5, 8, 13, .. '. Aceasta metoda garanteaza, pe, de 0 pane, numarul de past maxim in algoritmuJ lui

Euclid, iarpe de alta parte, solutia minima in cazu1 existenjci mai multcr perechi cuacelasi numar de pasi , Sa observam acea proprietate a algoritmului lui Euclid, conformcareia, daca Impartim un numar mai mic cu un numar mai mare, cele ooua numere se vorinversa. AstfeJ putem castiga inca un pas in favoarea solutiei.

in concluzie, solutia finala va fi fermata din ultimele doua clemente ale siruluicrescaror el<e2<e3< ... <e;..l<ep~n. Numarul de pasl va f p.

Avand in vederc marimea datelor de intrare, problema se va rezolva pe numere mario

Exemple

Olimpiada Najionala de Informatica, 2010

10. SubmcurixMiruna a gasit pe fundul marii 0 matrice ell n .linii si m coloane avand elementele

numere naturale. Din motive necunoscute, Mirunel vrea sa afle care este eea malmare submatrice patranca ce contine maxim k numere distincre.

Cerinta

Scrieti un program care sa determine latura maxima a unei submatrice carerespects conditiile lui Mirunel.

Date de intrare

Fisierul de intrare submatr ix . in contine pe prima linie trei numere naturalen m k separate prin cate un singur spatiu avand semnificatia din enunt, Pe urma­toarele n linii se gasesc care m nwnere naturale separate prin spatiu reprezentandvalorile din matrice. .

Date de iesire

Fisierul de iesire submatrix. aut va contine 0 singura linie pe care va fiscris un singur numar natural, larura submatricei cautate.

Restrictii si precizari

• 1:S:: n , m s; 300

·l:S::k:S::n*'m

submatrix.in submatrix.out Explicatie

573 3 Submatricea avand coltul din sranga sus pe pozijia

657 3 6 6 7 (2, 3) ~i latura 3 conune doar elemenrele 3, 5 ~i 7.

5 7 5 573 7

"3 3 5· -3-'''-5 6 -7 ,---7755567

7 7 6 5 6 3 5

' ..~-"~.

....1

Page 121: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

~

240 SOLUTII ~I INDICATII SOLUTII o5J INDICATil 241

~

"

, i

~ ~

,....,

~

~

3. Eiemente de programare generica

l.c;2.d;3.c·

6. Unifica. Se consnuieste vectorul de frecventa al cifrelor.b. Ideea de a parcurge vectorul $i de a realiza eliminarile conform enunjului este

ineficienta. Vern citi succesiv numerele $i te vom introduce intr-o stiva. La fiecare pasanalizam elementul curent $i elementul din varful stivei. Daca esre posibil, realizarnunificarea (extragem din stlva elementul de la varf in acest caz). Nu introducem insanumarul citit (sau rezultarul obtinut la precede-uta unifieare) decal atunci cand suntemsiguri ca nu mai este posibila 0 alta unificarc ,d,-,ci proeedeul deseris se repeta cat timpvaloarea din varful stivei $i valoarea- curentil se pot unifica). 0 aremie specials launificare trebuie acordera eifreJor egale -eu 0.·

4. STL. Concepte generale

1. c; 2. d ; 3. b, d, g, i :

4. Construim 0 functie de generare a numerelor aleatorii (era posibila $j definireaunui functor, dar varianta Cll functia e mai simpiaj :

I int GenT () { return (rand () %10000) ;

Generarea unui vector v format din numere aleatorii se poate realiza cu algoritmulgenerate () astfel:

generate(f, f+n, GenT);

5. Consrrutm functia elimin () , care elimina eifra/eifrele din mijloeul numarului :

void elimin(int& x)·{int 19, ii

vectar<int> Ci//extrag cifrele lui x si Ie plasez in c in ardine inversawhile (x) {c.push_back{x%lO) i x/::oIO;} •/tcalculez lungimea lui xLqe c . size () i

//canstruiesc a daua jumatacefor (x::oO, i::olg-li i>lg/2; i--) x-x*10+c[i]//sar una sau daua cifre din mijlaci--lg%2?1:2i//cancatenez prima jumatatewhile (i:>=O) x=x*lO+c [i--J i

Pentru a transforma toate valorilc dintr-un vector v:

fo-::::-_ea.ch(v.begin(), v.end() I elimip);"·

5. Containere secventiale1. c; 2. a. c, d;3.3 37 76 7arnxama ;

4. b; 5. d;6. Lista vl va contine 1 1 2 3 3 4 5 7, iar Iista v2 va fi vida.7. Lista vl va contine 1 6 5 4 3 2 1 2 3 4 iar Iista v2 va contine 7.8. 49. Mama si Ada vorbe nes10. a, C: 11. a, c ;

15. ArmeSolupa 1. Yom utiliza metoda Greedy. Sortam armele de la brau crcscaror dupa

punctaj. Sortam ~i armele din camera a~melor crescaror dupa punctaj. Parcurgem inordine crescaroare armele de la brau ~i le inlocuim pe cele mai miei arme de la brau ellcele mai mari din eamera armeJor (dear daca punerajul se uiareste).

Solutia 2. Utilizand interclasarea a doi vectori sortan (puterile armelor), insumarnprimele n valori din eei doi veetori sortaji descrescator.

Solutia 3. Se ordoneaza crescaror sirul puterilor armelor de la brau $i descresctitorsirul puterilor armelor de pe perete. Se inlocuieste anna ell cea mai mica putere cu armaeu putere maxima dintre cele aflare pe perete (daca este posibil) ~i asa mai .departe panacand nu mai putem alege nimic de pe perete (pbi~PCi) sau nu mai avem anne ladispozitie (m-en}. Suma initials a puterilor pbi va creste la fieeare Inlocuire eu diferentaPCi -pbi ·

16. SegmMetoda utilizara este Greedy. Vom defini un tip denumit segment, ea fiind 0 clasa

in care retinem doug date membre: extremitatea initiaHi ~i eea finala, Yom sortasegmentele crescator dupa extremitatea finala ; daca exists mai multe segmente ell aceeastextremitate finala, le sortam descrescaror dupa extremitatea initiala (pentru aceasta putemsupralncarca operatorul <). Vom utiliza doua variabile Last si PrevLast in careretinem ultimul punct selectat in multime (ell abseisa maxima pana la momentul curent) ~i

respeetiv penuitimul punct selecrat in muljime. Parcurgem aCUJ11 segmenrele in ordine.Dad. Las t (ultimul punet selectat) nu apartine segrnentului curent, atunci includem inmultime doua noi punete (extremitatea finala a segmentului curent $i extremitatea finals -1).Daca Last apartine segmentului curent, verificam oaca $i PrevLast: apartine segmen­tului curent. Dacg nu, vom include in multime extremitatea finala a segmentului curent.

17. CampusProblema se rezolva utilizand un dequeue. Scopul structurii esre de a proccsa la

fieeare moment elementul minim din dreapta e]cmemullli curcnt, pe un interval eulungime egaia eu eea a intervalului dinrre incepuruJ 1jiru]ui 1ji elementlll curcnt. Pentru arealiza acest Iuem, elememele ~irului sum parcursc de Ja dreapt3,Spre stangaiji intr9dusein dequeue prin partea dreapta impreuna eu un "rimp de in'trare" asociat ·(0 pentrUeJementul eel mai din dreapt3, 1 pentru unnatorul ere.).

Page 122: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

242 SOLUTII ~IINDICATII SOLUTIl SI INDICATIl243

u

6. Clasele adaptor

Penrru a "rezolva" acest 'circuit vom sparge un purcelus de pe circuit.Apoi facem 0 parcurgere DFS din purcelusul spart, pentru a deschide toti purcelusii

care se pot deschide cu cheile care se objin. Complexitate (memor-ia ~i timp) :O(N).

3. d; 4. c; 5. b;

9. Swap

a) Rezolvarea presupune folosirea unei stive in care sunt pastrate poz.itiile paran­rezelor deschise, neimperecheate Ja momenrul curenr. Pentru rezolvarea primului punctc3.J.1d este imalnira 0 paranteza Inchisa se adauga Ja costul total costul parantezei perccheformate din varful stivei ~i paranteza inchisa curenta. Notam eu C

t o tcosrul determinat Ia

punctul a.

b) Costul minim care se poate objine in urma efecruarii unci singure operatii swapasupra parantezarii initiate este ega1 cu Ceee- 2. Daca exista eel putin 0 posibilitate de aefectua 0 operajie swap, se va afisa Ct o t - 2 , a1tfel se va afisa -1

c) Exista patru tipuri de perechi de paranreze care pot fi interschimbate:) - se obtine acelasi sir deci acelasi cost;( ( - se obtlne acelasi sir deci acelasi cost;

) ( - se obtine un ~ir ell cost suplimentar 2. Oricc. astfel de caz. este redus.-Ja situaliaurmatoare: $irul () () se trans'for111~ ·i~ ( () ); -

() - se obrine un ~ir cu un cost mai mk eu 2: Orice astfel de caz este redus 1asituatia urmatoare: §irul (()) se transforma in () ().

Rezolvarea se face asemanator cu puncru1 a): se parcurge ~irul inirial construind stivain acela$i mod §i se comorizeaza de ,cate ori se imaJnesc paranteze pereche de cost 1.

Mai exista un caz particular in care ~irul de la stanga perechii () este parantezat corect,caz in care swap-ul este invalid deoarece nu se obrme 0 paramezare corecra. Exemplu pentruparantezarea {(») (), imerschimband paramezele de pe poziriile 5 §i 6 se obline -?irulinvalid ( ( ) ) ) {. Pentru a evita situalia preZentata se verifidi daca stiva nu este vida.

10. Valeto configuralie este identificata prin poziria ma;:;inii pe care dorim sa 0 scoatem din

parcare (ex, ey) ~i pozitia JocuJui liber (hx, by) .

Pentru simpJitate (~i economic.de memorie) v9m coditica conflgur31ia prinrr-un numarintreg in care ultimele doua cifre sum ex, unnatoa"re1e doua cy, urmatoarele dou~ hx §iprimele doua hy. Yom rezolva problema efecruand un Lee pe configuralij:

Elementul inrrodus la un moment dat "elimina" elementele din dreapta dequeue-uluicare au valori mai mari sau egaJe eli eJ deoareceniciunuJ uu mai poate reprezenraelement minim Ia dreapta. Pentru accesarea 1a un moment dat a unui minim Ia dreaptavalid (minimul la dreapta unui element cu numarul de ordine i (i~O) care se affasuficient de aproape de i pentru a tl indus in prefixul central in i), se vor elimina mailntai din caparul din stanga elementele care au "expirat" (adica acele elemente care suntminime la dreapra, dar se afla prea departe de elementul curem pentru a intra incomponenta prefixului). Acest lucru ll realizam utilizand timpii de intrare ai elementelorin dequeue. Timpul de intrare care ne intcreseaza este eel al elementului irnediarurmator srarsitutui prefixului curent. Daca prefixu1 curent este dat de mijJocuJ i, aruncie1ernentul cautat este pe pozitia 2* i in sir. Conform conventiei de norare a timpilor deintrare, suma dintre timpuJ de intrare in dequeue ~i nurnarul de ordine din sirul initial aJunui element este ri c L, AstfeJ, deducem ca timpul Iimira de intrare cautat este (n-l) -2*i.In acest moment, in capatu! din sranga al dequeue-u1ui se afla minimul la dreapta validdiutat. Daca elementul curcnt este rnai mare decat rninimul sau din dreapta $i este iarandul sau maxim Ia stanga (mai mare decat toate elementele din stanga sa) arunci eldetermina un prefix compus.

18. SecvopYom utiliza 0 lisra dublu inJanluira in care vom reline intervale1e ce se obtin in urma

operatiilor de inversare (un container de tip list). Initial lista este constlruita dintr-unsingur element care reprezinta intervalul [1, N] . La fiecare operatie de inversare I X Y:

se deterrnina elemenrul siruar pe pozitia x ;-se partitioneazll inrervalul in care se afla elementul siruat pe pozitia x in douaintervale;se determina eJementul suuat pe pozuia y ;se pantnoneaza intervalul in care se ana elementu1 siruar pe pozitia y in ooua intervale;se parcurg elementele listei situate intre pozitiile x sl Y ~i se inverseaza intervaleJecorespunzatoare.

Pentru a calcula suma elernentelor s x Y este suficient sa parcurg toare elernenteledin !ista core~punzatQ.?L~, interva1elQr si!uate)mre intervalulhLcare se afla poziria x $iintervalul in care se a-fjil poziria Y, ·s~ determina surn~ elementelor din fiecare interval $ise insumeaza sumele. Evident, 0 atenrie speciaJa trebuie sa acordam exact intervalelor incare se afla pozitia x $i respectiv poziria Y (aici n~u trebuie calculata suma din tatimervalul $i doar pan a la pozitia X, respectiv Y).

19. CheiPurern asocia probJemei un graf orientat astfel :

1. varfurile grafului sunl cei N purcelu$j.(numerotati de la 1 la N) ;

2. exista arc de la varful i Ja \larful j daca cheia purce1u§ului j se aiM. in purcelu$uJ i (i

va fi numit predecesoru1lui j).

Acesta este un graf particular (fiecare varf j are exact un predecesor - notatpre [j J). Vom r,.eprezenta grafului prin liste de adiacenta. De asemenea vom utiliza unvector chei: chei [i] ""0, "daca purcelu:5u! i nu a fast deschis, sau n+l, daciipurcelu~uJ i. '-! (OSl d~schis.

Cat rimp mai exista purcelu$i care nu au fast deschi~i :alcgcm primul purcelu~ inchis;po mind din accst purcelu~, construim "drumul" inapoi pana oblinem un circuit.

I

1.a. 25 13 2 10 7b. 25 13 10 7 2

2.

S.push( 'a'); S.push( 'm');cDut«S.top(); s.pop();.ccu t e e s . top () ;S.push('m'); cout«s.toP()i s.pop();coue-e e s . top () ;

~

..~

Page 123: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

r-r-244 SOLUTII SI INDlCATH SOLUTII s: INDICATil '45

,....

r

L J

r-t

r

r

r

1. lnitializam coada ell configuratia initiala (ex, cy t I, 1)

2. Cat timp coada nu esre vida §i masina nu a ajuns la ieslre :- extragern un element din coada_ analizam succesiv vecinii spatiului libel' pe care se ami masini parcate (adica

pozitii vecine pe care nu sunt stalpi) $i generam noile configuratii, mutand masinile. inve­cinate in spauu! libel'; pentru fiecare configuratie generara retinem numarul de muulriefectuare pentru a ajunge in configuratia respectiva, apoi introducem corifiguratia in coada.

11. PredecesorSolutia optima va utiliza 0 stiva st de lungime n $i un vector viz, tot de lungirne n

(viz [k] =-1 daca elementul de pe pozitia k din sriva are succesor sau 0 daca nu are).Observarn ca, dad la un moment dat avem in sir 0 subsecventa de forma

a[i) >a[i+l] > ... »a Lj l ,atunci este evident di. un element a [k] (j e k si a [j) <a lk l ) are ca predecesor pea [j ] , deci ceilalti termeni ai subsecventei nu mai pot avea predecesori.

Vom introduce succesiv in sriva elementele sirului. La fiecare pas, in stiva e1ementeievor fi pastrare in ordine strict crcscatoare. Cand citim un element x din sir, avem cazurile :

1. x este mai mare decat elernenrul din varful suvei. in acest caz, Inscram pe x in suva.2. x este mai mic decat varful stivci. Arunci vom extrage din stiva toate elementele

stivei strict mai mari decat x, iar cele marcate in viz cu 0 le comortzam ca fiind fiirapredecesori. Apoi,

a. daca stiva e vida, il punern pe x in suva nernarcat (nu are predecesori. lncal ) ;b. deca stiva nu e vida, elernentul din varf il marcam ell 1 (are predecesor pe x) ~i

apoi il adaugam pe x nemarcat in stiva." La sfarsit. golim stiva pentru a contcriza sl elementele ramase in stiva nevizitatc.

Deoarece fiecare element din sir este introdus 0 singura datil in stiva ~i 0 singura dataeste extras, complexitatea algoritmului este O(n).

12. CezarSe poatc utiliza metoda Greedy. Se eliminf succesiv, dintre frunzele existentc la un

moment dat, frunza de cost minim. Toate nodurile au costul initial 1. La eliminarea uneifrunze, se incrementeaza cu 1 costul tataJui acesteia. Validitatea metodei rezulta dinobservatia"ca, la eliminarea unei fruriz'e ·oai-edlre", tatal ~acesteia ~;-oate deveni"·ftun'Za~-la

randu! lui, dar cu un cost',strict mai mare decat al frunzei eliminate. Frunzele se potorganiza ca un min-heap, structura care se actualizea{:1i in timp logaritmic.

7. Containere asociative1. a. -301510; b. -3011510;

2. d; 3. map: ac; multimap: c4. a, b, c, d, e, f, g, h, i;5.200 13 850 12033001332 5 0

III

I

I

:II

Ana 5Dan 6Dan 7Dan 8Ion 4Xena 2Ana 1Dan 6Ion 4Ion 4

8. StonesMetoda este Greedy: la fiecare pas se reunesc cole rnai mici gramezi. Organizati

gramezile ca un mu1tiset.

9. PikachuVOl11 analiza cazul in care Neste egal cu K. in aceasta situatie raspunsul optim se obtine

aducand elementele la valoarea medianei (definim mediana unui sir cu N elemente ca fiindal N/2-lea element in ordine crescatoare). Aceasta este 0 afirmatie cunoscura. demon­stratla poate fi gasita in cartea Introducere in algoritmi de Cormen, Leisserson ~j Rivest.

Pentru cazurile in care K este mai mic deceit N, observam ca nu are rosr sa consideramsubsecvente de lungime mal mare dedit K. Pentru subsecventa care Incepe pe primapozijie putern calcula user mediana §i costul aducerii ceiorJaltee1emente la aceastavaloare in complexitate O(K log K). in continuare vom procesa unuatoarelc subsccvenjein ordine, inccrcand sa recalculam mediana sl cosrul in mod eficient. Costul cerut esteega] ell (K/2)*mediana-surna elementelor mai mici ca mediana + suma ele­mentelor mai mari ca mediana- (K-K/2-1) *mediana. Observam ca doua subscc­vente consecutive difera prin doar doua clemente. De aid tragem concluzia ca avemnevoie de 0 structura de date care sa suporte in mod eficient urrnatoarele operatii :inserarea unui element, stergerea unui element, gasirea medianei.

Pentru aceste' operajii purem folosi un arbore de intervale sau un arbore echilibrat(este suficient un set din STL). Costul se poate recalcula la fiecare pas in timp constant.

10. Submatrix '_c.-.Vom calcula pentru fiecare pozitie latura maXima a submatricei patratice care are

coltul din dreapta jos in pozitia respectiva §i care contine maxim k numere distincte. Vomretine aceste valori intr-o matrice best. Observam ca best[i] [j] :::; best[i-l][j -1] + 1. Vom ea1cula valorile matricei bes t pentru fieeare diagonala independent. inmomentul in care dorim sa ·trecem dintr-o stare (i, j) in starea (i +1, j +1), vomincerca sa extindem patratul cu coltul in (i I j) cu 0 unitate. Daca noua submatrice vacon~ine mai mult de k numere distincte, 0 vom mic~ora atilt cat este neeesar - mic§orarease face pastrand coltul din dreapta jos in (i+l, j+l). Pemru a putea efcctua rapidoperatiile descrise, vom normaliza yalorile din matrice §i ne vom mentine un vector defrecvente. Aceastii solutie are complexitatea O(N3

) , deoarece pentru fiecare diagonalavom pareurge fiecare element al matri~ei de maxim doua ori.

",.....

~ 6.Ana 1Ana 3

Page 124: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

~

~:=.-$3:=ou....o

Q)-~~.-u:=.-....~

~-~.-U.-.....til.-~~....~

UI

)~

6:j

~

~ @ ~ ~ .~"j:D e l1.l~ .,8, §' '2-5 '2rl ~..o .<:: ":" ~ a;l @ tJ'l'::l tn i5§ E:§ ~.~ :.5 .~ ~ ~ ~ ~ §

-<] & -5 8 i i:P 8 8 0 R O'"§ Q I I

v

~ ~~:;j ~f; :5 <d .£ E: .8 G' '2] '"2 '"2E<l.l ..... v;;i:: tl i:: U u

b;3 "5 dJ ~ ~.~ s g 2 g -g g..0'- a;l._ .- '" rl.... rl::l rl... '5 :u ~ :::l ;::l :E 0 § '-' ~ -- 'C es '-'<C<l.lp...uzzco_uOo..Oo Cl 10

~ @ ~UJ t:: !=:...... ,.......,

'j:E~<u ·gEe-1:: I::...... ~.o@ ~~@01 tn~::l 0:= 0 .c d:i Vi 0 a §E 1: '5 Cd «;I::l:'E w § 8. 8- 'C C'i

<I::cu> ClZo::l_uO 00 0 I I

" -~ ~.u= e: __w:E e v ·gEC'l:: ~lJl<l.l,O .... uo:.>§tll 01~

2 == .Q .~ ~ Vi":: ~ s..... '5C'::l ::l::l:-s!Uj§ __ -c C':l

<e.:.> ZZCO,-,uO 00 Cl I I

:.::: 0~ "0

.w ::l l:::: =00 :0 X'd .$2 ::l

;:: .g"2. % E' "§"" t:: 0 '- ,-..,-.~~Cd C':l::l~ 52. «l.....1.5:> Cl Z o::l 0 0 Cl I I

S S :2u ...... ~Q)<l.J 2 ..!StE::;::J :> Cd L.. '"g ~_.- ;,~ .Y,- - •• ~:. _- --. ," Cl "v;. .~

'0'- @ ~ ~~·cg 0 «l ---. _.-i0- 0 ,,-..

~ Cd cd <'<l::l .5 5 otl ~ :::> 8> :> OOU 0 0 ,2::J Z 0

- ~>-! ~ -o £ @

.1..J ee U Q.) ~ 0U l-'- .... U l- "0 --.

£1 9 ~ :5 g g, ---- - rl'~ ---... u__ ee c: l::........... .-I>:5> Q8o~ 6 50~f. 8 (5

" ~ v(l) 0 <I:l - ....

'~ Cd 'i<i ~.!2.... ~ ~.... OJ)U W '-t:: .... iUE:! <l.l Cd :=: ~ 0<1.) ~ "0

, :::; ..... U> :g.... E E...... .E.- ..9 tl .... t< ... <1.l ~ <U VU <';1(.) ~ <Uo E<l.l~ "0

~ ~_ :><d._ I1.l ~8 eel-:1i2'-.~ . ~ 5 .~ -.~' "5 ~ @ D l': gj .~ b ~«l E EE'::<l ...... klE ~eEEti:e:'J ..2:! ~t>i) '~"'<Ll ;.=: ...... i)<Ll 0..o cc o..o...=::: u.5"i5 P.l;;Jo..EO

Ti

IIi

Bibliografie

Andonie, Razvan : Garbacea, llie, Algoritmi fundamentali. 0 perspective C+ +, EdituraLibris, Cluj Napaca, 1995.

Cerchez, Emanuela; Serban, Marinel, Programarea tn limbajut CIC+ -I- pentru liceu,vol. 1-111, Editura Polirom , Iasi , 2005-2006.

Farrell, Joyce, Object Oriented Programming using C+ +, Course Technology, 2009.

Galatan, Constantin, C+. -r-. Introducere in Standard Template Library, Editura All,Bucuresti, 2008.

Iorga, Valeriu; Opincaru, Cristian; Stratan, Carina; Chirita, Alexandru, Structuri dedate si algoritmi, Aplicatii in C+ -l- folosind STL, Editura Polirom, Iasi, 2005.

Jamsa, Kris ; Klander, Lars, Totul despre C ~i C+. +, Editura Teora, Bucuresti, 2001.

Josuttis, Nicolai, The C+ + standard library. A tutorial and reference, Addison Wesley,1999 .

Meyers, Scott, Effective STL. 50 Specific Ways to Improve Your Use Of the StandardTemplate Library, Addison Wesley, 2001.

Musser, David; Derge, 5~ilImer.; .,Sai~~~, Atu] , c;+ +. programing with StandardTemplate Library, Addison Wesley, 1996. .

Simes, Tony, Teach yourself Object Oriented Programming in 21 days, SAMSPublishing, 2002.

Strcustrup , Bjarne, What is "Object Oriented Programming"? (1991 revised version).

Stroustrup, Bjarne, Programming Principles and practice using C+ -i-, Addison Wesley,

2009 .

Standard C+ + Library reference, http://www.cplusplus.com/refcrence.

Standard Template Library Programmer's Guide, http : Jlwww.Sgi.COlll/wch/stJ.

~

'''''''';

C-J

.....J

Page 125: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

.~~ ...

!

!

n,

r

,....,

r

~

!

r-l :

ri

!,....,

r

LA EDITURA POLIROM

au aparut :

Emanucla Cerchez, Marine} Serban - Programarea in.C/C+ + pentruliceu (vol. I)Emanuela Cerchcz, Marine] Serban ~ Programarea in CIC+ + pentru ticeu. Metode ~i tetmici

de programare (vol. II)Emanuele Cerchez, Marinel Serban - Programarea in CIC+ + pentru Iiceu. (vel. III)Emanuela Cerchez, Marmel Serban - FC, Pas cu pasSilvia Curteanu - P'C, Ghid de utilizareStefan Tanasa. Cristian Olaru, Stefan Andrei - JAVA de la 0 to expertDragos Acostachioaie - Administrarea ~i configurarea sistemelor Limo: (ed. a II1-a)Dragos Acos11ichioaie, Ovidiu Ene - FreeBSD. Utilizare. Administrare. Confi gurareStefan Trausan-Maru - Programare in Lisp. Inteligema artificiala ~i web semanticMarin Fotachc - Proieciarea bazelor de dare. Normalizarc $i postnormalizare.

Imptemeruiui SQL S; OracleValeriu Iorga, Cristtan Opincaru, Corina Straran, Alexandru Chi rita - Structuri de dale

$I algoritmi, Aplicatii in-C+ + folosind S1LSilvia Curteanu - Pc. Elemente de .baza Sf utilizareSabin Buraga -Programarea in Web 2.0Doina Logofaru - Algoritmf fundameniali in Java. AplicapdSilvia Curteanu - P'C, Etemente de baza $I tuilizareSilvia Curteanu - lnitiere in MotlabMircea Badut - Sisteme geoinformatice (GIS) pentru etectroenergetioiDorel Lucanu, Mitidi Craus - Proiectarea algorirmilorMarin Potache - SQL, Diatecte DE2, Oracle, PosrgreSQL Sf SQL ServerAna [ntuneric, Cristina Sichim, Daniela Tarasa - Aplicatii Windows in Visual C# 2008 Express

Edition. Aplicasii cu baze de date SQL Server 2008Mircea Cezar Preda (coord.), Ana-Maria Mirea, Doina Lavinia Preda, Constantin

Teodorescu-Mihai - Introducere tn programarea orientata-obiect. Conceptefundamentale din perspeaiva ingineriei software

Cosmin Varian - AcrionScripr 3.0. Programare Web in Flex # FlashMircea Badut - AutoCAD-ul in trei timpi. Inuiere, utilizare, performatua (ed. a III-a)Traian Anghel - Tot ce trebuie sa stii despre InternetMircea Baduj - Calculatorul in trei timpi (ed. a IV-a)Emanuela Cerchez, Marinel Serban - Programarea in C/C+ + peruru liceu. Programare orientata

pe obieae ~i programare genericil cu STL (vol. IV)....~-,

www.poliront.ro­

Redactor: Adri~il BotezTchnoredactor : Ir-ina Lacatusu

BUll de tipar : cctombrte 2013. Aparur : 2013Editurn Polirom, B-dul Carol J nr. 4 • P.O. BOX 266

700506, lasi , Tel. & Fax: (0232) 21.41.00; (0232) 21.41.11 ;(0232) 21.74.40 (difuzare) : E-mail: [email protected]

Bucuresri, Splaiul Unirii nr. 6, bl. B3A, SC. 1, et. I.sector 4, 040031, D.P. 53· C.P. 15-728

Tel. : (021) 313.89.78; E-mail: [email protected]

Tiparul execurat la S.C. Tipo-Lidana S.R.L.,Calca Unirii. nr. 35, Suceava

Tel.' 02301517.518; Fax: 0330/401.06'2E-mail: [email protected]; www.tlpcfidana.ro

I

+I,

Page 126: elibrary.ceiti.md+_POO(Cerchez).pdf · orice functie din algebra booleana poate fi impJementatii mecanic cu ajutorul unor circuire Jogice electronice) ~i John von Neumann (care a

[~~ l -- - r..; L: L L- _..._--" L------ l L - " t.- ~

L_ r