Sunteți pe pagina 1din 12

TIPURI STRUCTURATE DE DATE

TIPURI STRUCTURATE DE DATE


Pentru nceput am scris programe care nu prelucreaz dect date simple (de
exemplu, numere ntregi, numere reale, caractere). n realitate, un program trebuie
s prelucreze volume mari de date i pentru ca prelucrarea s se realizeze eficient
este necesar organizarea acestor date n structuri. De exemplu, s presupunem c
dorim s ordonm elevii din coal n ordine alfabetic. Pentru aceasta este nevoie
s reinem undeva (ntr-o structur de date) numele i prenumele elevilor colii i
abia apoi i putem ordona.
O structur de date reprezint un ansamblu (o colecie) de date,
organizate dup anumite reguli, reguli care depind de tipul de structur.

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]

Am specificat elementul indice al tabloului nume (indice reprezint


numrul de ordine al elementului n tablou, cuprins ntre 0 i NrE-1). Parantezele
ptrate ([]) constituie operatorul de indexare. Operatorul de indexare are
prioritate maxim (mai mare dect a operatorilor unari).
Exemple
1. S declarm un tablou cu 10 elemente de tip int:
int a[10];

Elementele tabloului sunt a[0], a[1], a[2], ..., a[9].


2. S declarm un tablou cu 100 de elemente de tip float:
float b[100];

TIPURI STRUCTURATE DE DATE

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};

Ca urmare se vor atribui n ordine elementelor tabloului valorile din lista de


iniializare (kNrE). Dac tabloul este integral iniializat la declarare, nu este
necesar s mai specificm dimensiunea sa, fiind considerat egal cu numrul de
valori din lista de iniializare. De exemplu:
int a[]={12,20,30,5};

Am declarat un tablou cu 4 elemente de tip int iniializate astfel:


12
20
30
5
a[0] a[1] a[2] a[3]
3. Un astfel de tablou, pentru care la declarare este specificat o singur
dimensiune, iar poziia unui element este specificat utiliznd un singur indice,
se numete tablou unidimensional sau vector.
4. Elementele unui tablou pot fi de orice tip al limbajului. Prin urmare....
elementele unui tablou, pot fi de tip tablou! Declarare:
tip nume[Nr1][Nr2];

Am declarat un tablou cu Nr2 elemente, fiecare element fiind un tablou cu Nr1


elemente de tipul specificat. Un astfel de tablou, pentru care la declarare trebuie s
specificm dou dimensiuni, iar poziia unui element este specificat utiliznd doi
indici, se numete tablou bidimensional sau matrice.
Putem s ne imaginm un tablou bidimensional ca pe o tabl de ah. Poziia unui
element pe tabl este identificat prin doi indici: linia i coloana. Prin analogie cu tabla de
ah, i la informatic primul indice utilizat n referirea unui element este denumit indice
de linie, iar cel de al doilea indice este denumit indice de coloan.

De exemplu s declarm o matrice cu dou linii i trei coloane cu elemente


ntregi, pe care o vom iniializa la declarare:
int a[2][3]={{1,2,3},{4,5,6}};

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]

De exemplu, pentru a ne referi la elementul de pe linia 1, coloana 2 din


matricea a, vom scrie a[1][2].

TIPURI STRUCTURATE DE DATE

5. Elementele unui tablou bidimensional pot fi de orice tip, inclusiv... tablou! Se


obin astfel tablouri multidimensionale. S declarm de exemplu un tablou
tridimensional (v imaginai un paralelipiped cu dimensiunile 10, 5, 40):
int a[10][5][40];

Prelucrri elementare pe vectori


Citirea unui vector
Citirea unui vector se realizeaz citind elementele vectorului, unul cte unul. S
considerm ca exemplu un vector a cu n elemente (n100) de tip int.
int a[100], n, i;
//declarare vector
cout << "n= "; cin >>n;
//citesc numarul de componente
for (i=0; i<n; i++)
//citesc succesiv componentele
{cout <<"a["<<i<<"]="; cin>>a[i];}

Afiarea unui vector


