Sunteți pe pagina 1din 9

Clasa a IX-a

Tablouri

Cap.6 Tablouri
6.1 Declararea tablourilor
Un tablou reprezint un tip structurat de date care ocup o zon de memorie continu,cu elemente componente de acelai tip. n cadrul tabloului un element este n mod unic identificat prin poziia ocupat n cadrul structurii. Aceast poziie este definit prin unul sau mai muli indici sau indeci, din acest motiv tablourile numindu-se variabile indexate. Declararea unui tabou se face cu sintaxa : tip nume[dim_1][dim_2]..[dim_n]; unde : - tip este tipul elementelor componente ale tabloului. Acesta poate fi un tip predefinit sau definit de utilizator - nume este numele variabilei tablou - dim_1, dim_2,..,dim_n sunt numere ntregi pozitive care exprim dimensiunile tabloului Pentru a utiliza un element din tablou se folosete sintaxa : nume[index_1][index_2][index_n] fiecare index respectnd condiia index_i { 0,,dim_i-1} . Un tablou unidimensional se numete vector, iar un tablou bidimensional se numete matrice . Exemple: char s[100]; int x[25]; long double a[10][15]; Observaii: - primul element dintr-un vector va avea indexul 0, iar ultimul element stocat va avea indexul dim-1 - primul element dintr-o matrice va avea indexul (0,0), iar ultimul va avea indexul (dim_1-1,dim_2-1) - dimensiunile tabloului trebuie s fie expresii constante - compilatorul nu face verificri pentru depirea dimensiunii tabloului - pentru alocarea unui tablou sunt necesari nr_elemente*sizeof(tip) octei, unde tip este tipul de baz al tabloului - atribuirea tablourilor nu poate fi fcut direct Exemplu : int x[10],y[10]; x=y; /*operaie ilegal*/

6.2 Iniializarea tablourilor


Declaraia unui tablou poate fi urmat de o secven de iniializare format din una sau mai multe perechi de acolade ntre care se pun valori ale tipului de baz, separate prin virgul. Pentru tablourile unidimensionale este permis omiterea numrului de elemente. El va fi egal cu numrul de valori folosite la iniializare. n cazul n care la iniializarea tablourilor de tip numeric sunt folosite mai puine elemente dect dimensiunea tabloului, restul elementelor sunt iniializate cu 0. Exemple: float x[5]={1.2,3.4e3,-2,90.7E-8,-88.5e-7}; char s[100]=test tablou; short y[]={0,1,2,3,4}; /* y are 5 elemente */ char s[]={t,e,s,t,\0}; /* char s[]=test; */ int x[5]={1,2}; /* x=(1, 2, 0, 0, 0) */ Iniializarea unui tablou multidimensional se face asemntor cu cea a unui vector. Se poate face specificarea complet sau parial a datelor, cele nedefinite fiind iniializate cu 0. Este permis doar omiterea primei dimensiuni (cea din stnga). Exemple: int a[3][2]={{1,2},{3,4},{5,6}}; echivalent cu :

Clasa a IX-a

Tablouri

int a[][2]={{1,2},{3,4},{5,6}}; sau chiar cu: int a[3][2]={1,2,3,4,5,6}; Iniializarea int m[2][3]={{1},{2}}; este echivalent cu : int m[2][3]={{1,0,0} , {2,0,0}}; //elementele lips au fost iniializate cu 0

Clasa a IX-a

Tablouri

6.3 Prelucrri elementare ale vectorilor


Deoarece limbajul C nu verific depirea dimensiunilor maxime declarate pentru tablourile utilizate n aplicaii, pentru a evita scrierea accidental a unor zone de memorie, programatorul trebuie s asigure validarea dimensiunilor reale (implicit a numrului de elemente) citite de la intrare. Uzual, un vector se declar n urmtoarea manier: #define MAX 100 /* dimensiunea maxim admis */ int a[MAX]; int n; /* dimensiunea real citit la intrare */ cout<<n=; cin>>n;

6.3.1 Citirea elementelor unui vector


Dup validarea dimensiunii, citirea elementelor unui vector se face n ordinea cresctoare a indicilor, uzual cu o instruciune for : for(int i=0; i<n; i++) { cout<<a[<<i<<]=; cin>>&a[i]; } Observaie: Dei tablourile sunt indexate n C ncepnd de la 0, se pot utiliza elementele numai de la indexul 1 (ca n Pascal), elementul a[0] rmnnd liber. n aceast situaie secvena de citire (i toate celelalte secvene de prelucrare) se vor modifica corespunztor, conform modelului de mai jos: for(int i=1;i<=n;i++) { cout<<a[<<i<<]=; cin>>a[i]; }

