Sunteți pe pagina 1din 9

Algoritmic i programare Laborator 4

Tablouri de memorie
n cazul n care o aplicaie trebuie s prelucreze un ir de 20 de numere, s le ordoneze cresctor de exemplu, numerele sunt date de intrare pentru algoritm i n primul pas vor fi introduse n memoria calculatorului. La pasul urmator numerele vor fi prelucrate i aranjate conform criteriului de ordonare precizat, dup care, la al treilea pas, vor fi furnizate utilizatorului sub form de date de ieire. n memoria intern ele vor fi reprezentate ntr-o structura de date de tip tablou de memorie. Tabloul este o structur de date intern format dint-o mulime ordonat de elemente, ordonarea fcndu-se cu un ansamblu de indici. Tabloul de memorie se va identifica dup un nume, iar fiecare element al su, dup numele tabloului i numrul su de ordine. Fiecare element al structurii se identific dup numele tabloului i poziia din tablou. De la nceput trebuie s se precizeze cte elemente are tabloul pentru ca sistemul s-i aloce zona de memorie corespunztoare. n timpul prelucrrii tabloului nu i se pot aduga mai multe elemente dect au fost alocate, pentru c se iese din spaiul de memorie alocat. Tabloul de memorie este o structur de date static. Tabloul cu o singur dimensiune este numit vector. Declararea unui tablou de memorie de tip vector se face prin instructiunea: Tip_data nume [ nr_elemente ]; Aici, tip_data precizeaz tipul elementelor vectorului, nume este identificatorul vectorului, iar nr_elemente este o constant ntreag care specific numrul de elemente ale vectorului. De exemplu, prin: int a[20]; se declar un vector cu 20 de elemente de tip ntreg. La declararea unui vector se pot atribui valori iniiale elementelor sale astfel: Tip_data nume[ nr_elemente ] = { lista_valori }; Exemplu: int a[5]={10, 20, 2, 4, 9 }; n cazul declarrii unui vector iniializat se poate omite elementelor sale, dac se iniializeaz toate elementele. Referirea la un element al vectorului se face prin construcia: nume[indice]; unde nume este numele tabloului, iar indice este numrul de ordine al elementului n vector. n C++ numerotarea indicilor se face pornind de la 0! numrul

Cutare secvenial
Cutarea secvenial este unul dintre cei mai simpli algoritmi studiai. El urmrete s verifice apartenena unui element la un ir de elemente de aceeai natur, n spe a unui numr la un ir de numere. Pentru aceasta se parcurge irul de la un capt la cellalt i se compar numrul de cutat cu fiecare numr din ir. n cazul n care s-a gsit coresponden

(egalitate), un indicator flag este poziionat. La sfritul parcurgerii irului, indicatorul ne va arta dac numrul cutat aparine sau nu irului. #include<iostream> using namespace std; void main() { int n,x,i,gasit,a[50]; cout<<"Dati numarul de elemente ale sirului : "; cin>>n; cout<<"Dati numarul de cautat : "; cin>>x; cout<<"Dati elementele sirului"<<endl; gasit=0; for(i=0; i<n; i++){ cout<<"a["<<i<<"]= "; cin>>a[i]; if (a[i]==x) gasit=1; } if (gasit==0) cout<<"Numarul nu apartine sirului !"<<endl; else cout<<"Numarul apartine sirului !"<<endl; } Tem. S se transforme programul anterior poziiile n care apare elementul cutat. astfel nct s se afieze

Cutare binar
Algoritmul de cutare binar ofer performane mai bune dect algoritmul de cutare secvenial. El funcioneaz astfel: se compar numrul de cutat cu elementul aflat la mijlocul irului (element care se mai numete i pivot). n cazul n care cele dou elemente coincid cutarea s-a ncheiat cu succes. Dac numrul de cutat este mai mare dect pivotul, se continu cutarea n aceeai manier n subirul delimitat de pivot i captul irului iniial. Dac numrul de cutat este mai mic dect pivotul se continu cutarea n aceeai manier n subirul delimitat de pivot i nceputul irului iniial. Algoritmul prezentat se ncadreaz n clasa algoritmilor elaborai conform tehnicii de programare Divide et Impera. Unul din dezavantajele acestui algoritm este c irul n care se face cutarea trebuie s fie iniial sortat. #include<iostream> using namespace std; void main() { int i, n, x, st, dr, mijl, gasit, a[50]; cout<<"Introduceti numarul elementelor vectorului : "; cin>>n; cout<<"Introduceti elementul de cautat : "; cin>>x; for(i=0;i<n;i++) { cout<<"a["<<i<<"]= "; cin>>a[i]; } st=0; dr=n-1; gasit=0; while (st<=dr && gasit!=1) {

} if (st>dr) cout<<"Nu s-a gasit elementul cautat !"<<endl; else cout<<"Elementul cautat apartine sirului !"<<endl;

