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:

numrul

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!

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

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) {

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

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

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++) {

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

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

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
sortai
(cresctor
sau
descresctor). Prin acest algoritm se parcurg simultan cei doi vectori
surs pentru a se compara un element dintr-un vector cu un element din
cellalt vector.
Elementul cu valoarea mai mic, respectiv mai mare, este copiat n
vectorul destinaie i ters din vectorul surs. Procesul continu pn
cnd este epuizat unul dintre vectori. Elementele rmase 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 sortai
cresctor sau descresctor) i c - vectorul rezultat (vectorul destinaie)
care reunete elementele din vectorii a i b, ordonate dup acelai
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 aduga la vectorul
c elementele rmase 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