6.3.2 Determinarea elementului minim/maxim


Metoda tipic de determinare a elementului minim/maxim dintr-un vector este urmtoarea : se iniializeaz minimul/maximul cu primul element din vector apoi se compar cu celelalte elemente din vector reinndu-se, pe rnd, valorile mai mici/mai mari. minim=a[1]; /* maxim=a[1]; */ for(i=2; i<=n; i++) if(minim>a[i]) /* (maxim<a[i]) */ minim=a[i]; /* maxim=a[i]; */

6.3.3 Determinarea primului element cu o anumit proprietate


Pentru a determina primul element (de indice minim) cu o anumit proprietate, se parcurge vectorul de la stnga la dreapta pn cnd gsim primul element cu proprietatea cerut sau pn cnd epuizm elementele vectorului. De exemplu, determinarea primului element nul dintr-un vector se realizeaz cu secvena: f=-1; for(j=1;j<=n;j++) if(!a[j]) { f=j; break; } Verificnd valoarea variabilei f decidem dac n vectorul exist cel puin un element cu proprietatea cerut (f=indicele acestuia) sau nici unul (f =-1).

Clasa a IX-a

Tablouri

6.3.4 Determinarea ultimului element cu o anumit proprietate


Pentru a determina ultimul element (de indice maxim) cu o anumit proprietate, se parcurge vectorul de la dreapta spre stnga (n ordinea descresctoare a indicilor) pn cnd gsim primul element cu proprietatea cerut sau pn cnd epuizm elementele vectorului. De exemplu, determinarea ultimului element par dintr-un vector se realizeaz cu secvena: f=-1; for(j=n;j>=1;j--) if(!(a[j]%2)) { f=j; break; }

6.3.5 Eliminarea tuturor elementelor cu o anumit proprietate


Cea mai simpl metod de a elimina dintr-un vector toate elementele cu o anumit proprietate este s crem un nou vector n care se pstreaz elementele care nu au proprietatea respectiv. De exemplu, pentru a elimina dintr-un vector toate elementele negative, putem utiliza secvena: j=0; for(i=1;i<=n;i++) if(a[i]>=0) /* nu are proprietatea cerut */ b[++j]=a[i]; /* pstram elementul n vectorul b */ n=j; /* actualizm dimensiunea vectorului */ Metoda este ineficient datorit consumului de memorie necesar pentru vectorul b. O metod mult mai eficient este s folosim acelai vector n care vom ngrmdi pe primele poziii elementele care trebuie pstrate. Prin actualizarea dimensiunii vectorului, elementele de prisos nu vor mai fi luate n consideraie n prelucrrile ulterioare. Secvena care realizeaz aceast operaie este urmtoarea: j=0; for(i=1;i<=n;i++) if(a[i]>=0) /* nu are proprietatea cerut */ a[++j]=a[i]; /* mutm elementul la nceputul vectorului */ n=j; /* actualizm dimensiunea vectorului */

6.3.6 Eliminarea elementului din poziia k dat (1<=k<=n)


Prin eliminarea elementului din poziia k dat (elementul de indice k-1), se observ c primele k-1 elemente rmn neschimbate, n timp ce elementele din poziiile k+1, k+2,.,n se deplaseaz cu o poziie spre stnga pentru a umple golul rmas prin eliminarea elementului din poziia k. Evident, dimensiunea vectorului scade cu o unitate : for(j=k;j<=n-1;j++) a[j]=a[j+1]; /* deplasm elementele spre stnga */ n--; /* corectm dimensiunea */

6.3.7 Inserarea unui element y n poziia k dat (1<=k<=n)


Cum inserarea unui element se face fr a pierde vreun element din vectorul iniial, elementele din poziiile k, k+1,.......n trebuie s se deplaseze cu o poziie spre dreapta pentru a face loc noii valori y introdus n poziia k (indice k-1). Dimensiunea vectorului crete cu o unitate: for(j=n+1;j>=k+1;j--) a[j]=a[j-1]; /* deplasm elementele spre dreapta */ a[k]=y; /* inserm elementul y */ n++; /* actualizm dimensiunea */