mijl=(st+dr)/2; if (a[mijl]==x) gasit=1; else if (x<a[mijl]) dr=mijl-1; else st=mijl+1;

Problem. S se elaboreze un algoritm pentru tergerea dintr-un vector a elementului cu indicele k i deplasarea elementelor vectorului, ncepnd cu indicele k+1, cu o poziie spre stnga, lungimea logic a vectorului micorndu-se cu 1. #include<iostream> using namespace std; void main() { int i,n,k,a[10]; cout<<"Introduceti dimensiunea vectorului : "; cin>>n; cout<<"Introduceti indicele elementului ce se elimina : "; cin>>k; for(i=0;i<n;i++) { cout<<"a["<<i<<"]="; cin>>a[i]; } for(i=k;i<n-1;i++) a[i]=a[i+1]; cout<<"Vectorul rezultat este : "; for(i=0;i<n-1;i++) cout<<a[i]<<" "; cout<<endl; } Problem. Algoritmul pentru inserarea unui element ntr-un vector n poziia indicelui k nseamn deplasarea elementelor vectorului, ncepnd cu indicele k+1, cu o poziie spre dreapta i apoi atribuirea noii valori elementului cu indicele k. Lungimea logic a vectorului se va mri cu o unitate i va fi n+1, cu condiia ca n+1 s fie mai mic sau cel puin egal cu lungimea fizic a vectorului, altfel ultimul element al vectorului se pierde. #include<iostream> using namespace std; void main() { const int dim=10; int i,n,k,x,a[dim]; cout<<"Introduceti dimensiunea vectorului (<=10): "; cin>>n; cout<<"Introduceti pozitia de inserare : "; cin>>k; cout<<"Introduceti elementul ce se insereaza : "; cin>>x;

for(i=0;i<n;i++) { //sunt citite componentele vectorului cout<<"a["<<i<<"]="; cin>>a[i]; } cout<<"Vectorul obtinut prin inserare este : "; if(n!=dim) { //daca dimensiunea era strict mai mica decat dim, putem obtine //un vector de dimensiune mai mare, fara pierderea de elemente for(i=n;i>k-1;i--) a[i]=a[i-1]; a[k-1]=x; for(i=0;i<n+1;i++) cout<<a[i]<<" "; } else { //prin inserarea elementului x se pierde ultima componenta a //vectorului citit de la tastatura //prima ramura din if-ul urmator este pentru situatia in care //pozitia de inserare nu este ultima pozitie a vectorului initial if (k<n-1) { for(i=n-1;i>k-1;i--) a[i]=a[i-1]; a[k-1]=x; for(i=0;i<n;i++) cout<<a[i]<<" "; } else { //cazul in care trebuie inserat un element pe ultima pozitie //a vectorului initial a[n-1]=x; for(i=0;i<n;i++) cout<<a[i]<<" "; } } cout<<endl;

Metode de sortare pentru vectori


1. Sortarea prin selecie direct
Considerm un vector de elemente comparabile ntre ele i dorim s le ordonm cresctor. Pentru aceasta comparm primul element cu toate elementele care urmeaz dup el. Dac gsim un element mai mic dect primul atunci le interschimbm pe cele dou. Apoi continum cu al doilea element al irului, pe care, de asemenea l comparm cu toate elementele care urmeaz dup el i n caz de inversiune interschimbm cele dou elemente. Apoi procedm la fel cu al treilea element al irului iar procesul continu astfel pna la penultimul element al irului care va fi comparat cu ultimul element din ir. #include<iostream> using namespace std; void main() { int i,j,n,aux,a[50];

cout<<"Introduceti numarul de elemente din sir : "; cin>>n; cout<<"Introduceti numerele"<<endl; for(i=0;i<n;i++) { cout<<"a["<<i<<"]="; cin>>a[i]; } //urmeaza algoritmul de sortare for(i=0;i<n-1;i++) for(j=i+1;j<n;j++) if (a[j]<a[i]) { aux=a[i]; a[i]=a[j]; a[j]=aux; } //urmeaza afisarea sirului sortat cout<<"Sirul sortat este:"<<endl; for(i=0;i<n;i++) cout<<a[i]<<" "; cout<<endl;

2. Sortarea prin metoda bulelor


Acest algoritm se mai numete i "sortarea prin selecie i interschimbare", "sortarea prin propagare" sau "metoda lent de sortare" datorit numrului mare de operaii care trebuie efectuate. Succesul algoritmului este asigurat de trecerea succesiv prin tablou, pn cnd acesta este sortat, cu specificaia c, la fiecare trecere, elementele succesive i i i+1 pentru care a[i]>a[i+1], vor fi interschimbate. Metoda poate fi imbuntit dac, dup fiecare trecere, se va reine ultima poziie din tablou n care a avut loc o interschimbare, iar trecerea urmtoare se va efectua doar pin la acea poziie. n cazul n care la o trecere nu a avut loc nici o interschimbare algoritmul se va incheia. Pentru o i mai bun optimizare se poate nlocui trecerea prin tablou ntr-un sens cu trecerea n dublu sens. n acest caz, dac la dou treceri succesive, ntre dou elemente i i i+1 nu a avut loc o interschimbare, atunci nici la trecereile urmtoare nu se vor nregistra interschimbri. Cu toate optimizrile aduse acestei sortari, ea se dovedete a fi cu mult mai lent dect sortarea prin inserie, fiind ns preferat de unii datorit simplitii, ce nu ridic probleme de implementare. Pentru valori suficient de mari ale dimensiunii vectorului ce urmeaz a fi sortat se recomand utilizarea unor algoritmi ce au o complexitate mai redusa i, prin urmare, ofer un timp de calcul mai mic. #include<iostream> using namespace std; void main() { int n,i,aux,terminat,a[50]; cout<<"Introduceti dimensiunea vectorului : "; cin>>n; for(i=0;i<=n-1;i++) { cout<<"a["<<i<<"]=";

cin>>a[i]; } terminat=0; while(!terminat) { terminat=1; for(i=0;i<n-1;i++) if(a[i]>a[i+1]) { aux=a[i]; a[i]=a[i+1]; a[i+1]=aux; terminat=0; } } cout<<"Vectorul ordonat este : "; for(i=0;i<=n-1;i++) cout<<a[i]<<" "; cout<<endl;

