Sunteți pe pagina 1din 9

Tablouri. Particularizare - vectori.

Aplicaii


Obiective
n urma parcurgerii acestui laborator, studentul va fi capabil:
s declare i s iniializeze vectori (din declaraie i prin structuri iterative)
s implementeze algoritmi simpli de sortare i cutare pe vectori
s foloseasc practici recunoscute i recomandate pentru scrierea de cod surs care
implic lucrul cu vectori
s recunoasc i s evite erorile comune de programare legate de aceste structuri
s aplice lucrul cu vectori pentru rezolvarea unor probleme cu dificultate medie
Noiuni teoretice
Vectori
Printr-un vector se nelege o colecie liniar i omogen de date. Un vector este liniar
pentru c datele(elementele) pot fi accesate n mod unic printr-un index. Un vector este, de
asemenea, omogen, pentru c toate elementele sunt de acelai tip. n limbajul C, indexul
este un numr ntreg pozitiv i indexarea se face ncepnd cu 0.
Declaraia unei variabile de tip vector se face n felul urmtor:
<tip_elemente> <nume_vector>[<dimensiune>];
De exemplu, avem urmtoarele declaraii de vectori:
int a[100];
float vect[50];

#define MAX 100
...
unsigned long numbers[MAX]
Este de remarcat c vectorul este o structur static: dimensiunea acestuia trebuie s
fie o constant la compilare i nu poate fi modificat n cursul execuiei programului. Astfel,
programatorul trebuie s estimeze o dimensiune maxim pentru vector, i aceasta va fi o
limitare a programului. De obicei, se folosesc constante simbolice (ca n ultimul exemplu)
pentru aceste dimensiuni maxime, pentru ca ele s poat fi ajustate uor la nevoie. De
asemenea, n cadrul unei declaraii, se pot iniializa cu valori constante componente ale
vectorului, iar n acest caz, dimensiunea vectorului poate rmne neprecizat (compilatorul
o va determina din numrul elementelor din list). De exemplu:
int a[3] = {1, 5, 6}; /* Toate cele 3 elemente sunt initializate */
float num[] = {1.5, 2.3, 0.2, -1.3}; /* Compilatorul determina dimensiunea -
4 - a vectorului */
unsigned short vect[1000] = {0, 2, 4, 6}; /* Sunt initializate doar primele 4
elemente */
n cazul special n care specificm dimensiunea i doar un singur element la initializare,
primul element va fi cel specificat, iar toate celelalte elemente ale vectorului vor fi
iniializate la 0:
char string[100] = {97}; /* Sirul va fi initializat cu: 97 (caracterul 'a')
pe prima poziie i 99 de 0 */
Este important de remarcat faptul c elementele neiniializate pot avea valori oarecare. La
alocarea unui vector, compilatorul nu efectueaz nici un fel de iniializare i nu furnizeaz
nici un mesaj de eroare dac un element este folosit nainte de a fi iniializat. Un program
corect va iniializa, n orice caz, fiecare element nainte de a-l folosi. Elementele se
acceseaz prin expresii de forma <nume_vector>[<indice>]. De exemplu, putem avea:
char vect[100];
int i = 90;
vect[0] = 1;
vect[5] = 10;
vect[i] = 15;
vect[i + 1] = 20;
Stil de programare
Exemple de programe
Citirea unui vector de intregi de la tastatura:
int main(void) {
int a[100], n, i; /* vectorul a are maxim 100 de intregi */

scanf("%d", &n); /* citeste nr de elemente vector */

for(i = 0; i < n; i++) {
scanf("%d", &a[i]); /* citire elemente vector */
}

for(i = 0; i < n; i++) {
printf("%d ", a[i]); /* scrie elemente vector */
}

return 0;
}
Generarea unui vector cu primele n numere Fibonacci:
#include <stdio.h>
int main(void) {
long fib[100] = {1, 1};
int n, i;

printf("n = ");
scanf("%d", &n);

for(i = 2; i < n; i++) {
fib[i] = fib[i - 1] + fib[i - 2];
}
for(i = 0; i < n; i++) {
printf("%ld ", fib[i]);
}

return 0;
}
Dei modul n care se manifest erorile din program poate fi surprinztor i imprevizibil,
cauzele care produc aceste erori sunt destul de comune i pot fi grupate n mai multe
categorii. Cteva dintre acestea sunt prezentate mai jos
Depirea limitelor indicilor (index out of bounds) este o eroare frecvent, ce poate
duce la blocarea programului sau a sistemului i poate fi evitat prin verificarea
ncadrrii n intervalul valid.
Indici folosii greit n bucle imbricate (index cross-talk). Sunt multe cazuri n care pe
un nivel al buclei se folosete, de exemplu vect[i], i pe nivelul imbricat vect[j],
cnd de fapt se dorea folosirea lui i. Mare atenie i n astfel de cazuri!
Definii dimensiunile prin constante i folosii-le pe acestea n locul tastrii explicite a
valorilor n codul surs. Astfel vei evita neconcordane n cod dac dorii ulterior s
modificai dimensiunile i uitai s modificai peste tot prin cod.
#define MAX 100