Clasa a IX-a

Tablouri

6.3.8 Permutarea circular cu o poziie spre stnga


Prin acest operaie, elementele din poziiile 2,3,..,n se deplaseaz cu o poziie spre stnga i elementul din prima poziie ajunge n poziia n. Vectorul nu i modific dimensiunea: aux=a[1]; /*salvm temporar primul element */ for(j=10;j<=n-1;j++) a[j]=a[j+1]; /* deplasm elementele spre stnga */ a[n]=aux; /* mutm elementul n ultima poziie */

6.3.9 Permutarea circular cu o poziie spre dreapta


Prin aceast operaie, elementele din poziiile 1,2,,n-1 se deplaseaz cu o poziie spre dreapta, iar elementul din poziia n ajunge n poziia 1. Vectorul nu i modific dimensiunea: aux=a[n]; /* salvm temporar ultimul element */ for(j=n;j>=2;j--) a[j]=a[j-1]; /*deplasm elementele spre dreapta */ a[1]=aux; /* mutm elementul n prima poziie */

6.3.10 Sortarea vectorilor


Prin sortare se nelege aranjarea elementelor unui vector n ordine cresctoare sau descresctoare. Pentru rezolvarea acestei probleme au fost concepui diveri algoritmi, mai mult sau mai puin rapizi, mai simpli sau extrem de complicai. n acest moment vom aborda dou dintre cele mai simple metode de sortare de complexitate n2 . A) Metoda bulelor (bubblesort) Conform acestei metode, vectorul este parcurs de la stnga spre dreapta comparndu-se perechi de elemente succesive (a[j] cu a[j+1]). Dac cele dou elemente nu sunt n ordinea cerut, se interschimb i, o variabil iniial egal cu 0, se incrementeaz. n acest fel, la prima parcurgere a vectorului, elementul maxim din ir (dac se face ordonare cresctoare) se deplaseaz spre dreapta pn cnd ajunge n ultima poziie. La a doua parcurgere a vectorului , al doilea cel mai mare element ajunge n penultima poziie etc. Parcurgerea vectorului se reia pn cnd nu mai gsim nici-o pereche de elemente consecutive neordonate. La fiecare parcurgere, lungimea secvenei care se verific scade cu o unitate: k=n; /* iniial verificm tot vectorul */ do{ f=0; /* numr perechile neordonate */ for(j=1;j<=k-1;j++) if(a[j]>a[j+1]) /* pentru ordonare cresctoare */ { aux=a[j]; a[j]=a[j+1]; a[j+1]=aux; /* interschimbm elementele */ f++; /* numrm in f */ } k--; /* lungimea secvenei care se verific scade */ }while(f); /* repet ct timp mai sunt perechi neordonate */ B)Sortarea prin selecie direct Conform acestei metode primul element (a[0]) se compar pe rnd cu toate elementele de dup el i dac ordinea de sortare nu este respectat, cele dou elemente se interschimb. Dup efectuarea tuturor comparaiilor, n prima poziie ajunge cel mai mic element din vector (n cazul ordonrii cresctoare). Se compar apoi al doilea element cu toate elementele de dup el etc. La ultimul pas se compar numai ultimele dou elemente. Secvena corespunztoare de program este : for(i=1; i<=n-1; i++) /* elementul care se compar */ for(j=i+1;j<=n;j++) /* elem. de dup el cu care se compar */ if(a[i]>a[j]) /* pentru ordonare cresctoare */ { aux=a[i]; a[i]=a[j]; a[j]=aux; /* interschimbm elementele */ }

Clasa a IX-a

Tablouri

6.3.11 Algoritmul de cutare binar