3. Sortarea prin inserie


Sortarea prin inserie se bazeaz pe aceleai principii ca i cele aplicate de majoritatea juctorilor de cri, adic dup ridicarea unei cri de pe mas, aceasta se aeaz n pachetul din mn la locul potrivit. Cu alte cuvinte, considerm c avem vectorul sortat a, iar la ivirea unui nou element care se va aduga vectorului, el va fi pus pe locul potrivit printr-o inserie n interiorul vectorului. - Inseria direct. Este cea mai simpl implementare a algoritmului i se face n felul urmtor: Se consider c primele i elemente al vectorului sunt deja sortate. Pentru elementul al (i+1)-lea, din tabloul iniial, se va gsi poziia n care trebuie inserat printre primele i elemente. Toate elementele tabloului de la aceast poziie i pn la i vor fi deplasate cu o poziie mai la dreapta iar poziia eliberat va fi ocupat de elementul i+1. - Inserarea rapid. Deoarece vectorul destinaie este un vector ordonat cresctor, cutarea poziiei n care va fi inserat a[i] se poate face nu secvenial (ca n cazul inserrii directe) ci prin algoritmul de cutare binar. Subvectorul destinaie este mprit n doi subvectori, se examineaz relaia de ordine dintre elementul de la mijlocul subvectorului i elementul a[j] i se stabilete dac elementul a[i] va fi inserat n prima jumtate sau n a doua jumtate. Operaia de divizare a subvectorului continu pn se gsete poziia n care urmeaz s fie inserat a[i]. #include<iostream> using namespace std; void main() { int i,j,n,aux,a[50]; cout<<"Introduceti dimensiunea sirului : "<<endl; cin>>n; cout<<"Dati elementele sirului :"<<endl; for(i=0;i<n;i++) { cout<<"a["<<i<<"]="; cin>>a[i]; } for(j=1;j<n;j++) {

} cout<<"Sirul ordonat este: "; for(i=0;i<n;i++) cout<<a[i]<<" "; cout<<endl;

aux=a[j]; i=j-1; while (aux < a[i] && i>=0){ a[i+1]=a[i]; i=i-1; } a[i+1]=aux;

4. Sortarea prin numrare


Aceast metod necesit spaiu suplimentar de memorie. Ea folosete urmtorii vectori: - vectorul surs (vectorul nesortat) a; - vectorul destinaie (vectorul sortat) b; - vectorul numrtor (vectorul de contoare) k. Elementele vectorului surs a[i] se copie n vectorul destinaie prin inserarea n poziia corespunztoare, astfel nct, n vectorul destinaie s fie respectat relaia de ordine. Pentru a se cunoate poziia n care se va insera fiecare element, se parcurge vectorul surs i se numr n vectorul k, pentru fiecare element a[i], cte elemente au valoarea mai mic dect a lui. Fiecare element al vectorului k este un contor pentru elementul a[i]. Valoarea contorului k[i] pentru elementul a[i] reprezint cte elemente sunt mai mici decit el i arat de fapt poziia n care trebuie copiat n vectorul b. #include<iostream> using namespace std; void main() { int i,j,n,a[50],b[50],k[50]={0}; cout<<"Introduceti dimensiunea sirului : "; cin>>n; for(i=0;i<n;i++) { cout<<"a["<<i<<"]="; cin>>a[i]; } for(i=0;i<n-1;i++) for(j=i+1;j<n;j++) if(a[i]>a[j]) k[i]++; else k[j]++; for(i=0;i<n;i++) b[k[i]]=a[i]; cout<<"Vectorul ordonat este : "; for(i=0;i<n;i++) cout<<b[i]<<" "; cout<<endl; }