int vect[MAX];
va fi de preferat n locul lui
int vect[100];
Verificai c indicii se ncadreaz ntre marginile superioar i inferioar a intervalului de
valori valide. Acest lucru trebuie n general fcut n cazul n care datele provin dintr-o surs
extern: citite de la tastatur sau pasate ca parametri efectivi unei funcii, de exemplu.
Exemplu:
// program care citete un index i o valoare, i atribuie valoarea
elementului din vector care se gsete la poziia respectiv
#include <stdio.h>
#define N 10

int main(void) {
int i, val;
int v[N];

scanf("%d%d", &i, &val);

/* !!! Verific daca indexul este valid */
if (i >= 0 && i < 10) {
v[i] = val;
} else {
printf("Introduceti un index >= 0 si < 10\n");
}

return 0;
}
Folosii comentarii pentru a explica ce reprezint diverse variabile. Acest lucru v va ajuta
att pe voi s nu ncurcai indici, de exemplu, ct i pe ceilali care folosesc sau extind codul
vostru.
Exemplu:
#include <stdio.h>
#define N 100

int main(void) {
int v[N];
int i, j; /* indecsii elementelor ce vor fi interschimbate */
int aux; /* variabila ajutatoare pentru interschimbare */

/*... initializari */

/* Interschimb */
aux = v[i];
v[i] = v[j];
v[j] = aux;

return 0;
}
Aplicaii cu vectori
Cutri
Cutare secvenial
Cnd avem de a face cu un vector nesortat (i nu numai n acest caz), cea mai simpl
abordare pentru a gsi o valoare, este cutarea secvenial. Cu alte cuvinte, se compar, la
rnd, fiecare valoare din vector cu valoarea cutat. Dac valoarea a fost gsit, cutarea
se poate opri (nu mai are sens s parcugem vectorul pn la capt, dac nu se cere acest
lucru explicit).
Exemplu:
#define MAX 100

...

int v[MAX], x, i;

/* initializari */
...

for (i = 0; i < MAX; i++) {
if (x == v[i]) {
printf("Valoarea %d a fost gasita in vector\n", x);
break;
}
}

