Documente Academic
Documente Profesional
Documente Cultură
Tablouri
Un tablou este o colecie de date de acelai tip, memorate ntr-o zon de
memorie contigu, reunite sub un nume comun (numele tabloului).
Declararea unei variabile de tip tablou:
tip nume[NrE];
Am declarat un tablou format din NrE elemente de tipul tip. NrE indic
numrul de elemente din tablou i trebuie s fie obligatoriu o expresie constant.
nume[0]
nume[1]
nume[2] ...
nume[NrE-2]
nume[NrE-1]
Deoarece elementele unui tablou sunt memorate n ordine, unul dup altul, ntro zon contigu, pentru a ne referi la un element al unui tablou putem specifica
numele tabloului din care face parte elementul i poziia sa n tablou, prin numrul
su de ordine (numerotarea ncepe de la 0).
nume[indice]
Observaii
1. La ntlnirea unei declaraii de variabil tablou, compilatorul verific dac
dimensiunea zonei de memorie necesar pentru memorarea tabloului nu
depete memoria disponibil. Dimensiunea zonei de memorie necesar unui
tablou se calculeaz nmulind numrul de elemente cu numrul de octei
necesari pentru memorarea unui element, adic NrE*sizeof(tip).
2. Ca n cazul oricrei declaraii de variabile, putem iniializa elementele unei
variabile tablou, chiar de la declarare.
tip nume[NrE]={val0, val1, ..., valk};
a
Coloana 0 Coloana 1 Coloana 2
1
2
3
Linia 0
4
5
6
Linia 1
Pentru a ne referi la un element al unei matrice, specificm numele matricei,
indicele de linie i indicele de coloan astfel:
nume[indice_linie][indice_coloana]
Exerciii
1. Modificai secvena de instruciuni precedent, astfel nct s determine cel mai
mic element din vector.
Poziia simetricului
n-1
n-2
n-3
Observaie
0+n-1=n-1
1+n-2=n-1
2+n-3=n-1
...
i++)
sfarsit sau pana la intalnirea
proprietatea P
//a[i] nu are proprietatea P
Aceeai idee poate fi aplicat i pentru cutarea unui element ntr-un vector
ordonat. Cum pentru calculator este dificil s lucreze la ntmplare, vom lucra
prin njumtiri succesive: mai nti comparm elementul cutat cu elementul din
mijloc. Dac este egal, am gsit, am terminat. Dac nu este egal, verificm dac
elementul cutat este mai mare dect elementul din mijloc (n acest caz cutm mai
departe numai n cea de a doua jumtate). Dac elementul cutat este mai mic dect
elementul din mijloc, cutm mai departe numai n prima jumtate.
for (st=0, dr=n-1, gasit=0; !gasit && st<=dr;)
//cautam pe x de la pozitia st la pozitia dr; cautarea
//continua pana gasim sau pana nu mai avem unde cauta
{ mijloc=(st+dr)/2;
//calculam mijlocul
if (a[mijloc]==x) gasit =1;
//am gasit pe x
else
if (a[mijloc]<x) st=mijloc+1; //caut in stanga
else dr=mijloc-1;}
//caut in dreapta
if (gasit) cout<<x<<" se gaseste pe pozitia "<<mijloc;
else cout <<x<<" nu se afla in vector ";
Sortare
Fie n (nN*) elemente a0, a1, , an-1 dintr-o mulime total ordonat.
Ordonai cresctor elementele a0, a1, , an-1.
Observaie
La fiecare iteraie a ciclului for exterior este calculat max{a0, a1, , adr} i
este plasat pe poziia dr, elementele de la dr+1 la n-1 fiind deja plasate pe
poziiile lor definitive. Pentru a calcula max{a0, a1, , adr} sunt necesare dr
comparaii. Deci, n total se execut 1+2+...+n-1=n(n-1)/2 comparaii,
indiferent de ordinea iniial a elementelor vectorului.
Exerciii
1. Modificai algoritmul precedent, astfel nct s realizeze ordonarea
descresctoare a elementelor vectorului.
2. Modificai algoritmul precedent, astfel nct s realizeze ordonarea prin selecia
minimului.
Sortare prin compararea vecinilor (bubblesort)
O alt metod de sortare este de a parcurge vectorul, comparnd fiecare dou
elemente vecine i (dac este cazul) interschimbndu-le. Cum ntr-o singur trecere
nu se poate realiza sortarea vectorului, acest procedeu se repet pn cnd vectorul
devine sortat (la ultima trecere nu am mai efectuat nici o interschimbare).
do
{schimb=0;
//initial nu am facut nici o schimbare
for (i=0; i<n-1; i++)
//parcurg vectorul
if (a[i]>a[i+1])
//compar doua elemente vecine
{ //nu sunt in ordine, le interschimb
Observaii
1. Metoda este denumit i bubblesort (metoda bulelor) deoarece la fiecare nou
trecere prin vector elementele cu valori mari migreaz ctre sfritul vectorului
(urc n vector, aa cum bulele de aer se ridic la suprafa cnd fierbe apa).
2. n cazul cel mai defavorabil (cnd valorile sunt ordonate descresctor), aceast
metod execut aproximativ n2 operaii.
Exerciii
1. Modificai algoritmul precedent, astfel nct s realizeze ordonarea
descresctoare a elementelor vectorului.
2. Observm c dac la parcurgerea curent ultima interschimbare a fost efectuat
la poziia x, n oricare dintre parcurgerile ulterioare nu se vor efectua
interschimbri dup poziia x. mbuntii algoritmul precedent utiliznd
aceast observaie.
Sortare prin inserie
Metoda de sortare prin inserie, este de asemenea o metod simpl, pe care o
utilizm adesea cnd ordonm crile la jocuri de cri: de fiecare dat cnd tragem
o carte o plasm pe poziia sa corect, astfel nct n mn crile s fie ordonate.
Utiliznd aceast idee, sortm vectorul astfel: parcurgem vectorul, element cu
element; la fiecare pas i, cutm poziia corect a elementului curent a[i], astfel
nct secvena a[0], a[1], ..., a[i] s fie ordonat:
for (i=1; i<n; i++)
{v=a[i];
//caut pozitia lui v
for (poz=i; poz && a[poz-1]>v; poz--)
a[poz]=a[poz-1];
//mut la dreapta elementele > v
a[poz] = v; }
//poz este pozitia corecta pentru v
Interclasare
Fie a un vector cu n elemente i b un vector cu m elemente, ordonai cresctor.
S se construiasc un al treilea vector, c, care s conin att elementele vectorului
a, ct i elementele vectorului b, n ordine cresctoare.
O soluie (ineficient, care nu ine cont de faptul c a i b sunt deja ordonai)
este s copiem n vectorul c elementele din a i din b i apoi s sortm vectorul c.
O alt idee este de a parcurge simultan cei doi vectori, comparnd la fiecare pas
elementul curent din a cu elementul curent din b. Cel mai mic dintre cele dou
elemente va fi copiat n vectorul c, avansnd doar n vectorul din care am copiat.
Cnd am epuizat elementele din unul din cei doi vectori copiem elementele rmase
n cellalt, deoarece nu mai avem cu ce le compara.
for (i=j=k=0; i<n && j<m;)
if (a[i]<b[j])
//copiez in c elementul cel mai mic
c[k++]=a[i++];
//copiez din a
else c[k++]=b[j++];
//copiez din b
//copiez eventualele elemente ramase in a
for (; i<n; i++)
c[k++]=a[i];
//copiez eventualele elemente ramase in b
for (; j<m; j++)
c[k++]=b[j];
Aplicaii
Ciurul lui Eratostene
Fie n un numr natural (n10000). S se genereze toate numerele prime mai
mici dect n.
Soluie
O prim idee ar fi s parcurgem toate numerele naturale din intervalul [2, n],
pentru fiecare numr s verificm dac este prim i s afim numerele prime
determinate.
O idee mai eficient provine in antichitate i poart numele ciurul lui
Eratostene1. Ideea este de a pune n ciur toate numerele mai mic dect , apoi de a
cerne aceste numere pn rmn n ciur numai numerele prime. Mai nti
cernem (eliminm din ciur) toi multiplii lui 2, apoi cernem multiplii lui 3,
.a.m.d.
Vom reprezenta ciurul ca un vector cu 10000 de componente care pot fi 0 sau
1, cu semnificaia ciur[i]=1 dac numrul i este n ciur i 0 altfel.
Vom parcurge vectorul ciur de la 2 (cel mai mic numr prim), pn la n).
Dac ciur[i] este 1 deducem c i este prim, dar toi multiplii lui nu vor fi
(deci eliminm din ciur toi multiplii lui i).
n final n vectorul ciur vor avea valoarea 1 doar componentele de pe poziii
numere prime.
#include <iostream.h>
#define NMax 10000
int main()
{int ciur[NMax], n, i, j;
cout<<"n= "; cin>>n;
//initial toate numerele sunt in ciur
for (i=2; i<n; i++) ciur[i]=1;
for (i=2; i*i<=n; i++)
if (ciur[i])//i este prim
//elimin toti multiplii lui i
for (j=2; j*i<n; j++)
ciur[i*j]=0;
for (i=2; i<n; i++)
if (ciur[i]) cout<<i<<' ';
return 0; }
1. Eratostene (276196 .e.n) a fost un important matematician i filosof al antichitii. Dei puine
dintre lucrrile lui s-au pstrat, a rmas celebru prin metoda rapid de determinare a numerelor
prime i prin faptul c a fost primul care a estimat cu acuratee diametrul Pmntului.
pentru x=(1, 10, 3, -5, 4, 2, -100, 30, 15, 25, -10, 40, 1000) subsecvena de
sum maxim ncepe la poziia 7, are lungimea 6, iar suma elementelor este 1100.
Soluia 1
Considerm toate subsecvenele de elemente consecutive, calculm suma
elementelor din subsecven i reinem poziia de nceput i lungimea subsecvenei
de sum maxim.
#include <iostream.h>
int main ()
{int x[50], n, i, st, dr, poz, Lg, Sum, SMax;
cout <<"n="; cin >> n;
for (i=0; i<n; i++) {cout <<"x["<<i<<"]="; cin>>x[i];}
for (SMax=x[0], st=0; st<n; st++)
for (dr=st; dr<n; dr++)
{for (Sum=0,i=st; i<=dr; i++) Sum += x[i];
if (SMax<Sum) SMax=Sum, Lg=dr-st+1, poz=st; }
cout <<"Poz= "<<poz<<" ;Lg= "<<Lg<< " ; Smax= "<<SMax;
return 0;}
n acest caz, numrul de operaii efectuate de algoritm este comparabil (ca ordin
de mrime) cu n2. Spunem c algoritmul este ptratic.
Soluia 3
O dat cu parcurgerea vectorului x de la stnga la dreapta, se va memora suma
maxim calculat pn la momentul curent, n variabila SMax. n variabila Sum
este reinut suma elementelor subsecvenei curente. Elementul x[i] va fi
nglobat n subsecvena curent dac Sum+x[i]0. Dac Sum+x[i]<0,
nglobarea lui x[i] n orice subsecven ar conduce la o subsecven cu suma
elementelor mai mic dect cea maxim pn la momentul curent, prin urmare
x[i] trebuie ignorat, iar noua subsecven curent va ncepe la poziia urmtoare.
Mai exact, la pasul i: Sum=max{Sum, 0}+x[i]; SMax=max{SMax, Sum}.
Secvena de instruciuni care rezolv cerinele problemei devine:
for (SMax=Sum=x[0],st=poz=0, Lg=i=1; i<n; i++)
if (Sum < 0)
//noua subsecventa incepe pe pozitia i
n acest caz, numrul de operaii efectuate de algoritm este comparabil (ca ordin
de mrime) cu n. Spunem c algoritmul a devenit liniar.
Probleme propuse
1. Melci
Se consider n stlpi (numerotai de la 1 la n, n<20) de nlimi h1, h2, , hn
metri. La baza fiecrui stlp se afl cte un melc codificat prin numrul stlpului.
Fiecare melc i urc ziua pi metri i coboar noaptea qi metri (piqi). Scriei un
program care s afieze melcii n ordinea n care ating vrfurile stlpilor.
De exemplu, s considerm 3 stlpi cu nlimile 2, 4, 5. Melcul aflat la baza
stlpului 1 urc 1 m pe zi i coboar 0 m pe noapte. Melcul aflat la baza stlpului 2
urc 4 m pe zi i coboar 1 m pe noapte. Melcul aflat la baza stlpului 3 urc 1 m
pe zi i coboar 0 m pe noapte.
Melcul 1 ajunge n vrful stlpului dup dou zile. Melcul 2 ajunge n vrful
stlpului dup o zi. Melcul 3 ajunge n vrful stlpului dup 5 zile. Deci ordinea n
care melcii ajung n vrf este 2 1 3.
(Concurs PACO 1997)
2. Mulimi
Se citesc de la tastatur dou mulimi A i B cu n, respectiv m elemente numere
naturale mai mici dect 1000. S se determine intersecia i reuniunea celor dou
mulimi. Implementai mai nti o mulime ca un vector n care memorai
elementele mulimii, apoi prin vector caracteristic. Realizai o comparaie ntre
eficiena implementrii celor dou operaii cu cele dou reprezentri.
3. Zig-zag
Din fiierul ZigZag.in se citesc N numere ntregi (N1000). Afiai pe
prima linie a fiierului ZigZag.out cel mai lung MZigZag care se poate construi
din numerele citite. Numim MZigZag o secven de numere a1, a2, ..., am astfel
nct a1 a2a3a4a5... am-1am. De exemplu:
ZigZag.in
7
7 5 0 1 4 9 3
ZigZag.out
9 3 7 1 5 4