Algoritm pentru interclasarea a doi vectori (*)


Interclasarea a doi vectori nseamn reuniunea celor doi vectori simultan cu ordonarea elementelor vectorului rezultat. Presupunem c cei doi vectori sunt sorta i (cresc tor sau descresc tor). Prin acest algoritm se parcurg simultan cei doi vectori surs pentru a se compara un element dintr-un vector cu un element din cel lalt vector. Elementul cu valoarea mai mic , respectiv mai mare, este copiat n vectorul destina ie i ters din vectorul surs . Procesul continu pn cnd este epuizat unul dintre vectori. Elementele r mase n cellalt vector se adaug la sfritul vectorului destinaie. Se folosesc urmtoarele variabile de memorie pentru: - vectori: a i b - vectorii surs (se presupune c sunt deja sorta i cresctor sau descresctor) i c - vectorul rezultat (vectorul destinaie) care reunete elementele din vectorii a i b, ordonate dup acela i criteriu ca i cele din vectorii surs; - lungimile logice ale vectorilor: n - pentru vectorul a (se introduce de la tastatur) i m - pentru vectorul b (se introduce de la tastatur ); lungimea vectorului c va fi n+m; - contorii pentru parcurgerea vectorilor: i - pentru vectorul a, j - pentru vectorul b si k - pentru vectorul c. Pasii algoritmului (pentu vectori sortati crescator) sunt: Pas 1. Se iniializeaz variabilele contor, pentru vectorii surse i pentru vectorul rezultat, cu 0: i=0, j=0, k=0. Pas 2. Se compar elementele a[i] i b[j]. Dac a[i]<b[j] se copie elementul a[i] n vectorul c prin c[k]=a[i] i se terge elementul a[i] din vectorul a; altfel, se copie elementul b[j] n vectorul c prin c[k]=b[j] i se terge elementul b[j] din vectorul b. Operaia de tergere nu se execut prin eliminarea efectiv a elementului din vector, ci prin incrementarea contorului: dace se terge elementul din vectorul a se incrementeaz contorul i, iar dac se terge elementul din vectorul b se incrementeaz contorul j. Pas 3. Se incrementeaz contorul k pentru c urmeaz s se copie un element n acest vector. Pas 4. Se compar contorii vectorilor surs cu lungimea lor. Dac fiecare contor este mai mic sau egal cu lungimea vectorului (i<n i j<m) se revine la pasul 2, n caz contrar se trece la pasul urmator. Pas 5. Se adaug la fritul vectorului c elementele rmase n cellalt, printr-o simpl operaie de copiere: dac i<n nseamn c s-a epuizat vectorul b i se vor aduga la vectorul c elementele rmase n vectorul a (se execut c[k]=a[i], k=k+1, i=i+1 pn cnd i devine egal cu lungimea n a vectorului a); altfel, s-a epuizat vectorul a i se vor ad uga la vectorul c elementele r mase n vectorul b (se execut c[k]=b[j], k=k+1, j=j+1 pn cnd j devine egal cu lungimea m a vectorului b). #include<iostream> using namespace std; void main() { int i,j,k,n,m,a[50],b[50],c[100]; cout<<"Introduceti dimensiunea primului vector : "; cin>>n; cout<<"Introduceti dimensiunea celui de al doilea vector : "; cin>>m; // se citesc cei doi vectori ordonati deja crescator !

cout<<endl; cout<<"ATENTIE! Vectorii trebuie introdusi ordonati crescator"<<endl<<endl; cout<<"Componentele primului vector"<<endl; for(i=0;i<n;i++) { cout<<"a["<<i<<"]="; cin>>a[i]; } cout<<"Componentele celui de al doilea vector"<<endl; for(j=0;j<m;j++) { cout<<"b["<<j<<"]="; cin>>b[j]; } // incepe interclasarea celor doi vectori i=0; j=0; k=0; while(i<n && j<m) { if(a[i]<b[j]) { c[k]=a[i]; i=i+1; } else { c[k]=b[j]; j=j+1; } k=k+1; } if(i<n) while(i<n) { c[k]=a[i]; k=k+1; i=i+1; } else while(j<m) { c[k]=b[j]; k=k+1; j=j+1; } // este afisat vectorul obtinut for(k=0;k<n+m;k++) cout<<c[k]<<" "; cout<<endl;

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