printf("Valoarea %d nu a fost gasita in vector\n", x);
...
Cutare binar iterativ
Dac vectorul pe care se face cutarea este sortat, algoritmul mai eficient de folosit n acest
caz este cutarea binar. Presupunem c vectorul este sortat cresctor (pentru vectori
sortai descresctor, raionamentul este similar). Valoarea cutat, x, se compar cu
valoarea cu indexul N/2 din vector, unde N este numrul de elemente. Dac x este mai mic
dect valoarea din vector, se caut n prima jumtate a vectorului, iar dac este mai mare,
n cea de-a doua jumtate. Cutarea n una dintre cele dou jumti se face dup acelai
algoritm. Conceptual, cutarea binar este un algoritm recursiv, dar poate fi implementat la
fel de bine ntr-un mod iterativ, folosind indecii corespunztori bucii din vector n care se
face cutarea. Aceti indeci se modific pe parcursul algoritmului, ntr-o bucl, n funcie de
comparaiile fcute. Evoluia algoritmului este ilustrat n imaginea de mai jos.
Pseudocodul pentru cutarea binar:
int binarySearch(int v[N], int find) {
int low = 0, high = N - 1;

while (low <= high) {
int x = (low + high) / 2;

if (v[x] == find) {
// Am gasit elementul, returnam pozitia sa
return x;
}

if (v[x] < find) {
// Elementul cautat este mai mare decat cel curent, ne mutam in
jumatatea
// cu elemente mai mari
low = x + 1;
} else {
// Elementul cautat este mai mic decat cel curent, ne mutam in
jumatatea
// cu elemente mai mici
high = x - 1;
}
}

// Elementul nu a fost gasit
return -1;
}
Sortri
Bubble Sort
Metoda bulelor este cea mai simpl modalitate de sortare a unui vector, dar i cea mai
ineficient. Ea funcioneaz pe principiul parcurgerii vectorului i comparrii elementului
curent cu elementul urmtor. Dac cele dou nu respect ordinea, sunt interschimbate.
Aceast parcurgere este repetat de suficiente ori pn cnd nu mai exist nici o
interschimbare n vector.
Sortarea prin selecie
Sortarea prin selecie ofer unele mbuntiri n ceea ce privete complexitatea, ns este
departe de a fi considerat un algoritm eficient. Presupunnd c se dorete sortarea
cresctoare a vectorului, se caut minimul din vector, i se interschimb cu primul element
- cel cu indexul 0. Apoi se reia acelai procedeu pentru restul vectorului. Motivul pentru care
algoritmul de sortare prin selecie este mai eficient este acela c vectorul n care se caut
minimul devine din ce n ce mai mic, i, evident, cutarea se face mai repede la fiecare pas.
Studiul unor algoritmi mai avansai de sortare, precum i studiul complexitii lor nu
constituie obiectul acestui laborator. Acestea se vor relua mai detaliat n cadrul altor cursuri.
Pentru mai multe informaii legate de cutri i sortri, se pot consulta referinele.
Exerciii de Laborator
1. [1.5p] Se consider un vector x cu n < 100 componente. S se determine:
a. valoarea componentei minime;
b. poziia componentei maxime;
c. media aritmetic a componentelor;
d. numrul componentelor mai mari ca media aritmetic.
Dimensiunea vectorului, n, i elementele vectorului se citesc de la tastatur (cu
scanf()).
Programul se va testa cu fiierul de intrare de mai jos (in.txt), utiliznd
comanda:
./pb1 <in.txt >out.txt

Fiierul de intrare, in.txt:

50
95 59 50 15 53 44 91 7 86 16 73 57 27 54 97 62 59 5 98 61 99 22 22
84 17 96 13 96 5 50 62 53 61 12 68 14 8 59 74 95 27 47 52 54 53 2
68 13 7 19

Fiierul de ieire asociat, out.txt:
min = 2
poz_max = 20
ma = 49.22
gt_ma = 30
2. [2p] S se implementeze sortarea prin selecie pe un vector citit de la tastatur.
3. [2p] Citindu-se doi vectori A i B s calculeze diferena lor (elementele care sunt n A,
dar nu sunt n B).
Exemplu:
4. a = [6, 4, 2, 1, 7]
5. b = [4, 6, 3, 1]
6.
Rezultat = [2, 7]
7. [2p] Avnd un vector de N elemente s se determine subsecvena sa de suma
maxim. O subsecven a unui vector reprezint un subir de elemente ale acestuia
aflate pe poziii consecutive.
Exemplu:
8. 4
9. 3 -4 2 3 // raspuns 5
10. 5
11. -3 7 -3 4 // raspuns 8
12. 3
-1 -2 -3 // raspuns -1
13. [2.5p] Se citete de la tastatur un vector V sortat crescator de lungime N i apoi un
ir de perechi (x, y)de numere naturale terminat cu -1. Pe msura citirii acestor
numere, s se determine eficient elementele din V cuprinse ntre x i y (x < y).
Exemplu:
14. 5
15. 2 10 20 50 80
16. 5 15
17. 10 // output
18. 10 20
19. 10 20 // output
20. 27 91
21. 50 80 // output
-1

BONUS:
1. [2p] Implementai adunarea a dou numere mari. Un numr mare va fi reprezentat
ca un vector A, unde A[0] va fi numrul de cifre ale numrului, iar elementul A[i] va
conine a i-a cea mai nesemnificativ cifr.
Exemplu:
9420 // -> A[] = {4, 0, 2, 4, 9}
845 // -> B[] = {3, 5, 4, 8}
// Suma
10265 // -> C[] = {5, 5, 6, 2, 0, 1}

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