Afiarea unui vector se realizeaz afind pe rnd componentele vectorului.
for (i=0; i<n; i++)
cout << a[i] <<' ';

//afisez succesiv componentele

Copierea unui vector


S presupunem c dorim s copiem vectorul a ntr-un alt vector b. Copierea
unui vector nu se poate face printr-o atribuire de forma b=a(vei obine un mesaj
de eroare). Copierea unui vector se realizeaz element cu element:
for (i=0; i<n; i++) b[i]=a[i];

Determinarea elementului maxim/minim dintr-un vector


Pentru a determina cel mai mare element din vector, vom considera o variabil
(s o numim max) n care vom reine la fiecare pas maximul dintre elementele
analizate. Iniializm variabila max cu un element din vector (de exemplu, cu
a[0]). Parcurgem apoi vectorul, comparnd fiecare element din vector cu max, i
actualiznd eventual maximul dup comparare.
max=a[0];
//initializez maximul cu primul element
for (i=1; i<n; i++) //compar succesiv componentele cu max
if (max<a[i]) max=a[i];
//actualizez max

Exerciii
1. Modificai secvena de instruciuni precedent, astfel nct s determine cel mai
mic element din vector.

TIPURI STRUCTURATE DE DATE

2. Modificai secvena de instruciuni precedent, astfel nct s determine


maximul, dup iniializarea lui max cu ultimul element din vector.

Media aritmetic a elementelor strict pozitive


Se consider un tablou de 10 numere ntregi. Scriei un program care citete de
la tastatur cele 10 componente ale vectorului i afieaz pe ecran media aritmetic
a valorilor strict pozitive din vector, cu dou zecimale.
(variant bacalaureat, 2000)
Soluie
Dup citire, se parcurge vectorul, verificnd pentru fiecare element dac este
sau nu strict pozitiv. Cnd gsim un element strict pozitiv, l numrm i l adunm
la suma elementelor strict pozitive:
#include <iomanip.h>
void main()
{ float a[10], s=0;
int i, nr=0;
for (i=0; i<10;i++) cin >> a[i];
for (i=0; i<10; i++)
if (a[i]>0) s+=a[i], nr++;
if (nr) cout << setprecision(2) << s/nr;
else cout << "Nu exista elemente strict pozitive";}

Inversarea ordinii elementelor din vector


Pentru a inversa ordinea elementelor dintr-un vector trebuie ca primul element
s fie interschimbat cu ultimul, al doilea element cu penultimul, .a.m.d. Mai exact,
trebuie s parcurgem vectorul pn la mijloc i s interschimbm elementele
simetrice fa de mijloc. De exemplu:
12
20
30
5
1
2
a[0] a[1] a[2] a[3] a[4] a[5]
Problema care rmne este determinarea simetricului.
Poziia elementului
0
1
2

Poziia simetricului
n-1
n-2
n-3

Observaie
0+n-1=n-1
1+n-2=n-1
2+n-3=n-1

...

Observm c atunci cnd poziia elementului crete cu 1, poziia simetricului


scade cu 1, deci suma dintre poziia elementului i poziia simetricului este
constant (n-1). Deducem c simetricul elementului a[i] este a[n-1-i].
for (i=0; i<n/2; i++)
{aux=a[i]; a[i]=a[n-1-i]; a[n-i-1]=aux;}

TIPURI STRUCTURATE DE DATE

Verificarea unei proprieti


Frecvent apar probleme n care se cere s se verifice dac toate elementele unui
vector au o anumit proprietate P sau dac exist n vector un element care are
proprietatea P. Pentru a descrie o secven de instruciuni ct mai general,
considerm c P(x) are valoarea 1 dac x are proprietatea respectiv i 0, altfel.
a. Pentru a verifica dac toate elementele unui vector au proprietatea P, vom
verifica succesiv fiecare element din vector. Pentru a reine rezultatul verificrii,
vom considera o variabil ntreag ok, care va avea valoarea 1 dac toate
elementele vectorului au proprietatea P i 0, altfel. Iniial variabilei ok i
atribuim valoarea 1 (ipoteza optimist, prezumia de nevinovie din
moment ce nu am gsit nc nici un element care s conteste acest lucru, putem
presupune c toate elementele vectorului au proprietatea P). Dac, parcurgnd
vectorul, vom gsi un element care nu are proprietatea respectiv, variabilei ok
i vom atribui valoarea 0:
for (ok=1, i=0; i<n && ok;
//parcurg vectorul pana la
//unui element care nu are
if ( !P(a[i]) ) ok=0;

i++)
sfarsit sau pana la intalnirea
proprietatea P
//a[i] nu are proprietatea P

