Vectori
Pentru a crea și o motivație a învățării structurii pe care o vom prezenta, vom porni cu un enunț de problemă:
Se cere de la tastatură un număr n, apoi n numere naturale. Se consideră 1 ≤ n ≤ 1000 iar valorile de
maxim 9 cifre. Avem două cerințe:
a) Determinați cea mai mare valoare dintre cele n;
b) Determinați câte dintre valorile citite sunt egale cu ultima introdusă;
Pentru cerința a) rezolvarea este cunoscută (și recomandată) folosind câteva variabile simple, chiar în
momentul citirii datelor:
#include <iostream<
using namespace std;
int n, maxim, x, i;
int main () {
cin>>n;
maxim = -1;
for (i=1;i<=n;i++) {
cin>>x;
if (x > maxim)
maxim = x;
}
cout << maxim;
}
Aici observăm că toate numerele au fost citite (și memorate) în aceeași variabilă și imediat după citire am folosit valoarea comparând-o cu maximul.
Pentru rezolvarea celei de-a doua cerințe observăm că în momentul citirii ultimei valori este necesar să cunoaștem valoarea celorlalte, citite înainte. Deci avem nevoie, în acest caz, ca la final să avem memorate toate numerele introduse. Cu modul de folosire a variabilelor utilizat până acum nu am putea rezolva. Ar apărea întrebări de genul: cum declar până la 1000 de variabie? Cum le denumesc? etc.
Limbajele de programare oferă soluții pentru astfel de probleme prin folosirea tablourilor de memorie./p>
Un tablou de memorie este format din mai multe variabile, toate de același tip, care pot fi accesate folosind numele tabloului și un număr (sau, vom vedea ulterior, mai multe numere) ce reprezintă poziția în tablou.
Exemplu:
Name | Description | |
---|---|---|
int x; | O singură variabilă de tip int. | |
int v [ 100 ]; | 100 de variabile de tip int. | |
Din exemplu deducem și modul general de a declara tablouri:
tip nume[ dimensiune ];
- tip reprezintă tipul comun al tuturor elementelor tabloului; poate fi folosit orice tip al limbajului;
- nume reprezintă identificatorul cu care ne referim la variabila compusă v;
- dimensiune trebuie să fie o expresie constantă (adică poate conține constante și eventual operații cu ele); această valoare reprezintă numărul de elemente (de variabile de tipul tip) ale tabloului;
Componentele tabloului se accesează în program prin construcții de forma nume [ poziție ], unde poziție reprezintă o expresie de tip întreg, nu neapărat constantă, și a cărei valoare să fie, în momentul accesării, cuprinsă între 0 and dimensiune - 1.
Așadar, pozițiile (indicii) elementelor unui tablou sunt numere cu valori cuprinse între 0 și dimensiune-1.
Componentele unui tablou sunt variabile obișnuite de tipul comun și pot fi folosite în orice loc este permisă o variabilă de tipul respectiv.
Fie declarările:
int v [ 100 ]; int i, x; |
Description: |
|
---|---|---|
cin >> v [ 3 ]; | Corect, ce cere de la tastatură o valoare și se memorează în cea de-a patra componentă a tabloului (numerotarea începe de la 0). | |
v [ 2 ] = 2 * v [ 3 ]; | Este o atribuire corectă în care intervin două componente ale tabloului. Cea din stânga este variabila a cărei valoare se va modifica. | |
i = 2;
cin >> x; v [ i ] += 10 * x; |
Aici intervin trei variabile de tip int. Observăm că putem avea o
componentă a tabloului în stânga unei atribuiri (în ea se poate memora ceva ca în orice altă variabilă de tip int). |
|
Pentru o mai bună înțelegere a ceea ce reprezintă un vector, ne putem gândi că o declarație int v[2] este totuna ca și cum am fi declarat int a , b;
Acum este momentul să vedem cum folosim efectiv un vector într-un program. Mai concret, vom rezolva punctul b) al problemei enunțate.
Vom urma pașii:
- declarăm un vector care să poată memora cel puțin 1000 de elemente de tip int;
- citim de la tastatură pe n și cele n numere și, foarte important, le memorăm în vector;
- parcurgem iarăși vectorul pentru a compara elementele sale cu ultimul citit, aflând astfel rezultatul.
#include <iostream>
using namespace std;
int n, i, cnt;
int v[1001];
int main () {
cin >> n;
for (i = 1; i <= n;i++) {
cin >> v[i];
}
cnt = 0;
for (i = 1; i<= n;i++)
if (v[n] == v[i])
cnt++;
cout << cnt;
}
Observații:
- structura potrivită pentru a traversa element cu element vectorul este for;
- am decis să folosim componentele aflate pe pozițiile 1, 2, ..., n; astfel componenta de pe poziția 0 rămâne nefolosită; tot așa rămân nefolosite și componentele de pe pozițiile n+1, n+2 ... 1000 (am declarat tabloul cu dimensiunea 1001, deci componentele sale disponibile sunt pe pozițiile 0, 1, ..., 1000).
- Faptul că folosim componente de pe pozițiile 1..n (și nu 0..n-1) este pentru a obișnui mai rapid pe programatorii începători cu folosirea tablourilor.
- Avem pentru un tablou o dimensiune fizică (1001, cea declarată) și una logică (n – numărul de componente folosite efectiv);
Să analizăm programul de mai sus. Prima structură repetitivă face ca indicele i să ia pe rând valori ale fiecărei poziții din v la care se află elemente unde dorim să memorăm valorile introduse. Secvența este echivalentă cu:
cin >> v [ 1 ]; cin >> v [ 2 ]; cin >> v [ 3 ]; … cin >> v [ n ]; (iar noi fără să folosim o repetiție nu putem obține acest efect de puncte puncte).
După terminarea acestei repetiții numerele introduse de noi se află toate în memorie, fiecare în câte o
componentă a tabloului, deci putem să le folosim în alte scopuri.
Traversăm acum iarăși elementele tabloului, testând prin comparație care sunt egale ca valoare cu cel stocat
pe ultima poziție.
Putem concluziona: în general, elementele unui vector, aflate înre pozițiile p1 și p2 (cu p1 ≤ p2) se pot
vizita cu o secvență de forma:
for (indice = p1; indice <= p2; indice++)
accesăm elementul v [ index ];
Probleme rezolvate
1. Se cere de la tastatură un număr n (de maxim 4 cifre) și apoi n numere întregi cu maxim 9 cifre. Să se
determine:
a) Memorarea numerelor citite într-un vector pe poziții de la 1 la n;
b) Suma valorilor pare (dacă nu sunt valori pare se va afișa 0);
c) Suma valorilor de pe poziții pare;
d) Numărul valorilor nule;
e) Maximul elementelor negative (decă nu sunt valori negative se va afișa 0);
f) Media aritmetică a valorilor de două cifre (dacă nu sunt astfel de valori se va afișa 0);
Rezolvare:
Problema este un exercițiu bun pentru aplicarea unor operații de bază asupra unui șir de numere care are elementele stocate în memorie. Fiecare cerință poate fi rezolvată fără a fi necesară folosirea unu vector, dar noi acum o vom face după memorarea elementelor, fiind vorba, pe de o parte de o aplicație didactică, pe de altă parte cerințele pot face parte dintr-o aplicație mai mare care cere memorarea elementelor.
Toate cerințele necesită parcurgerea clasică a unui tablou unidimensional, de exemplu cu un for. Am ales varianta de a rezolva fiecare cerință individual, cu o structură repetitivă separată, dar știm că se putea folosi o singură repetiție pentru toate (chiar în momentul citirii, mai ales că am observat că nu era nevoie de stocatea elementelor).
#include <iostream>
using namespace std;
int n, i, sumaPare, sumaPozitiiPare, z;
int maxim, s, nr;
int v[10001];
/**
I declared the vector to fit
the maximum possible number of components
according to the statement
**/
int main () {
cin >> n;
/// reading the number of inputs
for (i = 1; i <= n; i++) {
cin >> v[i];
}
/// the sum of even values
sumaPare = 0;
for (i = 1; i <= n; i++)
if (v[i] % 2 == 0)
sumaPare += v[i];
cout << sumaPare << "\n";
/// the sum of the values on even positions
sumaPozitiiPare = 0;
for (i = 2; i <= n; i += 2)
sumaPozitiiPare += v[i];
cout << sumaPozitiiPare << "\n";
/** or
for (i = 1; i <= n; i++)
if (v[i] % 2 == 0)
sumaPozitiiPare += v[i];
**/
/// numarul valorilor nule
z = 0;
for (i = 1; i <= n; i++)
if (v[i] == 0)
z++;
cout << z << "\n";
///maximul elementelor negative
maxim = -1000000000;
for (i = 1; i <= n; i++)
if (v[i] < 0 && v[i] > maxim)
maxim = v[i];
if (maxim == -1000000000)
cout << 0 << "\n";
else
cout << maxim << "\n";
///media aritmetica a valorilor de doua cifre
s = 0;
nr = 0;
for( i = 1; i <= n; i++)
if (v[i] > 9 && v[i] < 100) {
s += v[i];
nr ++;
}
if (nr == 0)
cout << 0;
else
cout << s*1.0/nr;
}
2. Se citesc elementele unui vector despre care se știe că se dau distincte. Afișați-le pe cele aflate între valoarea maximă și valoarea minimă
Rezolvare:
#include <iostream>
using namespace std;
int v[1001];
int n, i, maxim, minim, pmaxim, pminim, aux;
int main() {
cin >> n;
for(int i = 1; i <= n; i++){
cin >> v[i];
}
minim = v[1];
maxim = v[1];
pminim = 1;
pmaxim = 1;
for(int i = 2; i <= n; i++){
if(v[i] < minim){
minim = v[i];
pminim = i;
}
if(v[i] > maxim) {
maxim = v[i];
pmaxim = i;
}
}
if(pmaxim &st; < pminim) {
aux = pmaxim;
pmaxim = pminim;
pminim = aux;
}
for(int i = pminim; i <= pmaxim; i++)
cout << v[i] << ' ';
return 0;
}