De ce contează?
Imaginează-ți că antrenorul îți spune „dă 5 genuflexiuni". Nu-ți scrie pe o foaie „genuflexiune, genuflexiune, genuflexiune, genuflexiune, genuflexiune" — îți spune o singură mișcare și un număr: repet-o de 5 ori. Calculatorul gândește la fel: în loc să-i scrii același pas de o mie de ori, îi dai pasul o dată și îi spui de câte ori să-l repete. Asta este structura repetitivă — bucla.
Intuiția
O buclă repetă aceiași pași de mai multe ori, fără să-i rescrii de fiecare dată. Ai nevoie de două lucruri: un contor (o variabilă i care numără la ce pas ești) și o condiție care spune cât timp continui. La fiecare trecere prin buclă, contorul avansează cu un pas, iar tu faci ceva util cu el — de exemplu îl aduni la un total. Când condiția nu mai e adevărată, bucla se oprește.
Vezi cum funcționează
Urmărește cum se construiește suma 1+2+3+4+5 pas cu pas. Contorul i urcă de la 1, iar acumulatorul s adună mereu valoarea curentă a lui i.
Folosește ← și → ca să pășești prin algoritm câte un pas, sau apasă Redă pentru animație automată. Uită-te cum s crește exact cu valoarea lui i la fiecare pas — niciodată cu altceva.
Vrei suma 1+2+3+4+5. Prima idee: scrii direct s = 1 + 2 + 3 + 4 + 5;. Calculatorul calculează 15 și gata. Pentru n = 5 merge perfect.
Acum ți se cere suma până la n = 1000000. Ar trebui să scrii de mână un milion de termeni: 1 + 2 + 3 + ... — nu încape în program, nu ai termina niciodată de tastat, și oricum nu știi n dinainte (îl citești de la tastatură). Abordarea „scriu fiecare termen" se rupe imediat ce n nu e un număr mic și fix.
Toți termenii arată la fel: „ia numărul curent și adună-l la total". Nu am nevoie să-i scriu pe toți — am nevoie de un contor i care merge de la 1 la n și de un acumulator s la care adaug i la fiecare pas. Un singur pas, repetat, înlocuiește un milion de termeni scriși de mână.
Pun pasul „s = s + i" într-o buclă for care plimbă pe i de la 1 la n. Pentru n = 5, s trece prin 1, 3, 6, 10, 15 și se oprește la 15. Aceeași buclă funcționează neschimbată și pentru n = 1000000.
Algoritmul pas cu pas
Pornim cu acumulatorul gol: s = 0. Apoi i urcă de la 1 la 5, iar la fiecare pas facem s = s + i. Hai să urmărim cum se schimbă cele două variabile.
1 | 0 |
i | s |
i=1 | s=1 |
2 | 1 |
i | s |
i=2 | s=3 |
3 | 3 |
i | s |
i=3 | s=6 |
4 | 6 |
i | s |
i=4 | s=10 |
5 | 10 |
i | s |
i=5 | s=15 |
Observă tiparul: s nu se schimbă haotic, ci crește mereu exact cu valoarea curentă a lui i. Când i depășește n (ajunge la 6), condiția i <= n devine falsă și bucla se oprește. Răspunsul rămâne în s: 15.
for și while sunt două forme ale aceleiași idei. for (i = 1; i <= n; i++) strânge într-un singur rând cele trei lucruri: cu ce pornește contorul, cât timp continuă și cum avansează. Aceeași buclă scrisă cu while arată exact pașii pe care for îi ascunde: i = 1; apoi while (i <= n) { s = s + i; i = i + 1; }. Folosește for când știi de la început câți pași faci.
Implementare C++
#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
int s = 0; // acumulatorul porneste de la 0
for (int i = 1; i <= n; i++) {
s = s + i; // adaugam numarul curent la total
}
cout << s << endl; // pentru n = 5 afiseaza 15
return 0;
}Aceeași logică cu while, ca să vezi pașii ascunși de for:
int s = 0;
int i = 1; // pornim contorul
while (i <= n) { // cat timp nu am depasit n
s = s + i; // adunam
i = i + 1; // AVANSAM contorul (nu uita asta!)
}
// pentru n = 5, s ajunge 15Complexitate
| Caz | Timp | Spațiu |
|---|---|---|
| Orice caz | O(n) | O(1) |
Facem un singur pas pentru fiecare valoare de la 1 la n, deci n operații — de aici O(n) timp. Folosim doar două variabile (s și i), oricât de mare ar fi n, deci O(1) spațiu. De asta bucla câștigă: aceeași n operații funcționează la fel de curat pentru n = 5 ca pentru n = 1000000, fără să rescrii nimic.
Trei capcane clasice ale buclelor:
- Buclă infinită. Dacă în varianta
whileuiții = i + 1, contorul rămâne mereu 1, condițiai <= nrămâne mereu adevărată și programul rulează la nesfârșit. Regulă: oricewhiletrebuie să aibă un pas care, în timp, face condiția falsă. - Off-by-one.
i <= nadună și termenuln;i < nse oprește mai devreme și ratează ultimul termen. Pentrun = 5,i < ndă1+2+3+4 = 10, nu15. Verifică mereu dacă vrei să incluzi sau nu ultima valoare. - Acumulator neinițializat. Dacă scrii
int s;fără= 0,spornește de la o valoare aleatoare din memorie, iar rezultatul e un număr aiurea. Acumulatorul de sumă pornește mereu de la0.