Se consider un vector oarecare A cu n elemente i o valoare x. Se cere s se verifice dac x apare printre elementele vectorului sau nu. Dac lucrm cu un vector oarecare, se vor compara pe rnd elementele acestuia cu valoarea cutat x. Sunt necesare cel mult n comparaii n caz de succes (x apare n vector) i exact n comparaii n caz de eec ( x nu apare n vector). n cazul n care vectorul este ordonat cresctor sau descresctor se poate folosi un algoritm de cutare mult mai eficient avnd complexitatea log2n. Acest algoritm se numete algoritmul de cutare binar i poate fi descris astfel : iniial se consider tot vectorul A i se compar x cu elementul din mijlocul acestuia (fie el a[mij]). Dac x=a[mij], algoritmul se ncheie cu succes; dac x<a[mij], vectorul fiind ordonat, cutarea va continua n prima jumtate, iar dac x>a[mij] cutarea va continua n a doua jumtate. Procedeul se repet pn cnd fie gsim valoarea x, fie nu mai avem secven valid de cutare, adic elemente neverificate. Secvena curent n care se face cutarea elementului x este identificat prin indicele elementului din extrema stng, respectiv indicele elementului din extrema dreapt. Secvena de program este urmtoarea : f=-1; /* x nu a fost gsit n vectorul A */ st=1; dr=n; /* secvena iniial de cutare este ntregul vector A */ while(st<=dr) /* secvena curent de cutare conine cel puin un element */ { mij=(st+dr)/2; /* indicele elementului din mijlocul secvenei de cutare */ if(a[mij]==x) { f=mij; /* memorm poziia n care apare */ break; /* cutare ncheiat cu succes */ } if(x<a[mij]) dr=mij-1; /* cutarea continu n prima jumtate */ else st=mij+1; /* cutarea continu n a doua jumtate */ }

6.3.12 Interclasarea vectorilor


Se consider doi vectori, A cu m elemente i B cu n elemente, ambii ordonai cresctor sau descresctor. A interclasa cei doi vectori nseamn a obine un vector C cu m+n elemente, care conine toate elementele din A i din B, ordonate n acelai mod. Metoda de creare a vectorului rezultat C este foarte simpl: se compar elementul curent din A cu elementul curent din B, n C se introduce spre exemplu cel mai mic dintre ele (la ordonare cresctoare). Dac elementul introdus a fost din vectorul A atunci se avanseaz la urmtorul element din A, altfel se avanseaz la urmtorul element din vectorul B. n momentul n care elementele unui vector sunt epuizate, elementele rmase n cellalt vector sunt copiate direct n vectorul C. Acest algoritm se simplific dac folosim dou santinele care vor face ca cei doi vectori s se epuizeze simultan. O santinel este un element care nu influeneaz valoarea unui rezultat, scopul utilizrii lui fiind numai obinerea unui algoritm mai simplu i mai eficient. n cazul algoritmului de interclasare, vom aduga la sfritul vectorului A o santinel mai mare dect cel mai mare element din B, iar la sfritul vectorului B o santinel mai mare dect cel mai mare element din A. n acest caz, dac presupunem c toate elementele utile din vectorul A au fost deja introduse n vectorul rezultat C, atunci, toate elementele utile din B care nu au fost nc verificate sunt mai mici dect santinela rmas n A i vor fi copiate automat, fr nici-o verificare suplimentar, n vectorul rezultat C. Secvena care realizeaz interclasarea cu santinele este: a[m]=b[n1]+1; /* santinela din A mai mare dect cel mai mare element din B */ b[n]=a[m1]+1; /* santinela din B mai mare dect cel mai mare element din A */ i=1; /* indicele elementului curent din A */ j=1; /* indicele elementului curent din B */ for(k=1; k<=m+n; k++) /* k este indicele elementului curent din C */ if(a[i]<b[j]) /* pentru ordonare cresctoare */ c[k]=a[i++]; /* avansez n vectorul A */

Clasa a IX-a else c[k]=b[j++];

Tablouri /* avansez n vectorul B */

Clasa a IX-a

Tablouri

6.4 Prelucrri elementare ale matricilor


