Sunteți pe pagina 1din 10

Structuri de date

CURS 4
1. Permutri
Permutrile sunt structuri algebrice larg folosite n algoritmi. Posibilitatea implementrii unei structuri de date care s gestioneze permutrile devine astfel o necesitate. Cea mai simpl structur de date care gestioneaz o permutare de n elemente este vectorul de n ntregi. De aceea vom construi n clasa Permutare structura de date necesar lucrului cu aceste tipuri de date.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 #include array.h // vom folosi clasa Array class Permutare { protected: Array<unsigned int> data //vectorul ce memorea!" #$tre%ii unsigned int $&rad // %radul 'ermut"rii public: Permutare(unsigned int const) Permutare(Permutare* const) Permutare(Array<unsigned int> const*+ unsigned int %rad) Permutare* set,de$tic() Permutare* set-everse() Permutare* operator=(Permutare const*) Permutare* operator.(Permutare const*) //com'u$ere unsigned int operator[](unsigned int const*) Permutare* operator++() // succesorul friend ostrea * operator!!(ostrea * os+ Permutare*) Permutare* %et,$verse() const unsigned int is/alid() const unsigned int is,de$tic() const unsigned int is-everse() const "oid dis'lay() const 0

n liniile 5-6 sunt declarai membrii prote ai ai unei permutri !i anume vectorul de ntregi fr semn !i gradul permutrii "numrul de elemente#. Dup cum se poate vedea n liniile $-%& sunt declarate trei variante de constructor. Primul constructor este cel implicit la care se specific doar gradul !i care iniial iniializeaz permutarea cu cea identic !i are ordinul de operaii #($)'
1 2 3 4 1 2 Permutare::Permutare(unsigned int const $r3e4&rad): $&rad($r3e4&rad)+ data($r3e4&rad+1) { for(unsigned int $r,$de561 $r,$de5<6$r&rad $r,$de577) data8$r,$de596$r,$de5 0

Structuri de date Cel de-al doilea constructor este un constructor de copiere care verific n linia ( dac nu cumva obiectul curent este tocmai cel dup care se copiaz. Dac prime!te ca parametru un alt obiect atunci copiaz datele acestuia n obiectul curent'
1 2 3 : 1 2 ; < Permutare::Permutare(Permutare const* 'erm) { if(t$is=6*'erm) { $r&rad6'erm.$r&rad data6'erm.data 0 0

)ltima variant de constructor prime!te ca informaie at*t gradul c*t !i vectorul ce reprezint permutarea'
1 2 3 : 1 2 Permutare::Permutare(Array<unsigned int> const* array+ unsigned int $r3e4&rad) { $r&rad6$r3e4&rad data6array 0

+dat ce am vzut cum se pot apela constructorii de permutri vom trece s vedem implementrile celorlalte metode ce in e,clusiv de teoria permutrilor. -unciile set.dentic !i set/everse seteaz valorile din permutarea curent corespunztor permutrii identice respectiv permutrii inverse0 deci aceste funcii modific valoarea permutrii curente.
1 2 3 : 5 2 ; < > 10 11 12 13 Permutare* Permutare::set,de$tic() { for(unsigned int $r,$de561 $r,$de5<6$r&rad $r,$de577) data8$r,$de596$r,$de5 return .t$is 0 Permutare* Permutare::set-everse() { for(unsigned int $r,$de561 $r,$de5<6$r&rad $r,$de577) data8$r,$de596$r&rad?$r,$de571 return .t$is 0

)rmtoarele trei metode sunt suprancrcri ai operatorilor de atribuire0 compunere !i inde,are. 1a fel ca la constructorul de copiere0 operatorul de atribuire verific dac nu cumva este vorba de o atribuire a valorii proprii !i numai n caz contrar realizeaz o atribuire de valori "folosind a!a cum se vede n linia 60 suprancrcarea operatorului de atribuire pentru 2rra3#' 4

Structuri de date
1 2 3 : 1 2 ; 8 > Permutare* Permutare::operator=(Permutare* const 'erm) { if(t$is=6*'erm) { $r&rad6'erm.$r&rad data6'erm.data 0 return .t$is 0

5om folosi operatorul de nmulire * pentru a realiza compunerea a dou permutri'


1 2 3 4 1 6 Permutare* Permutare::operator%(Permutare* const 'erm) //com'u$ere { for(unsigned int $r,$de561 i<6$r&rad i77) data8$r,$de596'erm8data8$r,$de599 return .t$is 0
n

2stfel0 dac notm cu &n mulimea tuturor permutrilor de grad

!i 0&n atunci 67 .

+peratorul de inde,are suprancrcat n continuare folose!te de a suprancrcarea inde,rii de la 2rra3 !i testeaz mai nt*i limitele indicelui nr'nde( pasat ca parametru'
1 2 3 4 1 6 ; unsigned int Permutare::operator[](unsigned int const* $r,$de5) { if(($r,$de5>61)**($r,$de5<6$r&rad)) return data8$r,$de59 cout << @Aroare acces i$dice @<< $r,$de5<< e$dl return B 0

8ai complicat de implementat este operatorul de incrementare 99 care genereaz permutarea succesor n lanul de permutri sortate n ordine le,icografic. Din punct de vedere teoretic0 ideea are la baz faptul c pe mulimea :n a tuturor permutrilor de grad n e,ist o relaie de ordine total ; astfel nc*t ntre dou permutri 0&n are loc relaia' ; <"#%=n>"i#6"i# "# %i;= !i "=#;"=#?. Pentru o permutare dat p0 procedura urmtoare genereaz succesoarea ei n ordine le,icografic'
1 2 3 4 1 6 ; < 9 Permutare* Permutare::operator77()// succesorul 'ermutarii { unsigned int $r,$de56$r&rad+ $rAu5+ $rCec+ $rDem' )$ile((data8$r,$de59< data8$r,$de5?19)**($r,$de5 > 1)) $r,$de5?? if($r,$de5>1) //e5ista succesor { $rAu56$r&rad )$ile(data8$r,$de5?19>data8$rAu59) // %aseste eleme$tul

Structuri de date
1B 11 12 13 1: 15 12 17 18 1> 2B 21 22 23 2: 25 22 //cel mai mic mai mare decat ultimul $rAu5?? $rDem'6data8$r,$de5?19 //i$terschimEa eleme$tele de 'e data8$r,$de5?196data8$rAu59 // 'o!. $r,$de5?1 si $rAu5 data8$rAu596$rDem' for($rAu56$r,$de5 $rAu5<6$r&rad $rAu577)//resortea!a //suEsecve$ta termi$ala for($rCec6$rAu571 $rCec<6$ $rCec77) if(data8$rAu59>data8$rCec9) { $rDem'6data8$rAu59 data8$rAu596data8$rCec9 data8$rCec96$rDem' 0 0 return .t$is 0

De e,emplu0 pentru permutarea '6(2+ 1+ :+ 2+ 1+ 3) &6 succesorul ei este 'F6(2+ 1+ 1+ 3+ :+ 2). .deea de calcul a succesorului este urmtoarea'
a#

se determin cel mai lung !ir descresctor de la sf*r!itul permutrii0 fie acesta 'G+ 'G71+ ...+ '$ cu 'G?1 < 'G > 'G71 > ... > '$ @ n cazul nostru0 pentru p avem c A ; 6 B 5 B (@ se determin n secvena 'G+ 'G71+ ...+ '$ elementul 'H astfel nc*t H {G+...+$0 !i 'H?1 > 'G?1 > 'H @ n cazul nostru avem 1 B A B(@

b#

c# d#

se interscCimb 'G?1 cu 'H?1 0 adic A cu 5@ se sorteaz cresctor elementele de pe poziiile G+G71+..+$ 0 adic 60 A0 ( !i se obine (0 A0 6.
<<

Dent*lnit p*n acum n curs0 suprancrcarea operatorului

de scriere n flu,"engl:stream# de

ie!ire este declarat ca funcie prieten "engl:friend# tocmai pentru c ea poate fi apelat din afara obiectului curent. Deci ea este o funcie e,tern0 care nu e membru al clasei Permutare dar are acces la datele privateEprote ate din clas. Codul ei apeleaz funcia membru
dis'lay

a clasei

Permutare0 este simplu !i !ablonul ei va fi reprodus pentru fiecare clas studiat n continuare'
1 2 3 4 1 ostream* operator!!(ostream* ostr+ Permutare* 'erm) { 'erm.dis'lay() return ostr 0

-uncia membru get.nverse calculeaz !i returneaz ntr-o permutare nou valoarea inversei permutrii curente'
1 2 3 Permutare* Permutare::%et,$verse() const { Permutare. 'erm6ne) Permutare(.this)

Structuri de date
4 1 6 ; for(unsigned int $r,$de561 $r,$de5<$r&rad $r,$de577) 'erm8data8$r,$de5996$r,$de5 return .'erm 0

8embrii is,de$tic !i is-everse testeaz dac permutarea curent este cumva permutarea identic respectiv permutarea invers !i returneaz % n caz afirmativ !i & n caz contrar'
1 2 3 4 5 6 ; < 9 1B 11 12 13 14 11 unsigned int Permutare::is,de$tic() const { for(u$si%$ed i$t $r,$de561 $r,$de5<$r&rad $r,$de577) if(data8$r,$de59=6$r,$de5) return B //false return 1 //true 0 unsigned int Permutare::is-everse() const { for(unsigned int $r,$de561 $r,$de5<$r&rad $r,$de577) if(data8$r,$de59=6$r&rad71?$r,$de5) return B //false return 1 //true 0

:e poate observa la membrii anteriori faptul c linia de declaraie a lor este urmat de cuv*ntul rezervat
const0

ceea ce nseamn c ei nu modific sub nici o form membrii privaiEprote ai ai

clasei Permutare. Pentru a putea valida o permutare "adic faptul c ea este o funcie bi ectiv pe mulimea F%040 G0nH# avem nevoie de o funcie membru care testeaz acest lucru'
1 2 3 4 1 6 7 < > 1B 11 12 13 1: 15 16 17 18 1> unsigned int Permutare::is/alid() const { Array<unsigned int> tem'Array($r&rad+ 1) // array tem'orar for(unsigned int $r,$de561 $r,$de5<$r&rad $r,$de577) tem'Array8$r,$de596B // i$iIiali!ea!" cu B valorile for($r,$de561 $r,$de5<$r&rad $r,$de577) if((data8$r,$de59>61)**(data8$r,$de5<6$r&rad9)) { tem'Array8data8$r,$de59977 0 else { return B // $u este valida 'ermutarea 0 for($r,$de561 $r,$de5<$r&rad $r,$de577) if(tem'Array8$r,$de59=61) return B // $u e5ista sau e du'licat return 1 //true 0

Structuri de date -uncia 'ri$t/alue nu este membru al clasei ns este apelat de membrul
cout' dis'lay

pentru a afi!a

coninutul permutrii. Ia are ca parametru un ntreg pozitiv !i l afi!eaz la flu,ul standard de ie!ire

1 2 3 :

"oid 'ri$t/alue(unsigned int $rPos) { cout<<$rPos<<@Jt@ 0

2!a cum probabil suntei obi!nuii de la Array !i clasa Permutare are un iterator care proceseaz secvenial valorile din vectorul suport al permutrii. 2cest membru se nume!te dis'lay !i are codul urmtor'
1 2 3 : 1 "oid Permutare::dis'lay() { data.visit('ri$t/alue) cout<<e$dl 0

2. STRUCTURA DE DAT MATRICE BIDIMENSIONAL


8atricea bidimensional oac un rol important n algebr !i geometrie vectorial motiv pentru care un rol important este acordat acestei structuri de date. Ia va fi g*ndit e,act a!a cum o trateaz orice calculator atunci c*nd la compilare se cunosc de a dimensiunile ei "numrul de linii !i cel de coloane# cu meniunea c ne vom folosi de un obiect de tipul Array de a tratat. Clasa *rra+2, pe care o vom scrie ca suport pentru matricele bidimensionale va privi o matrice cu m linii !i n coloane ca pe un grid0 adic vector unidimensional de m , n elemente grupate n m pacCete "linii# succesive de c*te n valori "coloane# ca n -igura %. n elemente 1inia % n elemente .......... ... 1inia 4 1inia i .............. 1inia m

-igura %. 8emorarea matricelor bidimensionale .at cum arat clasa ce implementeaz matricea bidimensional vzut simplu ca un grid cu number+f/oJs linii si number+fColumns coloane0 fr alte proprieti'
1 2 3 #include @array.h@ // foloseste clasa Array te plate<class D> class Array2K

Structuri de date
: 5 6 7 < 9 1B 11 12 13 1: 15 16 17 1< 19 2B 21 22 23 2: 25 22 2; 2< 2> 3B 31 32 33 34 31 { protected: unsigned int $umEerLf-o4s unsigned int $umEerLfMolum$s Array<D> array // su'ortul de memorare public: class -o4 //foloseste clasa -o4 i$ter$ { Array2K *array2K // referi$ta la u$ oEiect // de ti' Array2K unsigned int const ro4 // $umarul li$iei cure$te public: -o4(Array2K *Narray2K+ unsigned int Nro4): array2K(Narray2K)+ ro4(Nro4){0// fu$cIie i$li$e D* operator[](unsigned int colum$) const { return array2K.select(ro4+ colum$) // fu$cIie i$li$e 0 0 // sfOrPitul clasei -o4 Array2K(unsigned int N$umEerLf-o4s+ unsigned int N$umEerLfMolum$s):$umEerLf-o4s(N$umEerLf-o4s)+ $umEerLfMolum$s(N$umEerLfMolum$s)+ array(N$umEerLf-o4s.N$umEerLfMolum$s){0 //fu$cIie i$li$e QArray2K():$umEerLf-o4s(B)+ $umEerLfMolum$s(B) { array.setRe$%th(B) //fu$ctie i$li$e 0 D* select(unsigned int $r-o4+ unsigned int $rMolum$) -o4 operator[](unsigned int $r-o4) 0

Dup cum se poate observa0 n interiorul clasei 2rra34D am definit o nou clas -o4 corespunztoare unei linii din grid0 vizibil doar pentru metodele din clasa Array2K. Cum ma oritatea metodelor au fost de a definite inline0 iat cum arat n continuare definiiile metodelor
select !i a operatorului de inde,are aparin*nd clasei Array2K'
1 2 3 : 5 2 7 < > 1B te plate<class D> D* Array2K::select(unsigned int $r-o4+ unsigned int $rMolum$) { //fu$ctie i$li$e if($r-o4>6$umEerLf-o4s) cout<< @Ri$ia @<<$r-o4<<@ i$valida @<<e$dl if($rMol>6$umEerLfMolum$s) cout<< @Moloa$a @<<$rMolum$<<@ i$valida @<<e$dl return array8$r-o4.$umEerLfMolum$s7 $rMolum$9 //o'eratorul de // i$de5are a'licat clasei Array 0

Structuri de date
11 12 13 1: 11 -o4 Array2K::operator[](unsigned int $r-o4) { return -o4(%t$is+ $r-o4) // fu$ctie i$li$e 0

+dat astfel definit suportul pentru grid0 putem scrie interfaa cu metodele ce implementeaz operaiile algebrice corespunztoare matricilor !i anume adunarea0 scderea0 nmulirea0 transpusa !i scrierea matricilor.
1 2 3 : 1 6 7 < 9 1 0 1 1 1 2 1 3 1 : #include @array2K.h@ // folosim clasa Array2K te plate<class D> class Satri5:public Array2K<D> // moPte$ePte toate metodele // clasei Array2K { public: Satri5(unsigned int N$umEerLf-o4s+ unsigned int N$umEerLfMolum$s):array2K<D>(N$umEerLfRi$es+N$umEerLfMolum$s){0 Satri5<D> operator%(Satri5<D> const * ar%) const Satri5<D> operator+(Satri5<D> const * ar%) const Satri5<D> operator-(Satri5<D> const * ar%) const Satri5<D> tra$s'ose()const friend ostream* operator!!(ostream* ostr+ Satri5<D> const *ar%) 0 // sfOrPit de clas"

Dup cum se poate observa pe liniile K-$ din declaraia clasei0 constructorul este definit inline iar pe linia %( este declarat o funcie "ateneL nu e metod a clasei# prieten care pune coninutul matricei ntr-un flu, de ie!ire. /espect*nd ntocmai algoritmul algebric vom implementa n cele ce urmeaz nmulirea a dou matrice'
1 2 3 : 1 6 ; 8 > 1 B 1 1 1 2 1 Satri5<D> Satri5::operator.(Satri5<D> const * ar%) const { if($umEerLfMolum$s=6ar%.$umEerLf-o4s) cout<< @Satrici i$com'atiEile@<<e$dl Satri5<D> result($umEerLf-o4s+ ar%.$umEerLfMolum$s) for(unsigned int $rMurre$t-o46B $rMurre$t-o4<$umEerLf-o4s $rMurre$t-o477) for(unsigned int $rMurre$tMolum$6B $rMurre$tMolum$<ar%.$umEerLfMolum$s $rMurre$tMolum$77) { D sum6B for(unsigned int $r,ter6B $r,ter<$umEerLfMolum$s $r,ter77) sum76(.this)8$rMurre$t-o498$r,ter9 . ar%8$r,ter98$rMurre$tMolum$9 result8$rMurre$t-o498$rMurre$tMolum$96sum 0

Structuri de date
3 1 : 1 1 1 2 1 ; return result 0

n liniile (-A ne asigurm c cele dou matrici se pot nmuli0 dup care n linia 5 alocm noua matrice rezultat !i apoi o populm. 2dunarea !i scderea a dou matrice au apro,imativ acela!i cod !i se compun din trei etape "vezi codul urmtor#'
1 2 3 : 5 2 ; 8 > 1 0 1 1 1 2 1 3 1 : 1 5

validarea dimensiunilor "cele dou matrici trebuie s aib acelea!i dimensiuni# pe liniile (-6@ alocarea rezultatului "linia K#@ adunarea elementelor corespondente "liniile $-%(#.
Satri5<D> Satri5::operator+(Satri5<D> const * ar%) const { if($umEerLf-o4s=6ar%.$umEerLf-o4s) cout<< @Satrici i$com'atiEile@<<e$dl if($umEerLfMolum$s=6ar%.$umEerLfMolum$s) cout<< @Satrici i$com'atiEile@<<e$dl Satri5<D> result($umEerLf-o4s+ $umEerLfMolum$s) for(unsigned int $rMurre$t-o46B $rMurre$t-o4<$umEerLf-o4s $rMurre$t-o477) for(unsigned int $rMurre$tMolum$6B $rMurre$tMolum$<$umEerLfMolum$s $rMurre$tMolum$77) result8$rMurre$t-o498$rMurre$tMolum$96 (.this)8$rMurre$t-o498$rMurre$tMolum$97 ar%8$rMurre$t-o498$rMurre$tMolum$9 return result 0

Mranspusa matricei se calculeaz relativ u!or deoarece construim o matrice nou iar operatorul de scriere n flu, de ie!ire seamn cu cel de la 2rra3'
1 2 3 4 1 6 Satri5<D> Satri5::tra$s'ose()const //$u modific" oEiectul cure$t { Satri5<D> result($umEerLf-o4s+ $umEerLfMolum$s) for(unsigned int $rMurre$t-o46B $rMurre$t-o4<$umEerLf-o4s $rMurre$t-o477) for(unsigned int $rMurre$tMolum$6B

Structuri de date
; < > 1 0 1 1 1 2 1 3 1 : 1 5 1 2 1 ; 1 8 1 > 2 B 2 1 2 2 2 3 2 : $rMurre$tMolum$<$umEerLfMolum$s $rMurre$tMolum$77) result8$rMurre$t-o498$rMurre$tMolum$96 (.this)8$rMurre$tMolum$98$rMurre$t-o49 return result 0 friend ostream* operator!!(ostream* ostr+ Satri5<D> const *ar%) { for(unsigned int $rMurre$t-o46B $rMurre$t-o4<$umEerLf-o4s $rMurre$t-o477) { for(unsigned int $rMurre$tMolum$6B $rMurre$tMolum$<$umEerLfMolum$s $rMurre$tMolum$77) ostr<<ar%8$rMurre$tMolum$98$rMurre$t-o49<<@Jt@ ostr<<e$dl 0 return ostr 0

%&

S-ar putea să vă placă și