b. Pentru a verifica dac exist un element n vector cu proprietatea P, vom


parcurge vectorul (pn la sfrit sau pn la ntlnirea unui element cu
proprietatea P). Rezultatul verificrii l vom reine n variabila ntreag gasit.
Iniial (deoarece nu am gsit nc nici un element cu proprietatea P) i atribuim
variabilei gasit valoarea 0. Dac vom gsi n vector un element cu
proprietatea P, i vom atribui variabilei gasit valoarea 1:
for (gasit=i=0; i<n && !gasit; i++)
if ( P(a[i]) ) gasit=1; //a[i] are proprietatea P

Cutarea unui element ntr-un vector


Fie a un vector cu n (n100) componente ntregi i x o valoare ntreag.
Verificai dac x apare sau nu n vectorul a.
Practic, trebuie s verificm dac exist n vectorul a un element cu proprietatea
c este egal cu x. Particulariznd secvena de verificare de la punctul b, obinem:
for (gasit=i=0; i<n && !gasit; i++)
if (a[i]==x) gasit=1; //am gasit valoarea x in vector

Aceast metod de cutare, n care testm succesiv elementele vectorului, se


numete cutare secvenial. n cazul cel mai defavorabil (cnd x nu se gsete n
vector sau este plasat pe ultima poziie) cutarea secvenial efectueaz n
comparaii. O soluie mai eficient nu exist, n cazul general.

TIPURI STRUCTURATE DE DATE

n realitate ne confruntm frecvent cu problema cutrii unui element ntr-o


mulime i frecvent mulimea respectiv este ordonat (de exemplu, cutarea unui
cuvnt n dicionar, a unui numr n cartea de telefon, etc). n astfel de situaii nu
aplicm o cutare secvenial (de exemplu, pentru a gsi n cartea de telefon
numrul lui Popescu Ion nu ncepem s cutm de la litera 'A').
Cum procedm? Deschidem cartea de telefon la ntmplare. Verificm dac am dat
peste Popescu Ion. Dac nu, verificm dac Popescu Ion este n prima parte a crii sau n
cea de a doua i continum cutarea numai n poriunea respectiv. Procedeul se repet
pn cnd gsim sau pn cnd nu mai avem unde cuta.

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 ";

Acest algoritm de cutare se numete cutare binar. Denumirea este


sugestiv: la fiecare pas, alegem una din cele dou alternative posibile: caut la
stnga elementului din mijloc sau n dreapta lui.
Exerciiu
S considerm un vector cu n=7 elemente ordonate cresctor. Cte comparaii
execut algoritmul de cutare binar n cazul cel mai defavorabil (cnd elementul
cutat nu se afl n vector sau este depistat abia la ultima comparaie)? Dar pentru
n=10 elemente? Putei estima n general (n funcie de n) numrul de comparaii
necesare n cazul cel mai defavorabil? Ce concluzie tragei, comparnd algoritmul
de cutare binar cu algoritmul de cutare secvenial?

Sortare
Fie n (nN*) elemente a0, a1, , an-1 dintr-o mulime total ordonat.
Ordonai cresctor elementele a0, a1, , an-1.

TIPURI STRUCTURATE DE DATE

Problema ordonrii unor elemente (cunoscut i sub denumirea de sortare) este


