Algoritmi și structuri de date
Elevii învață să conceapă și să reprezinte algoritmi folosind pseudocod și scheme logice, cu accent pe structuri de control.
Evaluarea Națională
Ce este un algoritm și ce proprietăți trebuie să aibă
Un algoritm este o succesiune finită de pași, descriși clar și fără ambiguitate, care rezolvă o problemă pornind de la niște date de intrare și producând date de ieșire. O rețetă de clătite sau instrucțiunile de montaj ale unui dulap sunt algoritmi din viața reală: pași ordonați, pe care îi execuți exact în ordinea dată.
Ca să fie cu adevărat algoritm, o succesiune de pași trebuie să respecte câteva proprietăți — acestea se cer aproape mereu la teste:
- Finitudine — algoritmul se termină după un număr finit de pași. Un program care se învârte la nesfârșit în aceeași buclă nu este un algoritm corect.
- Claritate (determinism) — fiecare pas este precis, fără interpretări. „Adaugă puțină sare” nu e clar; „adaugă 5 grame de sare” este.
- Generalitate — algoritmul rezolvă o clasă întreagă de probleme, nu un singur caz. Un algoritm care adună două numere trebuie să funcționeze pentru orice două numere, nu doar pentru 3 și 7.
- Eficiență — pașii pot fi executați efectiv, într-un timp rezonabil.
Confuzia clasică: elevii cred că datele de intrare sunt obligatorii. Nu este așa — există algoritmi fără date de intrare (de exemplu, afișarea primelor 10 numere pare), dar orice algoritm util produce cel puțin o dată de ieșire, altfel nu am afla niciodată rezultatul.
Pseudocod și scheme logice
Un algoritm poate fi descris în mai multe feluri. Cele două reprezentări studiate în gimnaziu sunt pseudocodul și schema logică.
Pseudocodul este un limbaj intermediar între limbajul natural și un limbaj de programare. Folosește cuvinte-cheie standard:
- citește a, b — preia datele de intrare;
- scrie s — afișează datele de ieșire;
- s ← a + b — instrucțiunea de atribuire: valoarea expresiei din dreapta se memorează în variabila din stânga;
- dacă ... atunci ... altfel — decizie;
- cât timp ... execută — repetare.
Schema logică desenează algoritmul cu blocuri geometrice legate prin săgeți: ovalul marchează început/sfârșit, paralelogramul — citire/scriere, dreptunghiul — calcul/atribuire, iar rombul — o decizie cu două ieșiri (Da/Nu).
Atenție la atribuire: x ← x + 1 este perfect valid și înseamnă „noua valoare a lui x devine vechea valoare plus 1”. Nu este o ecuație matematică! La atribuire, vechea valoare a variabilei se pierde — se suprascrie. De aceea, ca să interschimbi valorile a două variabile a și b, ai nevoie de o a treia variabilă auxiliară: aux ← a, apoi a ← b, apoi b ← aux. Dacă scrii direct a ← b, valoarea inițială a lui a a dispărut pentru totdeauna.
Structura liniară și structura alternativă
Structura liniară (secvențială) este cea mai simplă: pașii se execută unul după altul, exact o dată fiecare, în ordinea scrisă. Exemplu: citește două numere, calculează suma, afișeaz-o. Nicio decizie, nicio repetare.
Structura alternativă (decizia) alege între două drumuri în funcție de o condiție — o expresie care poate fi adevărată sau falsă:
- dacă a > b atunci scrie a altfel scrie b — afișează maximul dintre două numere;
- ramura altfel este opțională: poți avea o decizie care face ceva doar când condiția e adevărată.
Condițiile se construiesc cu operatori relaționali (<, >, =, ≠, ≤, ≥) și pot fi combinate cu operatori logici: și (ambele condiții adevărate), sau (cel puțin una adevărată), nu (neagă condiția).
Două capcane care apar constant în teste:
- și vs sau: „n este divizibil cu 2 și cu 3” înseamnă divizibil cu ambele (adică cu 6); „divizibil cu 2 sau cu 3” e adevărat și pentru 4, și pentru 9. Elevii le inversează frecvent.
- Deciziile imbricate: un dacă poate conține în interior alt dacă. Ramura altfel se leagă întotdeauna de cel mai apropiat dacă fără altfel — citește cu atenție indentarea (spațiile de la începutul rândurilor).
Structurile repetitive: cât timp, pentru, repetă până când
Structurile repetitive (buclele) execută un grup de instrucțiuni de mai multe ori. Există trei forme, iar diferențele dintre ele sunt subiect sigur de test:
- cât timp condiție execută — bucla cu test inițial: condiția se verifică ÎNAINTE de fiecare execuție. Dacă e falsă de la început, corpul buclei nu se execută niciodată (zero execuții posibile).
- pentru i ← 1, n execută — bucla cu contor: se folosește când știm dinainte de câte ori repetăm. Contorul i pornește de la 1 și crește automat cu 1 la fiecare pas, până la n.
- repetă ... până când condiție — bucla cu test final: corpul se execută mai întâi, apoi se verifică condiția. Corpul se execută deci cel puțin o dată, oricum ar fi condiția. Atenție: repetarea continuă cât timp condiția e falsă și se oprește când devine adevărată — exact invers față de cât timp!
Bucla infinită e greșeala fatală: dacă în corpul lui cât timp nu modifici nicio variabilă din condiție, condiția rămâne mereu adevărată și programul nu se mai oprește — se încalcă proprietatea de finitudine.
Cel mai important exercițiu de examen este urmărirea execuției (trace): iei un tabel cu variabilele pe coloane și scrii valoarea fiecăreia după fiecare pas. Metoda pare lentă, dar este singura care garantează răspunsul corect la întrebarea „ce afișează algoritmul?”.
Algoritmi elementari pe care trebuie să îi stăpânești
Câțiva algoritmi apar atât de des încât trebuie recunoscuți din prima privire:
- Suma și numărarea: inițializezi s ← 0 (pentru sumă) sau k ← 0 (pentru numărare) ÎNAINTE de buclă, apoi în buclă aduni sau numeri. Dacă uiți inițializarea, rezultatul e imprevizibil.
- Maxim/minim dintr-un șir de numere citite: inițializezi maximul cu primul număr citit (nu cu 0! — dacă toate numerele sunt negative, 0 ar da un rezultat greșit), apoi compari fiecare număr nou cu maximul curent și îl înlocuiești când găsești unul mai mare.
- Cifrele unui număr: n mod 10 este ultima cifră a lui n, iar n div 10 este numărul fără ultima cifră (div = câtul împărțirii întregi, mod = restul). Ca să prelucrezi toate cifrele, repeți aceste două operații cât timp n ≠ 0. Așa se construiesc suma cifrelor, numărul de cifre și inversul (oglinditul) unui număr: inv ← inv * 10 + n mod 10.
- Paritate și divizibilitate: n e par dacă n mod 2 = 0; n e divizibil cu d dacă n mod d = 0.
Tablourile unidimensionale (vectorii) apar aici la nivel introductiv: un vector este o înșiruire de valori de același tip, numerotate printr-un indice. În loc de 20 de variabile separate, ai v[1], v[2], ..., v[20] și le parcurgi cu o buclă pentru. Prelucrările clasice — suma elementelor, maximul, numărarea celor pare — sunt exact algoritmii de mai sus, aplicați element cu element.
De reținut
- algoritm
- succesiune finită de pași descriși clar, care rezolvă o clasă de probleme pornind de la date de intrare și producând date de ieșire
- finitudine
- proprietatea algoritmului de a se încheia după un număr finit de pași, pentru orice date de intrare valide
- pseudocod
- limbaj de descriere a algoritmilor, intermediar între limbajul natural și un limbaj de programare, cu cuvinte-cheie precum citește, scrie, dacă, cât timp
- schemă logică
- reprezentare grafică a unui algoritm prin blocuri geometrice (oval, paralelogram, dreptunghi, romb) legate prin săgeți
- atribuire
- instrucțiunea v ← expresie, care calculează valoarea expresiei și o memorează în variabila v, suprascriind vechea valoare
- structură alternativă
- structură de control care execută una dintre două secvențe de instrucțiuni, în funcție de valoarea de adevăr a unei condiții
- structură repetitivă cu test inițial
- bucla cât timp: condiția se verifică înaintea fiecărei execuții, deci corpul se poate executa de zero ori
- structură repetitivă cu test final
- bucla repetă–până când: corpul se execută cel puțin o dată, iar repetarea se oprește când condiția devine adevărată
- div și mod
- div este câtul împărțirii întregi, mod este restul; n mod 10 dă ultima cifră a lui n, iar n div 10 elimină ultima cifră
- vector (tablou unidimensional)
- structură de date care memorează mai multe valori de același tip, accesibile printr-un indice
Greșeli frecvente
Greșit: Tratarea atribuirii x ← x + 1 ca pe o ecuație imposibilă sau citirea ei de la stânga la dreapta
Corect: Atribuirea se evaluează întâi în dreapta: se ia vechea valoare a lui x, se adună 1, iar rezultatul devine noua valoare a lui x
Greșit: Confundarea condiției de oprire la repetă–până când cu cea de la cât timp
Corect: Cât timp repetă cât condiția e adevărată; repetă–până când repetă cât condiția e falsă și se oprește când devine adevărată — la transformarea dintr-una în cealaltă condiția se neagă
Greșit: Inițializarea maximului cu 0 la determinarea maximului dintr-un șir de numere
Corect: Maximul se inițializează cu primul element al șirului; dacă toate numerele sunt negative, inițializarea cu 0 dă un rezultat greșit
Greșit: Interschimbarea a două variabile prin a ← b urmat de b ← a
Corect: După a ← b, vechea valoare a lui a s-a pierdut; interschimbarea corectă folosește o variabilă auxiliară: aux ← a, a ← b, b ← aux
Greșit: Uitarea inițializării sumei sau a contorului înaintea buclei
Corect: Înainte de buclă se scrie obligatoriu s ← 0 sau k ← 0; fără inițializare, variabila pornește de la o valoare necunoscută și rezultatul e greșit
Test — 6 întrebări ca la examen
1. Care dintre următoarele proprietăți impune ca un algoritm să se încheie după un număr limitat de pași?
- generalitatea
- claritatea
- finitudinea
- eficiența
Vezi răspunsul
finitudinea. Finitudinea cere ca execuția să se termine după un număr finit de pași. Generalitatea — distractorul tentant — se referă la altceva: algoritmul trebuie să rezolve o întreagă clasă de probleme, nu un singur caz particular.
2. În schema logică, blocul de decizie (cu două ieșiri, Da și Nu) se reprezintă printr-un:
- dreptunghi
- romb
- paralelogram
- oval
Vezi răspunsul
romb. Rombul reprezintă decizia, singurul bloc cu două ieșiri. Paralelogramul — confuzia frecventă — este pentru citire și scriere, dreptunghiul pentru calcule, iar ovalul marchează începutul și sfârșitul.
3. Ce valori au variabilele a și b după secvența: a ← 5; b ← 2; a ← a + b; b ← a - b?
- a = 7, b = 5
- a = 5, b = 2
- a = 7, b = 2
- a = 7, b = 3
Vezi răspunsul
a = 7, b = 5. După a ← a + b, a devine 7. Apoi b ← a - b folosește NOUA valoare a lui a: b = 7 - 2 = 5. Distractorul a = 7, b = 3 apare dacă folosești greșit vechea valoare a lui a (5 - 2 = 3) în loc de cea actualizată.
4. Pentru n = 407, ce afișează algoritmul: s ← 0; cât timp n ≠ 0 execută (s ← s + n mod 10; n ← n div 10); scrie s?
- 740
- 11
- 3
- 47
Vezi răspunsul
11. Algoritmul calculează suma cifrelor: 7 + 0 + 4 = 11. Distractorul 740 corespunde altui algoritm celebru, inversul numărului (inv ← inv * 10 + n mod 10) — cele două șabloane se confundă des pentru că folosesc aceleași operații div și mod.
5. O buclă repetă ... până când (i > 5) are corpul executat cu i pornind de la 10. De câte ori se execută corpul buclei?
- de zero ori
- exact o dată
- de cinci ori
- la infinit
Vezi răspunsul
exact o dată. La repetă–până când, corpul se execută întâi și abia apoi se verifică condiția: cum i = 10 face condiția i > 5 adevărată, repetarea se oprește după prima execuție. Răspunsul „de zero ori” ar fi corect doar pentru o buclă cât timp cu condiție falsă de la start — exact diferența dintre testul final și testul inițial.
6. Un vector v are elementele v[1]=3, v[2]=8, v[3]=1, v[4]=8. Algoritmul: m ← v[1]; pentru i ← 2, 4 execută (dacă v[i] > m atunci m ← v[i]); scrie m. Ce se afișează și ce calculează algoritmul?
- 8; maximul elementelor vectorului
- 1; minimul elementelor vectorului
- 20; suma elementelor vectorului
- 8; ultimul element al vectorului
Vezi răspunsul
8; maximul elementelor vectorului. Este șablonul clasic de maxim: m pornește de la primul element și se înlocuiește ori de câte ori găsim ceva strict mai mare; se afișează 8. Ultimul distractor e tentant pentru că v[4] chiar este 8, dar algoritmul nu afișează ultimul element — dacă vectorul ar fi fost 9, 8, 1, 8, rezultatul ar fi rămas 9.
Deschide varianta interactivă — cu AI care îți explică