Ce este un sir?
Un sir (numit si vector sau tablou) este o colectie de mai multe valori de acelasi tip, stocate impreuna sub un singur nume. In loc sa cream zeci de variabile separate, punem toate valorile intr-un singur sir si le accesam prin pozitia lor.
Imagineaza-ti un tren cu vagoane numerotate. Fiecare vagon poate contine o valoare (un numar), iar trenul intreg are un singur nume. Daca trenul se numeste "note", vagonul 1 contine prima nota, vagonul 2 contine a doua nota, si asa mai departe. In loc sa dai fiecarui vagon un nume separat, le accesezi prin numarul lor de ordine.
Exemplu: Sirul "note" cu 5 elemente
In viata reala, sirurile sunt peste tot. Lista de note dintr-un catalog este un sir. Temperaturile pe parcursul unei saptamani (7 valori) formeaza un sir. Preturile produselor dintr-un cos de cumparaturi sunt un sir. Scorurile jucatorilor intr-un clasament sunt un sir. Practic, orice colectie de date de acelasi tip poate fi reprezentata ca un sir.
Termenul "sir" vine din matematica, unde un sir de numere este o succesiune ordonata de valori. In informatica, sirul mai este numit si vector (un termen mai tehnic) sau tablou unidimensional (array in engleza). Toate aceste denumiri se refera la acelasi concept: o colectie de valori accesibile prin pozitia lor.
Indexul - Adresa elementului
Fiecare element din sir are o pozitie numita index (sau indice). Indexul este un numar care ne spune exact unde se afla elementul in sir. Fara index, nu am sti care element vrem sa accesam - ar fi ca si cum ai cauta un apartament intr-un bloc fara sa stii numarul.
Gandeste-te la indexul unui sir ca la numarul apartamentului dintr-un bloc. Daca spui "apartamentul 3", stii exact unde sa mergi. La fel, daca spui "elementul de pe pozitia 3 din sirul v", stii exact ce valoare sa cauti. Indexul este adresa unica a fiecarui element din sir.
Sir cu indexi de la 1 la 5:
Elementul de la indexul 2 are valoarea 23
Este esential sa nu confunzi indexul (pozitia) cu valoarea (continutul). In exemplul de mai sus, la indexul 2 gasim valoarea 23. Indexul 2 ne spune unde sa cautam, iar 23 ne spune ce gasim acolo. Aceasta distinctie este fundamentala si o vei folosi la fiecare problema cu siruri.
In pseudocodul pe care il folosim, indexarea incepe de la 1 (primul element este pe pozitia 1). In unele limbaje de programare reale (precum C, Java, Python), indexarea incepe de la 0 (primul element este pe pozitia 0), dar la acest nivel vom folosi indexarea de la 1, care este mai intuitiva si corespunde modului natural de a numara.
v cu n elemente este v[0], iar ultimul este v[n-1]. Cand vei implementa exercitiile in Code::Blocks, va trebui sa convertesti: indexul 1 din pseudocod corespunde lui v[0] in C/C++, indexul 2 corespunde lui v[1], si asa mai departe. Profesorul va indica aceasta conversie la momentul implementarii practice.
Notatia elementelor
Pentru a accesa un element din sir, scriem numele sirului urmat de indexul in paranteze drepte . Aceasta notatie ne permite sa specificam exact care element ne intereseaza:
v [ 3 ] // al treilea element
v [ i ] // elementul de pe pozitia i (variabila)
Daca v = [10, 20, 30, 40, 50], atunci:
v[1] = 10, v[2] = 20, v[3] = 30, v[4] = 40, v[5] = 50
Observa ca indexul poate fi si o
variabila
. Cand scriem
v[i]
, nu accesam un element fix, ci elementul de pe pozitia indicata de valoarea curenta a variabilei
i
. Daca i=3, atunci v[i] este de fapt v[3]. Daca i=5, atunci v[i] este v[5]. Aceasta posibilitate de a folosi o variabila ca index este extrem de puternica si este motivul pentru care sirurile functioneaza atat de bine impreuna cu bucla FOR.
Putem folosi si
expresii
ca index. De exemplu,
v[i+1]
accseaza elementul de dupa pozitia curenta, iar
v[i-1]
accseaza elementul de dinaintea pozitiei curente. Aceasta tehnica este utila cand vrem sa comparam un element cu vecinii sai. De exemplu, pentru a verifica daca un element este mai mare decat cel de dinainte:
DACA v[i] > v[i-1]
.
Atentie la o capcana importanta: indexul trebuie sa fie intotdeauna un numar valid, adica sa se afle intre 1 si n (dimensiunea sirului). Daca sirul are 5 elemente, nu poti accesa v[0] sau v[6] - acestea ar fi pozitii inexistente si ar cauza o eroare. Aceasta greseala se numeste depasire de index (index out of bounds) si este una dintre cele mai frecvente erori in programare.
Notatia cu paranteze drepte este standard in majoritatea limbajelor de programare (C, C++, Java, JavaScript, Python). Unele limbaje mai vechi, precum Pascal, folosesc aceeasi notatie, iar altele precum Fortran folosesc paranteze rotunde. In pseudocodul nostru, vom folosi intotdeauna paranteze drepte:
v[i]
.
Declararea si dimensiunea sirului
Cand cream un sir, trebuie sa specificam cate elemente va avea. Aceasta informatie se numeste dimensiunea sirului si este stocata de obicei in variabila n :
// Acum sirul are n pozitii disponibile
// de la v[1] pana la v[n]
Variabila
n
reprezinta
dimensiunea
sirului - numarul total de elemente pe care le poate stoca. Dupa ce stabilim dimensiunea, sirul are pozitii de la
v[1]
pana la
v[n]
. De exemplu, daca n=4, sirul are 4 pozitii: v[1], v[2], v[3] si v[4].
Daca n = 4, sirul are 4 pozitii goale care asteapta valori:
Gandeste-te la dimensiune ca la numarul de locuri dintr-un autobuz. Daca autobuzul are 40 de locuri, poti avea maximum 40 de pasageri. La fel, daca sirul are dimensiunea n=10, poti stoca maximum 10 valori. Dimensiunea trebuie sa fie un numar natural pozitiv (nu poti avea un sir cu 0 sau -3 elemente).
In practica, dimensiunea sirului este de obicei citita de la tastatura (utilizatorul spune cate valori va introduce) sau este o constanta stabilita in algoritm. De exemplu, pentru temperaturile unei saptamani, n=7 (intotdeauna 7 zile). Pentru notele unui elev la o materie, n poate varia (unii elevi au 5 note, altii au 8).
Citirea elementelor
Pentru a popula un sir cu valori, folosim o bucla FOR care citeste fiecare element pe rand. Acesta este sablonul standard de citire pe care il vei folosi in toate problemele cu siruri:
PENTRU i = 1 , n EXECUTA
CITESTE v [ i ]
SFARSIT_PENTRU
La fiecare pas al buclei, variabila
i
ia o noua valoare (1, 2, 3, ... n), si citim un numar pe care il plasam in pozitia curenta
v[i]
. Astfel, primul numar citit merge in v[1], al doilea in v[2], si asa mai departe pana la v[n].
Exemplu: Citim 3 numere: 5, 8, 12
Pasul 1 (i=1): citim 5 → v[1]=5
Pasul 2 (i=2): citim 8 → v[2]=8
Pasul 3 (i=3): citim 12 → v[3]=12
Ordinea citirii este importanta! Primul numar introdus de utilizator ajunge intotdeauna pe prima pozitie, al doilea pe a doua pozitie, si asa mai departe. Daca utilizatorul introduce numerele in alta ordine, sirul va arata diferit. De exemplu, daca introduce 12, 5, 8 in loc de 5, 8, 12, sirul va fi v=[12, 5, 8].
Un detaliu important: intai citim n (dimensiunea), apoi citim cele n elemente. Nu putem citi elementele fara sa stim cate sunt, deoarece bucla FOR are nevoie de valoarea lui n pentru a sti pana unde sa numere. Aceasta ordine (intai n, apoi elementele) este obligatorie si o vei respecta in toate problemele.
Modificarea elementelor
Putem modifica orice element din sir folosind indexul sau, la fel cum am modifica orice variabila obisnuita. Scriem numele sirului cu indexul dorit si ii atribuim o noua valoare:
v [ 3 ] = v [ 1 ] + v [ 2 ] // v[3] devine suma primelor doua
Inainte: v = [10, 20, 30]
Dupa v[2] = 100: v = [10, 100, 30]
Cand modificam un element, doar acel element se schimba - restul sirului ramane neatins. In exemplul de mai sus, v[1] ramane 10 si v[3] ramane 30; doar v[2] s-a schimbat din 20 in 100. Este ca si cum ai schimba continutul unui singur sertar dintr-o comoda - celelalte sertare nu sunt afectate.
Putem folosi si valori calculate. De exemplu,
v[3] = v[1] + v[2]
face ca elementul de pe pozitia 3 sa devina suma primelor doua elemente. Dupa aceasta operatie (cu v[1]=10 si v[2]=100), v[3] devine 10+100=110. Valoarea veche a lui v[3] (care era 30) se pierde definitiv - nu exista "undo" in algoritmi.
O tehnica frecventa este
interschimbarea
a doua elemente (swap). Daca vrem sa schimbam v[1] cu v[2] intre ele, avem nevoie de o variabila auxiliara:
aux = v[1]; v[1] = v[2]; v[2] = aux
. Fara variabila auxiliara, am pierde una dintre valori. Aceasta tehnica este fundamentala in algoritmii de sortare pe care ii vei invata mai tarziu.
Retine: modificarea se aplica imediat si este permanenta . Odata ce schimbi o valoare, cea veche dispare. De aceea, daca ai nevoie de valoarea originala mai tarziu, trebuie sa o salvezi intr-o variabila auxiliara inainte de a o modifica.
Afisarea elementelor
Pentru a afisa toate elementele unui sir, folosim aceeasi tehnica ca la citire - o bucla FOR care parcurge fiecare pozitie si afiseaza valoarea de acolo:
SCRIE ( v [ i ])
SFARSIT_PENTRU
Daca sirul este v = [5, 8, 12] cu n=3, bucla va afisa pe rand: 5, 8, 12. La fiecare pas, contorul i avanseaza, si v[i] se refera la alt element: v[1]=5, v[2]=8, v[3]=12. Este exact aceeasi mecanica ca la citire, doar ca in loc de CITESTE folosim SCRIE.
Putem afisa si informatii suplimentare la fiecare element, de exemplu pozitia si valoarea:
SCRIE("Pozitia ", i, ": ", v[i])
. Acest format este foarte util pentru depanare (debugging) - cand algoritmul nu da rezultatul asteptat, afisand pozitia si valoarea fiecarui element poti identifica rapid unde este problema.
Un sablon complet de citire si afisare arata astfel:
CITESTE n
PENTRU i = 1 , n EXECUTA
CITESTE v [ i ]
SFARSIT_PENTRU
// Afisare
PENTRU i = 1 , n EXECUTA
SCRIE ( v [ i ])
SFARSIT_PENTRU
Acest sablon este "scheletul" pe care il vei construi in toate problemele cu siruri. Citesti datele, le prelucrezi (calculezi ceva), apoi afisezi rezultatele. Prelucrarea se adauga intre citire si afisare sau chiar in timpul parcurgerii.
De ce folosim siruri?
Poate te intrebi: de ce sa folosesc un sir cand pot crea variabile separate? Raspunsul devine evident cand ai multe date. Imagineaza-ti ca trebuie sa stochezi 100 de note - fara siruri, ai nevoie de 100 de variabile cu nume diferite (nota1, nota2, nota3, ... nota100). Cu un sir, ai o singura variabila
note
cu 100 de pozitii.
Avantajele sirurilor:
- Organizare : Toate datele sunt grupate sub un singur nume, ceea ce face codul mai curat si mai usor de inteles
-
Acces prin index
: Poti accesa oricare element direct, scriind numele sirului si indexul sau —
v[i]— fara a fi nevoie sa parcurgi elementele anterioare. Acelasi mecanism se aplica si variabilelor separate, insa la siruri indexul poate fi o variabila sau expresie, ceea ce permite prelucrarea automata in bucle - Prelucrare usoara : Folosind FOR, poti procesa toate elementele cu doar cateva linii de cod
- Flexibilitate : Dimensiunea poate fi stabilita dinamic (citita de la utilizator), nu trebuie sa o stii dinainte
Fara sir: nota1, nota2, nota3, nota4... (100 de variabile!)
Cu sir: note[1], note[2], ... note[100] (un singur sir!)
Cel mai mare avantaj este posibilitatea de a folosi bucla FOR pentru prelucrare. Cu variabile separate, ai trebui sa scrii manual fiecare operatie:
s = nota1 + nota2 + nota3 + ... + nota100
(100 de adunari!). Cu un sir, scrii doar:
PENTRU i=1,100 EXECUTA s=s+note[i]
- trei linii in loc de 100. Aceasta economie creste enorm cu cat ai mai multe date.
Sirurile sunt esentiale pentru a lucra cu liste de date din lumea reala: note scolare, temperaturi meteorologice, preturi, scoruri, masuratori stiintifice, pixeli dintr-o imagine, caractere dintr-un text, si multe altele. Practic, orice aplicatie moderna foloseste siruri intr-o forma sau alta.
Operatii de baza cu siruri
Exista cateva operatii fundamentale pe care le vei face foarte des cu sirurile. Sa le recapitulam pe toate impreuna cu algoritmii lor:
1. Citirea sirului (intai n, apoi elementele):
PENTRU i = 1 , n EXECUTA
CITESTE v [ i ]
SFARSIT_PENTRU
2. Afisarea sirului :
SCRIE ( v [ i ])
SFARSIT_PENTRU
3. Interschimbarea (swap) a doua elemente v[a] si v[b]:
v [ a ] = v [ b ]
v [ b ] = aux
Interschimbarea este ca si cum ai avea doua pahare cu lichide diferite si vrei sa le schimbi intre ele. Ai nevoie de un al treilea pahar gol (variabila auxiliara): torni primul pahar in paharul gol, torni al doilea pahar in primul, si apoi torni paharul gol (care contine lichidul original) in al doilea pahar.
Aceste trei operatii formeaza baza pe care vei construi algoritmi din ce in ce mai complecsi. In lectiile urmatoare vei invata sa parcurgi siruri, sa calculezi suma si media, sa gasesti maximul si minimul, si sa combini toate aceste tehnici intr-un proiect complet.
Sablonul complet de lucru cu siruri
Sa punem totul cap la cap. Orice problema cu siruri urmeaza un sablon general cu patru etape. Acest sablon este "reteta" pe care o vei aplica de fiecare data:
CITESTE n
PENTRU i = 1 , n EXECUTA
CITESTE v [ i ]
SFARSIT_PENTRU
// ETAPA 2: Prelucrarea (calculul)
// Aici vine algoritmul specific problemei
// (suma, media, maxim, minim, etc.)
// ETAPA 3: Afisarea rezultatelor
SCRIE ( rezultat )
Etapa 1 (citirea) este intotdeauna aceeasi: citesti n, apoi citesti n elemente intr-o bucla FOR. Etapa 2 (prelucrarea) variaza in functie de problema - aici vei aplica algoritmii specifici pe care ii vei invata in lectiile urmatoare. Etapa 3 (afisarea) prezinta rezultatele utilizatorului.
De exemplu, daca problema cere sa afisezi elementele sirului in ordine inversa, etapa 2 ar fi o parcurgere de la n la 1:
PENTRU i = n, 1, -1 EXECUTA SCRIE(v[i])
. Daca problema cere suma elementelor, etapa 2 ar fi algoritmul de suma pe care l-ai invatat in lectia anterioara, aplicat pe elementele sirului.
Retine acest sablon - il vei folosi in fiecare lectie si la fiecare problema. Cu cat il exersezi mai mult, cu atat va deveni mai natural. La inceput poate parea mecanic, dar in scurt timp vei scrie citirea si afisarea sirului din reflexe, concentrandu-te doar pe algoritmul specific problemei.
Un sfat final: cand rezolvi o problema cu siruri, incepe intotdeauna prin a scrie sablonul de citire (etapa 1). Apoi gandeste-te la prelucrare (etapa 2). La final, adauga afisarea (etapa 3). Aceasta abordare structurata te va ajuta sa nu uiti niciun pas si sa organizezi algoritmul corect.
Exercitii practice
Exercitiul 1 (Nivel minim) - Analiza siruri
Daca v = [5, 12, 8, 3, 20], raspunde la urmatoarele intrebari. Justifica fiecare raspuns.
- Ce valoare are v[4]? Dar v[1]?
- Care este dimensiunea sirului (n)?
- Ce valoare va avea v[3] dupa instructiunea v[3] = v[1] + v[2]?
- Care este cel mai mare element al sirului? La ce indice se afla?
Raspunde numerotat: 1. ... 2. ... 3. ... 4. ...
Sfat: deseneaza sirul pe caiet cu casute si indecsi numerotati de la 1. Citeste fiecare valoare pe rand si compara-o cu cel mai mare numar gasit pana atunci.
Exercitiul 2 (Nivel standard) - Mini-proiect: Citire, modificare si afisare
Scrie algoritmul complet care: (1) citeste un sir de n numere, (2) inmulteste fiecare element cu 2, (3) afiseaza sirul modificat. Apoi, adauga o functionalitate care afiseaza sirul si in ordine inversa.
Cerinte obligatorii:
⭐ Bonus (pentru nota maxima):
- Interschimba primul element cu ultimul si afiseaza rezultatul
- Afiseaza pozitia si valoarea fiecarui element in formatul "Pozitia 1: valoare 10"
- Calculeaza cate elemente din sirul modificat sunt mai mari decat 20
Scrie algoritmul pe caiet, apoi verifica-l cu exemplul: n=4, elemente: 3, 7, 1, 5.
Exercitiul 3 (Nivel performanta) - Compunere
Cerinta: Scrie un text de 8-10 randuri in care explici diferenta dintre index si valoare intr-un sir. Foloseste cel putin doua exemple concrete din viata reala (de exemplu, numarul casei vs. cine locuieste acolo, numarul locului in clasa vs. elevul care sta acolo). Explica de ce este important sa nu le confundam.
Indicii pentru structurarea raspunsului:
- Defineste ce este indexul (pozitia) si ce este valoarea (continutul)
- Da doua exemple din viata reala care ilustreaza distinctia
- Arata ce se intampla cand le confunzi (erori frecvente)
- Explica cum notatia v[i] combina ambele concepte
Cuvinte cheie de folosit: index, valoare, pozitie, element, sir, paranteze drepte, dimensiune, acces
Format: Scrie raspunsul pe caiet in paragrafe coerente. Foloseste exemple concrete pentru claritate.