frecvent ntlnit n practic i din acest motiv a fost studiat intens. Ca urmare, au fost
elaborai numeroi algoritmi de sortare. Cum de obicei numrul de elemente care trebuie
s fie ordonate este mare, s-a studiat i eficiena acestor algoritmi, n scopul elaborrii
unor algoritmi de sortare performani. Pentru nceput, vom studia algoritmi de sortare
simpli, nu performani, urmnd ulterior s nvm s evalum eficiena acestor algoritmi
i s elaborm algoritmi eficieni.

Sortare prin selecie


Sortarea prin selecie are dou variante: sortarea prin selecia elementului
maxim i sortarea prin selecia elementului minim. n ambele variante, ideea de
baz este aceeai: se selecteaz cel mai mare element din vector (sau cel mai mic)
i se plaseaz pe ultima poziie n vector (respectiv, pe prima poziie). Apoi se
calculeaz cel mai mare dintre elementele rmase i se plaseaz pe penultima
poziie n vector (sau cel mai mic dintre elementele rmase i se plaseaz pe a doua
poziie), .a.m.d. Acest procedeu se repet de n-1 ori.
for (dr=n-1; dr>0; dr--)
//calculez maximul de la 0 la dr
{for (max=a[0],pozmax=0,i=1; i<=dr; i++)
if (a[i] > max) max=a[i], pozmax=i;
a[pozmax]=a[dr];
//plasez maximul pe pozitia dr
a[dr] = max; }

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

TIPURI STRUCTURATE DE DATE

aux=a[i]; a[i]=a[i+1]; a[i+1]=aux;


schimb=1;}
//retin ca am facut schimbari
}
//procedeul se repeta cat timp se executa schimbari
while (schimb);

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

Sortare prin numrarea apariiilor


n anumite probleme, elementele vectorului au ca valori numere naturale dintrun interval [0, Max) de dimensiune redus (sau au valori care pot fi asociate
numerelor naturale dintr-un astfel de interval). Prin dimensiune redus nelegem
c se poate declara un vector V cu Max componente ntregi.
n acest caz particular cea mai bun metod de sortare este sortarea prin
numrarea apariiilor: se numr pentru fiecare valoare din intervalul [0, Max) de
cte ori apare n vector.
#include <iostream.h>
#define Max 1000

TIPURI STRUCTURATE DE DATE

#define NrMax 10000


int n, V[Max], a[NrMax];
int main()
{int x, i, j, nr;
cout<<"n="; cin>>n;
for (i=0; i<n; i++)
{cin>>x; //citesc o noua valoare
V[x]++;} //marim numarul de aparitii ale valorii x
//plasam in ordine elementele in vectorul a
for (nr=i=0; i<Max; i++)
for (j=0; j<V[i]; j++)
a[nr++]=i;
for (i=0; i<n; i++) cout<<a[i]<<' ';
cout<<endl; return 0;}

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.

TIPURI STRUCTURATE DE DATE

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; }

Subsecven de sum maxim


Fie x=(x0, x1, ..., xn-1) o secven de numere ntregi, dintre care cel puin un
element pozitiv. S se determine o subsecven de elemente consecutive xi, xi+1,
..., xj, astfel nct suma elementelor din subsecven s fie maxim. De exemplu,

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.

TIPURI STRUCTURATE DE DATE

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;}

Datorit celor trei cicluri for imbricate, algoritmul realizeaz un numr de


operaii comparabil (ca ordin de mrime) cu n3.
Soluia 2
Pentru a calcula suma elementelor din subsecvena de la st la dr, vom folosi
suma deja calculat a elementelor de la st la dr-1. Secvena de instruciuni care
rezolv cerinele problemei devine:
for (SMax=x[0], st=0; st<n; st++)
for (Sum=0,dr=st; dr<n; dr++)
{Sum += x[dr];
if (SMax < Sum) SMax=Sum, poz=st, Lg=dr-st+1;}

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

TIPURI STRUCTURATE DE DATE

Sum = x[i], st=i;


else
//inglobez x[i] in subsecventa curenta
{Sum += x[i];
if (SMax<Sum) //subsecventa curenta este maximala
SMax=Sum, poz=st, Lg=i-st+1;}

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

Tema arhiva campion: jocprim, meteo, bursa, schi

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