Ca i n cazul tablourilor unidimensionale, se pune problema depirii dimensiunilor maxime specificate n declaraia unui tablou bidimensional (matrice). Matricile sunt de dou tipuri: dreptunghiulare (numrul de linii diferit de numrul de coloane) i ptratice (numrul de linii egal cu numrul de coloane). Pentru matricile dreptunghiulare maniera uzual de declarare i validare a dimensiunilor este urmtoarea : #define MAXLIN 7 /* numrul maxim de linii */ #define MAXCOL 5 /* numrul maxim de coloane */ int a[MAXLIN][MAXCOL]; int m,n; /* numrul real de linii, respectiv coloane */ cout<<numarul de linii=; cin>>m; cout<<numarul de coloane=; cin>>n; Pentru o matrice ptratic maniera uzual de declarare i validare a dimensiunii este urmtoarea: #define DIM 8 int a[DIM][DIM]; int n; /* dimensiunea real a matricii */ .. cout<<dimensiunea matricii=; cin>>n; Este bine de tiut c memorarea matricilor se face pe linii (ordine lexicografic), adic compilatorul rezerv pentru matrice o zon contigu de memorie de dimensiune MAXLIN*MAXCOL*sizeof(tip), unde tip este tipul de baz al matricii, adic tipul elementelor componente. Primele MAXCOL locaii din aceast zon sunt pentru elementele din prima linie (de indice 0), chiar dac nu toate sunt folosite, urmtoarele MAXCOL locaii sunt rezervate pentru elementele din a doua linie (de indice 1) etc. Practic, n memorie, matricea este liniarizat sub forma unui vector cu MAXLIN*MAXCOL elemente, unele din aceste elemente putnd fi neutilizate. Raionamentul se aplic identic pentru matricile ptratice, numrul de elemente fiind DIM*DIM (dimensiunea matricii). n continuare, vom considera cazul general al matricilor dreptunghiulare, secvenele de instruciuni trebuind modificate corespunztor pentru a lucra corect cu matricile ptratice ( m=n=dimensiunea matricii).

6.4.1 Citirea elementelor unei matrici


Deoarece memorarea matricilor se face pe linii, elementele se citesc pe linii, adic indicele de coloan se modific mai rapid dect indicele de linie. Secvena corespunztoare de program este urmtoarea: for(i=1;i<=m;i++) /* indicele de linie */ for(j=1;j<=n;j++) /* indicele de coloan */ { cout<<a[<<i<<,<<j<<]=; cin>>a[i][j]; }

6.4.2 Tiprirea elementelor unei matrici


Dac dorim s tiprim matricea cu valorile de pe aceeai coloan aliniate spre exemplu la dreapta, vom folosi facilitile de aliniere i de specificare a numrului de zecimale (pentru valori reale) ale funciei cout<<. Spre exemplu, tiprirea unei matrici de numere reale cu valorile aliniate la dreapta i trei zecimale exacte se poate realiza cu secvena: for(i=1;i<=m;i++) { for(j=1;j<=n;j++) cout<<a[i][j]<< ; /* tiprete elementele de pe o linie */ cout<<endl; /* trece la o linie nou */ }

Clasa a IX-a

Tablouri

6.4.3 Determinarea elementului maxim/minim


Metoda uzual este urmtoarea: se iniializeaz maximul/minimul cu primul element din matrice ( a[0][0]), se compar apoi pe rnd cu toate elementele din matrice i se reine valoarea mai mare/mai mic. Secvena de instruciuni care realizeaz acest lucru este urmtoarea: maxim=a[1][1]; /* minim=a[1][1] */ for(i=1;i<=m;i++) for(j=1;j<=n;j++) if(maxim<a[i][j]) /* minim>a[i][j] */ maxim=a[i][j]; /* minim=a[i][j] */

6.4.4 Identificarea elementelor specifice unei matrici ptratice


n cazul matricilor ptratice se identific urmtoarele elemente specifice: diagonala principal ( DP), diagonala secundar (DS), jumtatea superioar (JS) i jumtatea inferioar (JI). Diagonalele corespund (geometric) diagonalelor unui ptrat. Diagonala principal cuprinde elementele din colul stnga sus pn n colul dreapta jos, adic mulimea: DP={aij| i=j, i=1,..n}={ a11, a22, .,ann} unde n este dimensiunea real a matricii. Diagonala secundar cuprinde elementele din colul dreapta sus pn n colul stnga jos, adic mulimea: DS={aij|i=1,n , j=n,n-1,n-2,1, i+j=n+1}={a1n, a2n-1,..,an1} Jumtatea superioar cuprinde elementele de deasupra diagonalei principale (fr cele de pe DP), adic mulimea: JS={aij | i=1,n-1 , j=i+1,,n} Jumtatea inferioar cuprinde elementele de sub diagonala principal (fr elementele de pe DP), adic mulimea: JI={aij | i=2,.n , j=1,i-1} Un element a[i][j] din JS are drept simetric elementul a[j][i] din JI. Astfel, transpusa unei matrici ptratice (matricea care are liniile drept coloane i reciproc) se poate genera uor interschimbnd toate elementele din JS cu simetricele lor din JI aa cum se vede n secvena de mai jos: for(i=1; i<=n-1; i++) for(j=i+1; j<=n; j++) { aux=a[i][j]; a[i][j]=a[j][i]; a[j][i]=aux; }