Sunteți pe pagina 1din 212

See discussions, stats, and author profiles for this publication at: https://www.researchgate.

net/publication/308938197

STRUCTURI DE DATE ALOCATE DINAMIC. Aspecte metodice. Implementări în


limbajul C++

Book · July 2016

CITATIONS READS

0 974

2 authors, including:

Adrian Runceanu
University of Craiova
26 PUBLICATIONS   32 CITATIONS   

SEE PROFILE

All content following this page was uploaded by Adrian Runceanu on 08 October 2016.

The user has requested enhancement of the downloaded file.


Mihaela-Ana RUNCEANU Adrian RUNCEANU

STRUCTURI DE DATE ALOCATE


DINAMIC
Aspecte metodice. Implementări în
limbajul C++

Editura Academica Brâncusi din Târgu Jiu


2016
Ediţie publicată la Editura Digitală
Toate drepturile asupra ediţiei digitale a acestei cărţi sunt rezervate Editura
Digitala. Nici o parte din această carte nu poate fi reprodusă sub nici o formă
sau metodă fără acordul scris al autorului.
Aveţi drepturi de utiliza acestă carte doar pentru propria persoană. Această
carte digitală nu poate fi revândută sau dată către alte persoane. Dacă doriţi să
împărţiţi această carte cu o altă persoană, vă rugăm să achiziţionaţi încă o
copie pentru fiecare cititor. Dacă citeşti această carte şi nu ai achiziţionat-o, te
rugăm să accesezi magazinul preferat de cărţi digitale şi să-ţi cumperi propria
copie.
Editura Academica Brâncusi din Târgu Jiu
ISBN 978-973-144-770-4 - pentru format Epub

ISBN 978-973-144-771-1 - pentru format Pdf

ISBN 978-973-144-772-8 - pentru format Mobi


Cuprins

Capitolul_1. Structuri de date. Noţiuni generale


1.1. Noţiunea de tip de date. Exemple simple
1.2. Tipuri abstracte de date
1.3. Structuri de date. Exemple

Capitolul_2. Implementarea dinamică a structurilor de date în limbajul C++


2.1. Tipul referinţă. Structuri de date dinamice. Operaţii aritmetice cu
pointeri
2.2. Legătura dintre tablouri şi pointeri. Folosirea pointerilor şi tablourilor ca
parametri în funcţii
2.3. Pointeri la funcţii
2.4. Alocarea dinamică a memoriei
2.5. Stiva implementată dinamic
2.6. Coada implementată dinamic
2.7. Liste simplu înlănţuite
2.8. Liste dublu înlănţuite

Capitolul_3. Aspecte metodice cu privire la predarea alocării dinamice a


memoriei
3.1. Obiectivele generale ale disciplinei informatică în învăţământul
preuniversitar
3.2. Domeniile informaticii în programele scolare. Clasificarea lor
3.3. Conţinutul programei şcolare
3.4. Predarea structurilor de date în liceu
3.5. Sugestii în predarea alocării dinamice a memoriei. Metode specifice
de predare şi evaluare
3.6. Proiecte didactice – exemplificări sugestive
3.7. Concluzii
Bibliografie

Despre autori
Tine legatura cu Mihaela-Ana Runceanu si Adrian Runceanu

Cuvânt înainte

Cartea Structuri de date alocate dinamic. Aspecte metodice.


Implementări în limbajul C++ prezintă aspectele teoretice și metodice ale
structurilor de date implementate atât static cât și dinamic. Prezentarea
teoretică abordează tipurile abstracte de date ca și concept, implementate
ulterior folosind alocarea dinamică a memoriei. Ultimul capitol cuprinde aspecte
metodice foarte utile în activitatea didactică.
Sunt prezentate ca noțiuni teoretice de bază tipurile de date și structurile
de date, într-o manieră didactică și foarte utilă în desfășurarea activității de
predare-învățare.
În vederea implementării dinamice a structurilor de date, este prezentat
tipul referință și noțiunea de pointer. Un capitol întreg este dedicat alocării
dinamice a memoriei, pointerilor și diverselor tipuri de liste implementate cu
ajutorul acestora: stiva, coada, lista simplu înlănțuită și lista dublu înlănțuită.
Informația este prezentată potrivit cerințelor metodice și pegagogice actuale și
este foarte utilă profesorilor în activitatea didactică de predare.
O importanță deosebită este acordată aspectelor metodice, astfel încât
ultimul capitol – Aspecte metodice cu privire la predarea alocării dinamice a
memoriei – ocupă o parte semnificativă din această lucrare și este adresată
profesorilor preocupați de propria formare atât în vederea desfășurării activității
didactice cât și pentru pregătirea examenelor de definitivat și de obținere a
gradului didactic II.
Este de remarcat prezentarea corespunzătoare a conţinutului teoretic,
legătura dintre prezentarea teoretică şi cea practică.
Pentru fiecare exemplu prezentat se presupune o cunoaştere foarte
bună a principiilor programării structurate şi, în special, a limbajului C++.
Structura cartii este următoarea:
1. Structuri de date. Noţiuni generale
1.1 Noţiunea de tip de date. Exemple simple
1.2 Tipuri abstracte de date
1.3 Structuri de date. Exemple
2. Implementarea dinamică a structurilor de date în limbajul C++
2.1 Tipul referinţă. Structuri de date dinamice. Operaţii aritmetice cu
pointeri
2.2 Legătura dintre tablouri şi pointeri. Folosirea pointerilor şi
tablourilor ca parametri în funcţii
2.3 Stiva implementată dinamic
2.4 Coada implementată dinamic
2.5 Liste simplu înlănţuite
2.6 Liste dublu înlănţuite
3. Aspecte metodice cu privire la predarea alocării dinamice a memoriei
3.1 Obiectivele generale ale disciplinei informatică în învăţământul
preuniversitar
3.2 Domeniile informaticii în programele scolare. Clasificarea lor
3.3 Conţinutul programei şcolare
3.4 Predarea structurilor de date în liceu
3.5 Sugestii în predarea alocării dinamice a memoriei. Metode
specifice de predare şi evaluare
3.6 Proiecte didactice – exemplificări sugestive
3.7 Concluzii
Bibliografie
Conţinutul cartii Structuri de date alocate dinamic. Aspecte metodice.
Implementări în limbajul C++ este util în principal studenţilor de la programul
de studii de licenta Automatică şi Informatică Aplicată, precum şi celorlaţi
studenţi de la profiluri tehnice, cat si profesorilor preocupați de propria formare
atât în vederea desfășurării activității didactice cât și pentru pregătirea
examenelor de definitivat și de obținere a gradului didactic II.
CAPITOLUL

1
Capitolul 1 - Structuri de date. Noţiuni
generale

1.1. Noțiunea de tip de date

Informaţia care stă la dispoziţia calculatorului constă dintr-o mulţime de


date care descriu lumea reală prin abstractizare. O abstractizare este de fapt o
simplificare a faptelor prin reţinerea caracteristicilor relevante ale obiectelor
reale. O dată este orice entitate asupra căreia poate opera calculatorul. Astfel
apare noţiunea de tip de date. Prin tip de date se înţelege o mulţime de valori
D care formează domeniul tipului, împreună cu o mulţime de operatori pe
acest domeniu. În cazul când elementele domeniului sunt valori compuse din
mai multe componente atomice, tipul de date obţinut se numeşte tip de date
structurat sau structură de date.
Astfel, o variabilă se caracterizează prin: tip (natura datelor şi modul de
memorare), nume (prin care aceasta se adresează), valoare şi semnificaţie.
Limbajele de programare evoluate utilizează din plin cele mai variate tipuri de
date. Însă noţiunea de tip de date este de obicei legată de un anumit limbaj de
programare. În situaţia în care se renunţă la această legătură, se ajunge la
noţiunea de structură de date. Modul de proiectare a structurilor de date şi
modul de elaborare a algoritmilor subliniază faptul că a şti să programezi nu
înseamnă numai a cunoaşte limbaje de programare şi sisteme de operare.
Pentru elaborarea unui program performant trebuie avute în vedere metodele
de programare şi tehnicile de lucru adecvate problemei abordate.
Un programator poate să-şi definească propriile tipuri de date de care
are nevoie în programul său. Operaţiile existente în aceste noi tipuri de date
sunt în primul rând cele existente asupra componentelor. În structura definită
de programator, ca entitate de sine stătătoare există însă doar operatorul de
atribuire. Adesea programatorul are nevoie de operaţii propriu-zise.
Datele trebuie să poată fi reprezentate în sistemul calculator într-un mod
care să permită prelucrarea lor. Ca o consecinţă a reprezentării, multe aspecte
ale arhitecturii sistemelor de calcul sunt implicate în memorarea datelor: teoria
codurilor, mecanismele de adresare, dispozitivele de memorare. Dar nu numai
aspectele hard trebuie avute în vedere ci şi compilatoarele şi sistemele de
operare care joacă un rol important în crearea şi ştergerea datelor din memoria
sistemului de calcul.
Pe de altă parte, se poate da o descriere matematică riguroasă a datelor,
se pot defini operaţiile formale asupra diverselor tipuri de date şi se poate folosi
tehnica matematică pentru a demonstra că datele sunt prelucrate corect în
operaţii. Dar importantă este şi înţelegerea modului în care datele sunt
manipulate în calculator, tehnica matematică fiind un supliment al descrierii
modului în care datele sunt reprezentate în calculator.
În procesul de prelucrare a datelor se face o disţinctie clară între
numerele reale, complexe, logice sau între variabilele care reprezintă valori
individuale, mulţimi de valori şi funcţii. În acest sens, se postulează principiul
că fiecare constantă, variabilă sau funcţie este de un anumit tip. Această
noţiune de tip este formulată în limbajele de programare şi face posibilă
verificarea consistenţei definirii corecte a valorilor funcţiilor, expresiilor şi
variabilelor. Tipul datei este caracterizat prin mulţimea valorilor căreia îi
aparţine constanta sau mulţimea valorilor pe care le poate lua variabila sau
expresia sau care pot fi generate de o funcţie.
În majoritatea cazurilor, tipul asociat unei variabile este precizat printr-o
declaraţie explicită de constantă, variabilă sau funcţie. Declaraţia de tip precede
textual utilizarea respectivei constante sau funcţii. Această metodă simplifică
activitatea compilatoarelor generând facilităţi în memorarea datelor.
Caracteristicile conceptului de tip sunt:
- un tip de date determină mulţimea valorilor căreia îi aparţine o constantă sau
pe care le poate lua o variabilă sau o expresie sau care pot fi generate de un
operator sau funcţie;
- tipul unei valori precizată de o constantă, variabilă sau expresie poate fi dedus
din forma sau declaraţia sa, fără a fi necesară execuţia unor procese de calcul;
- fiecare operator sau funcţie acceptă argumente de un tip precizat şi conduce
la un rezultat de un tip precizat. Dacă un operator admite argumente de diferite
tipuri (de exemplu – adunarea numerelor întregi cu numere reale), atunci tipul
rezultatului poate fi determinat de regulile specifice ale limbajului de
programare.
Drept urmare, respectând aceste reguli, un compilator poate verifica
compatibilitatea şi legalitatea anumitor construcţii de limbaj, în faza de
compilare, fără a fi necesară execuţia programului.
Din punct de vedere al implementării lor, putem vorbi despre date
implementate static şi dinamic. Criteriul de clasificare este dat de modul de
alocare a memoriei interne. Pentru structurile statice memoria se alocă la
începutul programului şi rămâne alocată cât timp programul se execută. Astfel,
caracteristicile variabilelor statice sunt bine definite, cunoscute şi fixe.
Structura, tipul şi adresa de memorie nu se pot modifica în timpul execuţiei
programului. De asemenea, variabilele statice sunt referite prin numele lor,
fiecărui nume asociindu-i-se o adresă fizică de memorie. Unei variabile statice
i se poate modifica doar valoarea, nu şi adresa din memoria internă. Scopul
definirii tipurilor de date este acela de a fixa pe de o parte domeniul valorilor pe
care le pot lua aceste variabile, iar pe de altă parte de a preciza structura,
dimensiunea şi amplasarea zonelor de memorie ce le sunt asociate. Deoarece
toate aceste elemente sunt fixate de la început de catre compilator, astfel de
variabile şi structurile de date aferente lor se numesc statice.
Din motive de memorare a datelor în calculator, în limbajele de
programare, datele sunt formate din două clase: date elementare şi date
compuse. Datele elementare (aşa numitele tipuri scalare) sunt reprezentate în
structura internă a sistemului prin şiruri de biţi asupra cărora acţionează
mecanismul de adresare şi care pot constitui operanzii direcţi ai operaţiilor
sistemului de calcul. Date elementare se considera scalarii predefiniţi: întregi,
reali, caracter, respectiv boolean (dacă limbajul de programare dispune de
acest tip) precum şi cei definiţi de utilizator. Datele compuse sunt determinate
de o descriere a tipului componentelor lor şi prin indicarea metodelor de
structurare a acestora. Sunt considerate date compuse: tablourile,
înregistrările, şirurile de caractere, fişierele etc.
Pentru structurile dinamice se alocă memorie în timpul executţei
programului, iar când nu mai este necesară, memoria se eliberează. Totuşi,
variabilele dinamice au un tip bine precizat încă din faza de compilare, însă ele
pot fi alocate dinamic, pot fi utilizate prin adresa lor din heap şi pot fi distruse
dacă nu mai sunt utile. Aceste variabile pot fi referite printr-o variabilă de tip
referinţă ce conţine adresa variabilei dinamice. Structurile dinamice cuprind:
listele şi arborii. Lista este o structură de date definită cu ajutorul unor relaţii de
ordine asupra înregistrărilor. Arborele este o structură de date definită cu
ajutorul unor relaţii de ordine asupra listelor.

1.1.1. Structura de tip tablou

Structura de tip tablou este, probabil, cea mai răspândită. Un tablou este
o structură de date omogenă ce este formată din mai multe componente de
acelaşi tip, numit tip de bază al tabloului şi este apelată printr-un identificator
numit numele tabloului. Toate tablourile ocupă locaţii de memorie continue.
Pentru a preciza o componentă individuală, numelui întregii structuri i se
adaugă un indice care selectează acea componentă. Indicii unui tablou trebuie
să fie de tip scalar.
Tablourile sunt de trei feluri:
 tablouri unidimensionale (şiruri, vectori) – dacă referirea la elementele
tabloului se face printr-un singur indice
 tablouri bidimensionale (matrici) - dacă se folosesc doi indici
 tablouri n-dimensionale – dacă referirea la elementele unui tablou se
face folosind n indici

Tabloul în interpretare matematică


Fie An ={1,2,…,n}mulţimea primelor n numere naturale. Fie M= An
i 1
 An 2
… An produsul cartezian a k astfel de mulţimi.
k

Se numeşte tablou o funcţie f:M → T, unde T este o mulţime oarecare.


Numărul k este dimensiunea tabloului. Dacă k=1 tabloul se numeşte vector.
Vectorul are n1 componente. Dacă k=2 tabloul se numeşte matrice. Matricea
are n1n2 elemente.
Exemple:

1. Vector cu 5 componente numere naturale

V= (1, 3, 6, 2, 4)

k=1; n1=5, T=N, elementele vectorului sunt v1=1, v2=3,...,

v5=4

2. Vector cu n componente numere reale

Z=(z1, z2, z3,…, zn), zi R, i {1,2,…,n}

k=1, n1=n, T=R.

3. Matrice cu n linii şi m coloane cu elemente din R :

, unde ai,j R.

k=2, n1=n, n2=m, T=R.


În limbajul C++ tipul tablou se declară astfel:
Repartizarea memoriei pentru un tablou se face astfel: pentru fiecare
element al tabloului se repartizează o zonă de memorie necesară în
conformitate cu tipul tabloului respectiv (pentru tipul int 2 octeţi, pentru long int
4 octeţi etc.). Pentru întreg tabloul se rezervă o zonă de memorie contiguă
necesară pentru a păstra fiecare element al tabloului.
Numele unui tablou poate fi utilizat în diverse construcţii şi el are ca
valoare adresa primului său element (reprezintă un pointer). Totuşi există o
diferenţă între numele unui tablou şi o variabilă de tip pointer, deoarece dacă
unei variabile de tip pointer i se poate atribui o adresă, acest lucru nu se poate
tab realiza pentru numele unui tablou, el fiind

Adresa
lui tab[0] tab[1] tab[2] tab[3] tab[4]
tab[0]

întotdeauna un
pointer spre primul element al tabloului. Cu alte cuvinte, numele unui tablou
este considerat ca fiind un pointer constant.

Limbajul C++ nu ne permite să declarăm o variabilă tablou cu număr


variabil de componente, însă de multe ori nu ştim câte componente vor fi
necesare pentru o anumită rulare a programului. De aceea trebuie rezervat un
număr maxim de componente. De cele mai multe ori o parte dintre ele rămân
neutilizate. Cantitatea de memorie necesară pentru înregistrarea unui tablou
este direct proporţională cu tipul şi mărimea sa. Pentru un tablou
unidimensional, mărimea totală în octeţi este calculată astfel: total octeţi=
sizeof(tip de bază) * mărimea tabloului.

Tip nume[număr natural1] [număr natural2]… [număr naturaln]

Un caz aparte de tablou unidimesional îl constituie şirul de caractere. Un


şir de caractere este o succesiune de caractere, cuprinse între ghilimele şi care
se termină cu caracterul nul: ‘\0’. Din acest motiv, şirurile de caractere trebuie
declarate cu un caracter mai mult decât cel mai mare şir pe care îl va conţine.
Astfel, se face loc şi pentru caracterul nul la sfârşitul şirului.
Limbajul C++ admite şi tablouri multidimensionale. Cea ma simplă formă
de tablou multidimensional este cel bidimensional (matrice).

Exemplu:

int x[30][20] – reprezintă o matrice cu 30 de linii şi 20 de coloane

Matricile sunt stocate sub formă de rând-coloană, primul indice indicând


rândul (linia), iar al doilea indice indicând coloana. Deci, numărul de octeţi
ocupaţi de elementele unei matrice = mărimea primului indice*mărimea celui
de-al doilea indice*sizeof(tip de dată).

Pointeri de indexare
În limbajul C++ pointerii şi tablourile sunt strict legaţi, numele unui tablou
fiind un pointer la adresa primului element din tablou. Fie tabloul: char p[10].
Atunci p= =&p[0].
Un tablou fără indice generează un pointer, iar, invers, un pointer poate
să aibă un indice ca şi cum ar fi fost declarat ca şi tablou:
Exemplu:

int *p, i[10];

p=i;

p[5]=100; // atribuire utilizând indice

*(p+5)=100; // atribuire utilizând aritmetica pointerilor


Ambele instrucţiuni de atribuire plasează valoarea 100 în cel de-al
şaselea element al lui i. Prima instrucţiune foloseşte un indice al lui p; cea de-
a doua utilizează aritmetica pointerilor. Rezultatul este acelaşi.
Acelaşi concept se aplică şi tablourilor cu două sau mai multe
dimensiuni. De exemplu, presupunând că a este o matrice de numere întregi
de 10 pe 10, următoarea egalitate este adevarată: a=&a[0][0]. De asemenea,
la elementul de pe linia 0 şi coloana 4 din matricea a se poate face referire în
două moduri:
- folosind indici: a[0][4]
- folosind pointer: *(a+4)
Similar, elementul de pe linia 1 şi coloana 2 este a[1][2] sau *(a+12). În general,
pentru orice tablou bidimensional, a[i][k] este echivalent cu
*(a+(j*lungime_rand)+k).
Pointerii sunt uneori folosiţi pentru a avea acces în tablou deoarece
aritmetica pointerilor este, în general, mai rapidă decât adăugarea de indici
tabloului.
O matrice poate fi redusă la un pointer la un tablou unidimensional.
O categorie specială de şiruri o constituie şirurile de caractere, care sunt
tratate altfel decât tablourile numerice. Astfel, limbajul C dispune de o bibliotecă
specială numită string.h. Spre deosebire de limbajul Pascal, în limbajul C nu
există un tip de date special definit pentru şiruri de caractere, însă se pot folosi
pointeri şi tablouri cu o singură dimensiune care au ca tip de bază tipul char.
Pentru a marca sfârşitul şirului se adaugă un caracter special ‘\0’ (numit
caracterul nul) care este considerat sfârşitul de şir.

1.1.2. Structura de tip articol (înregistrare)

Limbajul C++ oferă programatorului posibilitatea de a grupa datele, date


de tipuri diferite putând fi prelucrate atât individual cât şi împreună. Dacă tabloul
conţine mai multe elemente de acelaşi tip, o structură este formată din mai
multe elemente de tipuri diferite. La rândul lor, structurile definite pot constitui
elemente componente pentru formarea de noi tipuri de date (tablouri, structuri,
uniuni). Elementele componente se mai numesc membri sau câmpuri.

Sintaxa declarării unei structuri este următoarea:

struct [ nume tip_tip_structura ]

tip_1 lista_parametri_tip_1;

tip_2 lista_parametri_tip_2;

……………………………

tip_n lista_parametri_tip_n;

} [ lista_variabile_structura ];

În declaraţie poate lipsi precizarea tipului de structură sau a listei de variabile


însă nu ambele simultan. În cazul în care lipseşte tipul, spunem că variabilele
au un tip anonim. Câmpurile componente ale unei structuri pot fi de oricare din
tipurile:
- predefinite (întreg, character, număr real);
- definite de utilizator.

Exemplul 1: Definirea datelor de bază pentru o persoană specificând numele şi


vârsta:

struct pers
{
char nume[35];
int ani;
}
S-a definit o structură de tip pers fără a fi folosită nici o variabilă de tipul definit.
Exemplul 2: Definirea unei structuri de tip angajat specificând pe lângă datele
de bază (un câmp de tip structură pers) adresa, salariul şi vechimea în muncă.
Declaraţia ei este următoarea:

struct angajat
{
struct pers p; //Structura pers a fost definită anterior
char adresa[50];
long salariu;
int vechime;
} persoana, firma[100];
struct angajat A[50] ;

Folosind typedef, exemplul anterior se mai poate scrie:

typedef struct
{
struct pers p;
char adresa[50];
long salariu;
int vechime;
} ANGAJAT;
ANGAJAT persoana, firma[100];

Definiţia structurii poate figura atât în cadrul functiei main() cât şi în faţa ei, după
includerile de fişiere antet.
De asemenea, se pune următoarea întrebare: fiind dată o variabilă de tip struct,
care este modalitatea de acces la câmpurile ei? Pentru aceasta, se folosesc
operatorii de selecţie:
a) ‘.’ – operatorul de selecţie directă
Exemplul 3:

persoana.salariu – reprezintă câmpul salariu al variabilei


persoana
persoana.adresa – reprezintă câmpul adresa al variabilei
persoana
b) ‘->’ – operatorul de selecţie indirectă – când se foloseşte un pointer la
structură (cazul listelor înlănţuite)
Este permisă atribuirea între structuri, însă cu condiţia ca structurile să
fie de acelaşi tip.
Un tip aparte de dată structurată este tipul union. Acesta reprezintă un
tip înregistrare cu structura variabilă. Fie exemplul următor:

#include<iostream.h>
union test
{
int a;
char b[10];
double c;
};
int main()
{
test var; int i;
cin>>var.c; cout<<var.c<<endl;
cin>>var.b; cout<<var.b;
}

Variabila var este de tip union. Ea conţine un întreg, un vector de caractere şi


o variabilă reală. Cele 3 câmpuri subordonate ocupă respectiv 2 octeţi, 10 octeţi
şi 8 octeţi. În realitate, pentru toate variabilele s-au reţinut 10 octeţi – adică
octeţii necesari pentru a memora câmpul cel mai lung. Aceasta înseamnă că,
la un moment dat, se poate memora doar un singur câmp dintre cele
subordonate.
Forma generală a unei uniuni este următoarea:
1.2. Tipuri abstracte de date

Un programator poate să-şi definească propriile tipuri de date de care are


nevoie în programul său. Operaţiile existente în aceste noi tipuri de date sunt
în primul rând cele existente asupra componentelor. În structura definită de
programator, ca entitate de sine stătătoare, există însă doar operatorul de
atribuire. Adesea programatorul are nevoie de operaţii propriu-zise.
Tipul Abstract de Date (prescurtat TAD) este un astfel de tip, definit de om în
urma unui proces de abstractizare. El este precizat prin:

- domeniul TAD;

- operatorii definiţi în acest domeniu.

Nu interesează cum se reprezintă elementele domeniului în calculator şi nici


cum se execută operatorii asupra diferiţilor operanzi posibili. Pentru a specifica
un TAD este necesar să precizăm cele două elemente ale tipului: domeniul şi
operaţiile.
Domeniul este precizat ca o mulţime matematică, D. Pentru a specifica o
operaţie o este necesar să definim matematic operaţia o. În general, spre
deosebire de operaţia din matematică, în programare operaţia o nu este o
aplicaţie totală; ea are sens numai pentru anumite elemente din D. Valorile
pentru care operaţia o are sens satisfac un predicat  numit precondiţie pentru
operaţia o. Rezultatul efectuării operaţiei o depinde de operanzi, este legat de
aceşti operanzi, legătură precizată cu ajutorul unei postcondiţii, dată printr-un
predicat ψ.

union [<numele uniunii>]

<tip> <nume variabila>;

………

}[lista variabile];
Pentru a putea folosi în programare un TAD este necesar să decidem modul
de reprezentare în calculator a valorilor din domeniul tipului precum şi
subalgoritmii corespunzători operaţiilor scrişi în limbajul ales. Obţinem ceea ce
se cheamă un Tip Virtual de Date (TVD). Este de dorit ca acest TVD să fie privit
ca o cutie neagră. Utilizatorul nu trebuie să vadă cum se lucrează în interiorul
acestei unităţi de program. Singurul acces la datele tipului virtual trebuie să se
facă prin operaţiile TAD corespunzător, cunoscând doar specificaţiile acestor
operaţii. Nu toate limbajele de programare au această proprietate.
Un tip abstract de date trebuie să conţină operaţii suficiente pentru a fi util . El
trebuie să permită crearea oricărei valori din domeniul tipului. Trebuie să existe
suficiente operaţii de testare pentru a putea fi verificate toate precondiţiile
operaţiilor. Trebuie concepute operaţii suficiente pentru ca programatorul să
aibă acces la oricare din componentele din care e compus acest tip abstract de
date.
Deci tipurile de operaţii pe care le conţine un TAD sunt:

- operaţii de intrare-ieşire;

- operaţii de construire de valori din domeniul tipului;

- operaţii de conversie (a unor valori din alte tipuri de date) în valori de acest
tip;

- operaţii de testare a unor condiţii;

- operaţii matematice propriu-zise (adunare, scădere,etc);

- operaţii de selectare a unor componente din care e construit acest tip de


date.
Printre avantajele folosirii tipurilor abstracte de date menţionăm specificarea
exactă, independenţa implementării, ascunderea informaţiei, simplitate şi
integritate. Prin abstractizare ne putem concentra asupra proprietăţilor
esenţiale şi nu asupra reprezentării şi implementării; accentul cade asupra
specificării tipului abstract de date. Utilizatorul se va folosi doar de această
specificare, el nu vede reprezentarea şi nici modul de implementare a
operaţiilor. Tipurile abstracte de date constituie unul din mijloacele care permit
o abordare sistematică şi prin a căror utilizare se ajunge la realizarea unor
module corecte şi refolosibile. Mai mult, aceste module se pot organiza în
biblioteci utile, ducând la creşterea productivităţii în programare.
De exemplu, să presupunem că în urma proiectării s-a stabilit că sunt necesare
trei tipuri de date A, B şi C şi un anumit cod ce apelează operaţiile acestor tipuri.
Dacă la realizarea programului lucrează o echipă de cel puţin patru
programatori, atunci trei ar putea implementa tipurile de date A, B, respectiv C,
iar unul ar putea implementa algoritmul principal. Fiecare dintre aceştia poate
lucra independent neinteresându-l decât specificaţia celorlalte tipuri, nu şi
detaliile de implementare. Evident, timpul total de realizare a produsului
program ar fi mult redus faţă de cazul în care ar lucra o singură persoană. Dar
chiar dacă el ar fi realizat de un singur programator, abstractizarea este utilă
deoarece reduce complexitatea problemei. Când implementează tipul A
programatorul nu are în vedere nimic despre tipurile B şi C, sau despre modulul
principal. În plus, în ambele cazuri s-ar mai obţine următoarele avantaje. Mai
întâi, testarea ar fi mult uşurată. Fiecare din tipurile A, B şi C pot fi testate şi
verificate separat. Apoi s-ar permite reutilizarea celor trei module. Este foarte
uşor să extragem o structură de date dintr-o aplicaţie şi s-o folosim în alta dacă
pentru tipul respectiv s-a folosit încapsularea datelor.
În plus, încapsularea şi ascunderea informaţiei are drept consecinţă
imposibilitatea modificării necontrolate a datelor în restul programului (se pot
folosi doar operaţiile tipului). Mai mult, se poate schimba reprezentarea unui tip
de date fără să fie afectate programele care folosesc acel tip de date, aceasta
cu condiţia ca operaţiile tipului să nu fie modificate (interfaţa, contractul să
rămână acelaşi).

1.2.1. Proiectarea TAD

a) TAD număr întreg


Este bine cunoscută mulţimea Z a numerelor întregi, precum şi operaţiile
obişnuite între numere întregi. Pentru a specifica un TAD Întreg va trebui să
precizăm exact mulţimea acestor operaţii şi semnificaţia lor. Domeniul este
format din mulţimea Z. Operaţiile sunt operaţiile aritmetice, cele relaţionale şi
operaţiile de intrare/ieşire (citiri şi tipăriri de valori întregi). Operaţiile aritmetice
sunt notate prin +, -, *, div, mod şi au semnificaţia binecunoscută. Toate sunt
operaţii binare (argumente întregi şi rezultat întreg). Operaţiile relaţionale sunt
notate prin =, , <, >, <=, >=, cu semnificaţia din matematică şi sunt operaţii
binare cu argumente numere întregi şi rezultatul una din valorile logice true sau
false.
Un TVD corespunzător acestui TAD este tipul int din limbajul C. Să observăm
însă că tipul int nu este o implementare exactă a TAD Întreg. În primul rând
diferă domeniile celor două tipuri; mulţimea Z este infinită, în timp ce domeniul
valorilor tipului int din C este finită, formată din toţi întregii cuprinşi între –32768
şi 32767. În consecinţă, diferă şi operaţiile lor. Mai mult, în tipul int suma a+b
nu este definită (mai exact, este greşit definită) pentru a + b > 32767.
Sunt posibile şi alte implementări. Evident, TVD Întreg depinde de
implementarea aleasă. Sunt posibile două reprezentări diferite pentru un număr
întreg şi ele depind de modul de alocare a memoriei: statică, sau dinamică. În
ambele situaţii se porneşte de la reprezentarea numerelor într-o bază de
numeraţie fixată. Numărul este dat prin cifrele reprezentării şi poate fi
reprezentat:

- ca un vector cu componentele egale cu cifrele reprezentării;

- ca o listă înlănţuită ce conţine cifrele reprezentării.


În primul caz alocarea va fi statică, iar un număr natural este reprezentat
pe un vector cu un număr fixat de componente. În al doilea caz, un număr
natural se reprezintă în calculator ca o listă ce conţine toate cifrele reprezentării
în baza fixată, oricâte ar fi acestea. În acest caz reprezentarea este mai
aproape de tipul abstract Întreg definit. Singura restricţie este spaţiul de
memorie al calculatorului care, evident, e finit!

b) TAD număr natural

În primul rând, TAD Natural diferă de TAD Întreg prin domeniul tipului,
mulţimea N a numerelor întregi fiind o submulţime a lui Z. În al doilea rând, deşi
există operaţii cu acelaşi nume, aceste operaţii diferă atât prin domeniul lor de
definiţie cât şi prin definiţia lor. Astfel, 3-5 este o operaţie nedefinită în mulţimea
numerelor naturale, în timp ce era bine definită în Z. Operaţia de scădere diferă
esenţial de scăderea numerelor întregi, a - b fiind definită doar dacă a  b.
Specificăm în continuare operaţiile definite în acest tip:

Operaţia adună {m := n1 + n2}

Precondiţia: n1, n2  N;

Postcondiţia: m = n1 + n2 .

Operaţia scade {m := n1 - n2}

Precondiţia: n1, n2  N, n1  n2;

Postcondiţia: m = n1 - n2 .

Operaţia multiplică {m := n1 * n2}

Precondiţia: n1, n2  N;

Postcondiţia: m = n1*n2.

Operaţia divide {m := n1 : n2}

Precondiţia: n1, n2  N şi n2 > 0;

Postcondiţia: m = n1 / n2.

Operaţia atribuie { m:= i }

Precondiţia: i  N;

Postcondiţia: m = i.

Operaţia citeşte {m:= număr natural}

Precondiţia: de la tastatură se introduce un număr întreg

Postcondiţia: m = numărul întreg citit.

Operaţia tipăreşte {Se afişează numărul natural m}

Precondiţia: mN

Postcondiţia: se afişează pe ecran numărul m

Relaţia esteZero {Este m egal cu zero ?}

Precondiţia: mN
Postcondiţia: Dacă m = 0 atunci esteZero = True altfel esteZero = False

c) TAD număr raţional

Domeniul acestui TAD constă din mulţimea numerelor raţionale, notată prin Q:
Q = {(m, n) m  Z, n  N+, m, n prime între ele}.
În această mulţime vom specifica următoarele operaţii:

Operaţia adună { q := q1 + q2 }

Precondiţia: q1, q2  Q;

Postcondiţia: q = q1 + q2 .

Operaţia scade { q := q1 - q2 }

Precondiţia: q1, q2  Q;

Postcondiţia: q = q1 - q2 .

Operaţia multiplică { q := q1 * q2 }

Precondiţia: q1, q2  Q;

Postcondiţia: q = q1*q2.

Operaţia divide { q := q1 : q2 }

Precondiţia: q1, q2  Q şi q2  0;

Postcondiţia: q = q1/q2.

Operaţia atribuie { q := m / n}

Precondiţia: m  Z, n  N şi n  0;

Postcondiţia: q = m / n.

Operaţia citeşte { q := număr raţional citit}

Precondiţia: de la tastatură se introduce un număr raţional ca pereche


(numărător, numitor).

Postcondiţia: q = numărul raţional citit.

Operaţia tipăreşte { Se afişează numărul q}


Precondiţia: q  Q;

Postcondiţia: se afişează pe ecran numărul q.

Relaţia esteZero { Este q egal cu zero ?}

Precondiţia: q  Q;

Postcondiţia: esteZero = (q = 0).

Relaţia egal {Este q1 egal cu q2 ?}

Precondiţia: q1, q2  Q;

Postcondiţia: egal = (q1=q2)

Relaţia maiMare {Este q1 mai mare decât q2?}

Precondiţia: q1, q2  Q;

Postcondiţia: maiMare = (q1>q2).

Funcţia întreg { Partea întreagă a lui q}

Precondiţia: q  Q;

Postcondiţia: întreg = partea întreagă a lui q.

În cazul TAD Raţional definit mai sus, operaţiile de intrare-ieşire sunt citeşte
şi tipăreşte, operaţia atribuie este constructor, operaţia întreg este o conversie,
esteZero, egal şi maiMare sunt operaţii de testare, iar adună, scade, multiplică
şi divide sunt operaţiile aritmetice cunoscute.
Cu cât construcţiile de limbaj sunt mai aproape de lumea exterioară, cu atât
sunt mai uşor de modelat prin programe sistemele aparţinând lumii reale.
Programele ar trebui atunci să conţină obiecte care colaborează între ele
pentru a efectua un anumit calcul. Un obiect este caracterizat de stare şi
comportament. Similar, un obiect ar trebui să fie caracterizat de asemenea de
stare – variabile şi de un comportament – operaţii sau metode. Colaborarea
între obiectele unui program poate fi privită ca şi transmitere de mesaje. Dacă
un obiect a trimite un mesaj obiectului b, atunci b va reacţiona, modificându-şi
starea şi/sau provocând alte mesaje către diferite obiecte. De fapt obiectele
care primesc mesajele şi reacţionează la ele produc informaţie. Calculul
efectuat de programul ce conţine aceste obiecte va consta din informaţia
produsă de obiecte ca reacţie la mesaje. Este aproape evidentă observaţia că:
obiectul a transmite un mesaj obiectului b prin apelarea unei operaţii (metode)
a obiectului b.

1.2.2 Implementarea TAD

[11,12,17] Tipurile abstracte de date se definesc cu ajutorul claselor. Se


obişnuieşte să se spună că datele protejate ale unui tip abstract sunt
încapsulate în clasa care defineşte tipul respectiv. Ca şi în cazul structurilor,
referirea la tipul de dată clasa se face cu numele după cuvântul cheie class
(numele clasei). Protecţia datelor se realizează cu modificatorii de protecţie:
private, protected şi public. După modificatorul de protecţie se pune caracterul
‘ :’. Modificatorul private şi protected reprezintă date protejate, iar public
neprotejate. Domeniul de valabilitate a modificatorilor de protecţie este până la
următorul modificator din interiorul clasei, modificatorul implicit fiind private.
De exemplu, clasa vector se poate declara în modul următor:

class vector
{
int *e; // elementele vectorului
int d ; // dimensiunea vectorului
public:
vector (int *e1, int d1) ;
~vector() {delete [] e ;}
void lpatrat();
void afiseaza();
}

Datele membru e şi d au fost declarate ca date de tip private (protejate),


iar funcţiile membru au fost declarate publice (neprotejate). Deci programatorul
nu are acces la datele membru numai prin funcţiile membru.
Protecţia datelor se realizează prin faptul că la ele au acces numai funcţiile
membru ale tipului (clasei). De asemenea, dacă o funcţie membru este
protejată, atunci ea poate fi apelată numai prin intermediul unei funcţii membru
a tipului (clasei). Acest mod de lucru, deşi asigură o protecţie bună a
elementelor membru protejate ale clasei (elemente protejate prin private sau
protected), uneori este considerat rigid. Astfel, deşi există funcţii descrise in C
care pot fi utilizate pentru a prelucra instanţieri (obiecte) ale unei clase, ele nu
se pot utiliza simplu deoarece nu sunt funcţii membru ale clasei respective şi
deci nu au acces la datele membru. Mai mult decât atât o funcţie membru se
apelează totdeauna în dependenţă cu un obiect care este numit obiectul curent
al apelului. În acest fel, o funcţie membru se apelează prin una din următoarele
formate:
nume_obiect.nume_functie_membru(…)

sau

pointer_nume_clasa->nume_functie_membru(…)

În cazul funcţiilor obişnuite nu se admit astfel de apeluri, toate datele


prelucrate de funcţie se transferă prin parametri sau sunt globale.
De aceea, o funcţie obişnuită poate fi utilizată pentru a prelucra obiectele unei
clase, dacă ea se modifică în aşa fel încât să devină funcţie membru.
S-a făcut un compromis pentru a admite accesul la elementele protejate şi
pentru anumite funcţii care nu sunt membru. Aceste funcţii au fost numite funcţii
prieten (friend) pentru clasa respectivă. Ele trebuie precizate ca atare în
definiţia clasei. În acest scop, prototipurile lor sunt prezente în definiţia clasei şi
sunt precedate de cuvântul cheie friend.
Exemplu:
Fie tipul definit de utilizator:

struct complex{
double real;
double imag;
};
Funcţia modul, pentru calculul modulului unei date de tip complex poate fi
definită, ca mai jos, ca o funcţie obişnuită:

double modul(complex *z)


{
return sqrt(z->real * z->real + z->imag * z->imag);
}

Dacă se consideră declaraţiile:


complex z1={1,1};
double d;
atunci instrucţiunea de atribuire:
d=modul(&z1);
atribuie lui d modulul numărului complex z1=1+i.
Acelaşi lucru se poate realiza implementând tipul abstract complex astfel:

class complex{
double real;
double imag;
public:
complex(double x=0,double y=0)
{
real=x;
imag=y;
}
double modul()
{
return sqrt(real*real + imag*imag);
}
….
};

Declaraţia pentru z1 se scrie:


complex z1(1,1);
iar instrucţiunea de atribuire devine:
d=z1.modul();
În acest caz, funcţia modul() nu are parametru deoarece ea se apelează pentru
obiectul z1. În corpul funcţiei modul() este definit implicit pointerul this şi acesta
are ca valoare chiar adresa lui z1.
Expresia:
real*real+imag*imag
din corpul funcţiei modul, trebuie considerată ca şi când ar fi scrisă sub forma:
this->real*this->real + this->imag*this->imag
Funcţia modul, definită pentru tipul utilizator complex (cu struct) poate
înlocui funcţia membru modul a clasei complex dacă ea se declară ca funcţie
prieten a clasei complex, astfel:
class complex{
double real;
double imag;
public:
complex(double x=0,double y=0)
{
real=x;
imag=y;
}
friend double modul(complex *z);
….
};

Funcţia modul, prieten al clasei complex, are aceeaşi definiţie ca şi funcţia


modul definită pentru tipul complex introdus prin construcţia struct. De
asemenea, ea se apelează ca orice funcţie obişnuită.
În exemplul de faţă, dacă se consideră instanţierea:
complex z(1,1);
atunci funcţia prieten modul se apelează în mod obişnuit, adică prin:
d=modul(&z);
Spre deosebire de funcţiile membru, în cazul funcţiilor prieten nu mai este
definit pointerul implicit this. Acest lucru conduce la faptul că o funcţie prieten
are un parametru în plus faţă de o funcţie membru care are acelaşi efect.
O funcţie prieten poate fi o funcţie obişnuită (ca în cazul funcţiei modul din
exemplul de mai sus) sau o funcţie membru a unei alte clase.
Iniţializarea obiectelor se face cu o funcţie membru specifică numită
constructor. Numele constructorului trebuie să coincidă cu numele clasei. O
clasă are mai mulţi constructori. În acest caz, aceste funcţii membru au numele
comun, ceea ce se poate face datorită posibilităţii de supraîncărcare a funcţiilor.
Bineînţeles, în acest caz, numele şi/sau tipul parametrilor formali trebuie să fie
diferit, altfel compilatorul nu poate să aleagă constructorul corespunzător.
Constructorul nu returnează o valoare. În acest caz, nu este permisă nici
folosirea cuvântului cheie void. Dacă o clasă are constructor fără parametri
atunci el se va numi constructor implicit.
Destructorul este funcţia membru care se apelează în cazul distrugerii
obiectului. Destructorul obiectelor globale se apelează automat la sfârşitul
funcţiei main ca parte a funcţiei exit. Deci nu este indicată folosirea funcţiei exit
într-un destructor, pentru că acest lucru duce la un ciclu infinit. Destructorul
obiectelor locale se execută automat la terminarea blocului în care s-au definit.
În cazul obiectelor locale se execută automat la terminarea blocului în care s-
au definit. În cazul obiectelor alocate dinamic, de obicei destructorul se
apelează indirect prin operatorul delete (obiectul trebuie să fi fost creat cu
operatorul new). Există şi un mod explicit de apelare a destructorului, în acest
caz numele destructorului trebuie precedat de numele clasei şi operatorul de
rezoluţie. Numele destructorului începe cu caracterul ~ după care urmează
numele clasei. Ca şi în cazul constructorului, destructorul nu returnează o
valoare şi nu este permisă nici folosirea cuvântului cheie void.
Exemplu – clasa cu mai mulţi constructori: Datele care sunt membru sunt
numele şi prenumele unei persoane

#include<string.h>
#include<iostream.h>
class persoana {
char *nume; char *prenume ;
public:
persoana(); //constructor implicit
persoana(char *n, char *p); // constructor
persoana(const persoana& p1); //constructor de copiere
~persoana(); //destructor
void afiseaza();
};
persoana::persoana(){
nume=prenume=0;
cout<<”Apelarea constructorului implicit\n”;}
persoana::persoana(char *n, char *p){
nume=new char[strlen(n)+1];
prenume=new char [strlen(p)+1];
strcpy(nume,n);
1.3. Structuri de date

1.3.1. Stiva

Multe procese sunt asemănătoare mutărilor tăvilor dintr-o cofetarie. Tăvile


sunt puse una peste alta, operaţia făcându-se în vârful stivei de tăvi, sau sunt
luate, tot din vârful stivei. Deci ultima tavă pusă este prima care este luată.
Termenul uzual pentru o structură care respectă această disciplină LIFO (Last-
In-First-Out) este cel de stivă.
O stivă [16] este un tip de dată ale cărui operaţii de inserare şi de ştergere
păstrează această disciplină, ultimul venit/primul servit. Astfel, într-o stivă pot fi
adăugate sau şterse elemente doar în vârful stivei.
Grafic, o stivă se poate reprezenta astfel:

Astfel, putem spune că o stivă este o structură de date având proprietatea


caracteristică că elementele ei pot fi şterse doar în ordine inversă introducerii.
Mai abstract, am putea caracteriza o stivă ca fiind o structură liniară în care
elementele sunt ordonate în raport cu momentul temporal al inserării lor.
Prezentăm în continuare principalele operaţii utile în tipul abstract de date
STIVA(notata cu St). Astfel, iniţializarea stivei se efectuează prin operaţia Init.
Operaţiile de adăugare a unui element în stivă şi de extragere din lista a ultimului
element depus (Push si Pop) sunt Adaug şi Extrag. Pentru a putea afla dacă stiva
este vidă şi pentru a cunoaşte numărul de elemente aflate în stivă la un moment
dat, sunt puse la dispoziţia utilizatorului funcţiile StVida şi Cardinal (test de stivă
vidă, respectiv numărarea elementelor stocate).
Specificarea acestor operaţii se dă în continuare.

Operaţia Init(St):
Precondiţie: True.
Postcondiţie: St este o stivă vidă.

Operaţia Adaug (St,Element):


Precondiţie: Stiva St= (x1,x2,...,xn), n0.
Postcondiţie: Stiva St= (y1,y2,...,yn,yn+1), unde y1=Element iar yi+1=xi, pentru
i=1,2,..,n.

Operaţia Extrag (St,Element):


Precondiţie: Stiva St= (x1,x2,...,xn), n>0.
Postcondiţie: Element=x1 iar Stiva St= (y1,y2,...,yn,yn-1), unde yi=xi+1, pentru
i=1,2,..,n-1.
Funcţia StVida (St):
Precondiţie: St este o stivă arbitrară.
Postcondiţie: StVida este True dacă numărul elementelor din stiva St este 0.

Funcţia Cardinal (St):


Precondiţie: St este o stivă arbitrară.
Postcondiţie: Cardinal = Numărul elementelor din stiva St.

Reprezentarea stivelor prin tablouri

Stivele pot fi implementate static prin tablouri. Orice stivă implementată pe


baza structurii de tablou trebuie să ţină cont de numărul elementelor tabloului,
care va reprezenta numărul maxim de valori ce pot fi memorate pe stivă. O
variabilă vf va fi folosită pentru a localiza vârful stivei.
Astfel, fiind dată variabila st de tip tablou ce reprezintă o structură de tip stivă şi
dimensiune maximă dmax şi cu elementele de un anumit tip tip:
const int dmax=100;
tip st[dmax] ;
int vf;
Având aceste date, operaţiile cu stiva, în limbajul C++ se pot implementa astfel:

1) Initializarea stivei:

void init(tip st[], int *vf)


{
(*vf)=0;
}

2) Adaugarea unui element x în vârful stivei:

void adaug(tip x; tip st[], int *vf)


{
(*vf)++;
st[*vf]=x;
}

3) Extragerea elementului din vârful stivei

void extragere(tip st[], int *vf,tip *p)


{
*p=st[*vf]; // Se reţine în variabila *p valoarea din vârful stivei
(*vf)--;
}

4) Verificarea dacă stiva este vidă

int stvida(tip st[], int *vf)


{
return (*vf)==0;
}

5) Numărarea elementelor din stivă

int cardinal(tip st[], int vf)


{
return vf;
}
Se observă că toate operaţiile asupra stivelor sunt rapide. Toate se referă
doar la valoarea din vârful stivei. De aceea, ele sunt recomandate în aplicaţii.
Afişarea conţinutului stivei poate fi facută doar dacă privim stiva ca şi o listă.
Folosind operaţiile descrise mai sus, putem afişa conţinutul stivei doar dacă
scoatem, prin extragere, valorile din stivă, afişându-le şi punându-le pe o stivă
auxiliară, apoi repunându-le pe stiva iniţială, prin adaug.
Deci stiva nu este potrivită pentru aplicaţiile care necesită traversarea ei. Nu
avem acces direct la valorile interioare din stivă. În general, pentru toate
structurile exceptând stivele şi cozile operaţia de traversare este fundamentală.
Stivele sunt folosite pentru că ele modelează comportarea multor sisteme din
lumea reală. Stivele sunt dinamice, dimensiunea lor creşte sau scade după
necesitaţile momentului(ex. metoda backtracking). Dar ele sunt ‘opace’
deoarece nu vedem decât valoarea din vârf. Nu trebuie sa ştim dimensiunea
lor atunci când sunt create. Ele sunt răspândite, dispersate deoarece nici un
nod nu reclamă un loc special, doar prin adaug şi extragere putem determina
unde putem găsi o anumită valoare.

1.3.2. Coada

Oameni aşteptând în linie la o casă de bilete sau maşini aşteptând într-o


intersecţie se întâlnesc deseori. Asemenea linii de aşteptare se formează oricând
şi oriunde numărul cererilor pentru o resursă este mai mare decât capacitatea de
servire a acelei resurse. Modelul de intrare şi ieşire din aceste aşteptări ordonate
este caracterizat prin faptul că entităţile sunt servite în ordinea sosirii.
O structură de date cu acest model de intrare şi ieşire a elementelor, care
respectă disciplina FIFO (First In First Out) se numeşte coadă. Pentru a respecta
această disciplină, vom efectua adăugarea în coada listei, iar extragerea din capul
cozii.
O coadă se poate memora şi manipula ca şi o structură de date coadă. Ca
şi în cazul tablourilor, listelor sau stivelor, structura de coadă nu priveşte
complexitatea fluxului de elemente care sunt în coadă, ci doar accesul la
elemente.
Grafic coada se poate reprezenta astfel:

O coadă este un tip de date cu operaţii caracteristice comportării primul


venit/primul servit. Elementul care poate servi este cel care a sosit în coadă cel
mai devreme. Dacă acesta a fost scos din coadă, atunci următorul element care
a sosit cel mai devreme devine elementul care va putea fi servit în continuare.
Specificarea operaţiilor este făcută în continuare.

Operaţia Crevida (c): {c:= coada vida}


Precondiţie: True {adică fără restricţii la intrare}
Postcondiţie: c este o coadă vidă.

Operatia Adaug (c, Element): {Adaugă pe Element în c}


Precondiţie: c = (x1,x2,...,xn), n0.
Postcondiţie: c = (x1,x2,...,xn,xn+1), unde xn+1=Element.

Operatia Extrag (c, Element): {Element:=Capul cozii}


Precondiţie: C = (x1,x2,...,xn), n>0.
Postcondiţie: Element=x1 iar C = (y1,y2,...,yn,yn-1), unde
yi=xi+1, pentru i=1,2,..,n-1.

Operaţia CVida (c): {Cvida este True dacă c e vidă}


Precondiţie: c = (x1,x2,...,xn), n>=0.
Postcondiţie: Dacă n=0 atunci Cvida=True altfel Cvida=False.

Operaţia Cardinal (c): {Cardinal:= n}


Precondiţie: c = (x1,x2,...,xn), n>=0.
Postcondiţie: Cardinal = n.

Şi structura de coadă poate fi implementată static cu ajutorul tablourilor


unidimensionale. Notăm coada cu c (cu elementele de tipul tip – un tip oarecare
de date), iar numărul de elemente din coadă (respectiv poziţia ultimului element
din coadă) cu n Evident, dacă coada este vidă n=0.
const int dmax=100; tip c[dmax] ; int n;
Având aceste date, operaţiile cu coada, în limbajul C++ se pot implementa astfel:
1) Iniţializarea cozii:

void Crevida (tip c[], int *n)


{
*n=0;
}

2) Adăugarea unui element x în coadă:

void adaug(tip x; tip c[], int *n)


{
(*n)++;
c[*n]=x;
}

3) Extragerea unui element din coadă (a primului element)

void extrag(tip c[], int *n,tip *p)


{
int i;
*p=c[1]; /* Se retine in variabila *p valoarea primului element
din coada*/
for(i=1;i<=(*n)-1 ;i++)
c[i]=c[i+1];
(*n)--;
}

4) Verificarea dacă coada este vidă

int cvida (tip c[], int n)


{
return (n==0);
}

5) Numărarea elementelor din coadă

int cardinal (tip c[], int n)


{
return n;
}
1.3.3. Lista înlănțuită

Un mod uzual de a păstra o colecţie de elemente este de a face o listă a


acestor elemente. De exemplu, lista cumpărăturilor pentru o familie: o astfel de
listă creşte după cum membrii familiei îşi notează lucrurile necesare. Elemente
pot fi adăugate la sfârşitul listei sau între altele două existente. Uneori unele
elemente vor fi şterse din listă, descoperindu-le acasă sau cumpărându-le.
După cumpărături este posibil ca lista să se golească. Dacă încercăm să
adăugăm un element, putem căuta întâi în listă dacă există acel element, caz
în care nu-l vom adăuga. Sau poate este necesară actualizarea unui element
din listă.
Aceste operaţii descrise mai sus apar în multe aplicaţii, astfel structurile
de listă se pot include printre structurile fundamentale în programare.
O listă [17] este o colecţie (eventual vidă) de elemente de acelaşi tip.
Caracteristica esenţială a structurii de listă este aceea că elementele ei au
legături între ele.
Putem surprinde natura structurii de listă prin contrast cu structura de
tablou, relativ la operaţiile efectuate asupra unor instanţe (obiecte) ale acestor
structuri. Operaţiile aplicate asupra listelor diferă semnificativ de cele aplicate
asupra tablourilor:
a) Activarea. În mod normal, la crearea unei liste de elemente lista este
vidă, nu conţine elemente. Astfel, la fel cum luăm o bucată de hârtie pentru a
face o listă a cumpărăturilor, putem aloca spaţiu pentru elementele pe care le
conţine lista sau am putea aloca doar când este necesar (în cazul inserării unor
elemente în listă). Indiferent de modul de implementare, numărul elementelor
unei liste creşte sau scade, în funcţie de operaţiile efectuate asupra listei. Prin
contrast, numărul elementelor unui tablou este constant, nu este dependent de
operaţiile efectuate asupra tabloului.
b) Adăugarea. O listă creşte când îi este adaugat un element. Adăugarea
poate fi făcută nu numai în ‘coada listei’, ci uneori într-o anumită poziţie pentru
a păstra o ordine dată.
c) Actualizarea. Singura formă de atribuire permisă pentru liste este
atribuirea unei valori unui element al listei. Actualizarea nu afectează în felul
acesta structura listei (numărul elementelor şi relaţiile dintre ele).
d) Partiţionarea. Este convenabil să putem descompune o listă în mai multe
subliste. Pentru adăugarea unui element într-o poziţie dată este esenţial să
putem împărţi lista în două subliste; pentru ştergerea unui element, în trei
subliste. Partiţionarea este de obicei transparentă, adică parte a altor operaţii.
Partiţionarea pentru un tablou nu este posibilă.
e) Regăsirea. Returnarea (regăsirea) unei valori dintr-o listă implică
localizarea unui element (intrări) care conţine acea valoare – deci o căutare.

1.3.3.1 Lista simplu înlănțuită

O listă simplu înlănţuită este formată dintr-o colecţie de elemente de


acelaşi tip. Fiecare element conţine în afară de elementul propriu-zis şi o
legătură care ne spune unde putem găsi un alt element din mulţime. Elementele
listei vor fi numite şi noduri. Ideea este că fiecare nod dintr-o listă simplu
înlănţuită contine informaţii despre cum putem localiza un alt nod dintr-o
mulţime de noduri. Accesul imediat la fiecare nod din mulţime nu este necesar
pentru că fiecare nod conduce la un altul, la fel cu un şir de pietre pe care putem
sări de pe un mal pe celălălt al unui pârău. Iată o ilustrare a acestui model:
Cap

E1 E2 En- En
1
NIL

Astfel, un nod în listă este structurat, este o înregistrare cu câmpurile


Element şi Legătură. Câmpul Legătură este de tip ‘adresa a unui alt nod’,
referinţă a unui nod. Astfel, variabila Cap conţine adresa nodului 1, nodul 1 are
o legătură spre nodul 2 şi aşa mai departe, legătura ultimului nod fiind NULL
(care nu este adresa nici unui nod).
În multe aplicaţii este convenabil ca toate listele să aibă ultima legătură spre un
nod special, un nod santinelă universal. Valori particulare pentru nodul
santinelă pot să conducă la simplificarea unor algoritmi de prelucrare a listelor.
Alegerea aceasta este o problemă de stil. În continuare mă voi referi la liste
care au legătura de la ultimul nod spre NULL. Pentru unele aplicaţii este
convenabil să avem două adrese la nodurile listei, numite de obicei Cap şi
Curent.
Cap Curent

E1 E2 En- En
1
NIL

Specificarea structurii de listă simplu înlănţuită este dată în continuare:


Elemente. Elementele sunt de acelaşi tip (notat în continuare TElement). Ne
vom referi uneori la elemente prin noduri, în sensul că elementul este conţinut
de un nod (ce mai conţine şi o adresă a altui nod).
Structura. Relaţiile dintre noduri (elemente) sunt liniare. Fiecare nod are un nod
(element) succesor unic, exceptând ultimul nod (element) care nu are succesor.
Dacă lista este nevidă atunci Cap este adresa primului nod din listă, altfel are
valoarea NULL. De asemenea, în listă vom avea un nod curent care va indica
asupra cărui element din listă vor fi aplicate unele operaţii.
Operaţii:
Crează(L)
Precondiţie: Receptorul este lista L. L este într-o stare nedefinită.
Postcondiţie: L este vidă.
Distruge(L)
Precondiţie: Receptorul este lista L.
Postcondiţie: L este vidă.
Vidă(L)
Precondiţie: Receptorul este lista L.
Postcondiţie: Returnează TRUE dacă lista L nu conţine noduri şi FALSE în
caz contrar.
Prim(L)
Precondiţie: Receptorul este lista L.
Postcondiţie: Curent referă primul nod (element), adică nodul referit de Cap.
Succ(L)
Precondiţie: Receptorul este lista L.
Postcondiţie: Curent referă nodul (elementul) ultim din lista.
Extrage(L,Element)
Precondiţie: Receptorul este lista L.
Postcondiţie: dacă Curent este valid Element=elementul referit de curent şi
operaţia returnează TRUE, altfel returnează FALSE şi elementul este nedefinit.
Inserează(L, Element)
Precondiţie: Receptorul este lista L şi Element este valoarea care se
inserează.
Postcondiţie: Dacă există memorie suficientă pentru încă un nod, Element
este plasat într-un nod nou ce este inserat înainte de nodul curent; Curent
referă nodul inserat.
Şterge(L,Element)
Precondiţie: Receptorul este lista L.
Postcondiţie: Dacă Curent este valid atunci Element=elementul referit de
curent, nodul curent este eliminat din listă şi operaţia returnează TRUE, altfel
returnează FALSE şi elementul este nedefinit.
Alte structuri de date care apar frecvent în aplicaţii sunt cele liniare.
Caracteristica acestora este că elementele lor sunt ‘aşezate’ liniar sau circular.
Accesul de la un element la altul din structură înseamnă o anumită parcurgere
secvenţială a elementelor din structură.
Astfel, printr-o structura liniară înţelegem o mulţime finită de elemente care este
sau vidă, sau conţine un singur element sau:
- există un unic element numit primul;
- există un unic element numit ultimul;
- fiecare element, exceptând ultimul, are un succesor unic;
- fiecare element, exceptând primul, are un predecesor unic.
Vom considera în continuare două cazuri particulare de structuri liniare.
Dacă elementele sunt ordonate prin poziţia lor atunci structura o vom numi lista
liniară. Dacă elementele sunt ordonate crescător sau descrescător după
valorile unor chei, atunci vom vorbi despre o listă ordonată.
Prin lista (liniară) înţelegem o structură liniară în care elementele sunt ordonate
prin poziţia pe care o ocupă în structură. Astfel succesorul şi predecesorul unui
element sunt determinate în funcţie de poziţia elementelor în listă. Specificarea
acestui tip este precizată în continuare:
Elemente. Elementele sunt de acelaşi tip, tipul putând fi oricare.
Structura. Structura este liniară. Fiecare element are asociată o poziţie
unică în structură. Poziţia primului element este 1. Dacă un element are
asociată poziţia k şi el are un succesor atunci succesorul lui este pe poziţia k+1.
Analog, dacă are predecesor acesta este pe poziţia k-1.
Operaţii: Operaţiile asupra listelor permit accesarea, actualizarea,
ştergerea oricărui element. Dacă lista este nevidă atunci ea are un element
curent, asupra căruia vor acţiona cele mai multe dintre operaţii. Putem impune
la specificare şi testul dacă în listă mai există spaţiu pentru memorarea unor
elemente. Deci operaţiile sunt:
Crează(L) {Crează o listă L}
Precondiţie: True
Postcondiţie: Lista L este vidă
NrElem(L) {Funcţie care returnează numărul elementelor listei L}
Precondiţie: True
Postcondiţie: NrElem(L)=numărul elementelor listei L
Plină(L) {Funcţie care returnează True dacă în listă se mai pot insera
elemente şi False în caz contrar}
Succesor(L) {Modifică cursorul în lista L}
Precondiţie: Elementul curent este diferit de ultimul
Postcondiţie: Succesorul elementului curent devine element curent.
Predecesor(L) {Modifică cursorul în lista L}
Precondiţie: Elementul curent este diferit de primul
Postcondiţie: Predecesorul elementului curent devine element curent.
ActPozElem(L,k) {Modifică cursorul în lista L}
Precondiţie: Valoarea lui k trebuie să fie între 1 şi NrElem(L)
Postcondiţie: Elementul curent este cel de pe poziţia k din L.
ExtPozElem(L) {Returnează poziţia elementului curent în lista L}
Precondiţie: Lista L este nevidă
Postcondiţie: PozCrt(L)=poziţia elementului curent din lista L.
ExtElem(L,e) {Extrage valoarea elementului curent din lista L}
Precondiţie: Lista L este nevidă
Postcondiţie: e = valoarea elementului curent din lista L.
ActElem(L,e) {Actualizează valoarea elementului curent}
Precondiţie: Lista L este nevidă
Postcondiţie:Elementul curent din lista L are valoarea e.
Adauga(L,e) {Insereaza un element e dupa cel curent din lista L}
Precondiţie: Lista L nu este plină
Postcondiţie: Inserează e după elementul curent din listă. Elementul
inserat devine element curent.
Inserează(L,e) {Inserează un element e înaintea celui curent în lista L}
Precondiţie: Lista L este plină
Postcondiţie: Inserează e înaintea elementului curent din listă.
Elementul inserat devine element curent.
Şterge(L) {Şterge elementul curent din lista L}
Precondiţie: Lista L este nevidă.
Postcondiţie: Dacă elementul curent este ultimul atunci primul element
va fi cel curent, altfel succesorul celui şters va fi element curent.
Operaţiile cu listele simplu înlănţuite se pot extinde şi la liste dublu înlănţuite,
liste care se deosebesc de cele simplu înlănţuite prin faptul că fiecare nod are
două referinţe, spre succesorul respectiv predecesorul lui, ca în figura
următoare.
Cap

E1 E2 En- En
1
NIL NIL
NIL

Operaţiile cu listele dublu înlănţuite sunt asemănătoare ca şi la cele de la


listele simplu înlănţuite, însă trebuie ţinut cont de faptul că acestea au dublă
referinţă.
1.3.3.2 Lista ordonată

În exemplele precedente a fost considerată structura de listă care permite


utilizatorului să insereze elemente în orice poziţie în listă. Ordonarea după
poziţia elementelor este la discreţia utilizatorului. Vom considera structura de
listă ordonată în care elementele păstrează o ordonare în funcţie de valorile lor
(după o anumită cheie). Această structură nu mai permite controlul utilizatorului
asupra poziţiilor elementelor. Operaţia de inserare va stabili poziţia în care va
fi inserat elementul în listă, în funcţie de relaţia de ordine aleasă între elemente
(în funcţie de cheia stabilită). Specificaţia acestui tip este aceeaşi cu cea a unei
liste, cu următoarele deosebiri:
- referitor la elemente se presupune că există o funcţie cheie care este de
tip simplu sau string, cu proprietatea că în codomeniul ei este definită o relaţie
de ordine <;
- privind structura, elementele din listă vor satisface cheie(ei)< cheie(ei+1),
pentru i=1,2,…,n-1.
- toate operaţiile de la liste au aceeaşi specificaţie, dar lipsesc operaţiile
Inserează şi Adaugă, dar Actualizează va fi redescrisă în continuare împreună
cu două operaţii noi Inserează şi Caută:
Inserează(L,e) {inserează elementul e în lista ordonată L}
Precondiţie: Lista nu este plină (se mai pot memora elemente) şi nu conţine
un element cu cheia acestui element e.
Postcondiţie: Elementul e este inserat în L. L este lista ordonată. Elementul
inserat devine element curent.
Caută(L,e) {Caută dacă în listă există un element cu aceeaşi cheie ca şi e}
Precondiţie: Lista este nevidă.
Postcondiţie: Dacă există un element cu cheia egală cu cheia lui e, funcţia
returnează True şi elementul căutat devine element curent, altfel returnează
False.
Actualizează(L,e) {Actualizează elementul curent din lista L cu valoarea e}
Precondiţie: Lista L este nevidă. Cheia elementului curent este aceeaşi cu
cheie(e).
Postcondiţie: Elementul curent ia valoarea lui e.
1.3.4. Arbore binar

Un arbore orientat este format dintr-o mulţime finită de noduri cu proprietăţile:


- Există un nod special numit rădăcină.
- Nodurile rămase, dacă există, sunt partiţionate în submulţimi disjuncte,
fiecare submulţime formând un arbore orientat. Aceste submulţimi se numesc
subarbori ai rădăcinii.
Exemplu:

ION

VLAD IOANA IULIA

ANA MARIA PETRU


ION este nodul rădăcină, submulţimile disjuncte de noduri fiind {IOANA, ANA,
MARIA}, {VLAD} si {IULIA, PETRU}, fiecare din ele fiind un arbore orientat.
Dacă pornim de la un arbore orientat şi ordonăm (după poziţie) subarborii
fiecărui nod, obţinem un arbore ordonat.
Definiţie:
Un arbore ordonat conţine o mulţime finită de noduri.
- Unul din noduri este numit rădăcină.
- Restul nodurilor sunt partiţionate în submulţimi disjuncte T 1, T2,…,Tm,
care sunt ordonate prin indicii lor, fiecare din submulţimi formând la rândul lor
un arbore ordonat.
Un arbore ordonat în care fiecare nod poate să aibă cel mult doi subarbori se
numeşte arbore binar. Mai exact, putem defini un arbore binar ca având
următoarele proprietăţi:
- Fiecare nod poate avea cel mult doi subarbori – altfel spus cel mult doi fii;
- Fiecare subarbore este identificat ca fiind subarbore stâng, respectiv
subarbore drept;
- Un arbore binar poate fi vid.
Rădăcina unui arbore binar este la nivelul 0, iar fiul unui nod este la un nivel cu
unu mai mare decât nodul. Adâncimea unui arbore binar este nivelul maxim al
tuturor nodurilor. De exemplu, adâncimea arborelui binar din figura următoare
este:
Nivel

0 A

1
B C

2 D E

3 F G

H
4

Numărul maxim de noduri de pe nivelul 0 este 1, pe nivelul 1 este 2, pe nivelul


2 este 2*2=4,….. În general:
- Numărul maxim de noduri pe nivelul n este 2n.
- Numărul maxim de noduri într-un arbore binar de adâncime i este 2i+1-1.
Un arbore binar este plin dacă fiecare nod interior are doi fii. Un arbore binar
este complet dacă toate nodurile frunză sunt pe cele mai joase nivele şi cele
de pe ultimul nivel sunt situate cât se poate spre stânga.

A
Exemplu: arbore binar plin
B C

D E

F G
Exemplu: arbore binar complet
A

B C

D E
F G

H I J
În contrast cu structurile precedente, arborii binari au formă; forma lor este
determinată de numărul nodurilor şi de distanţele dintre diferite noduri. Eficienţa
algoritmilor pentru prelucrarea arborilor binari este afectată de forma arborilor
binari.
Trăsătura fundamentală a arborilor binari este ramificarea (parte esenţială
a limbajului şi a gândirii). Arborii binari reduc ramificarea la o formă elementară,
în două. Fiecare ramură urmată într-un arbore binar înseamnă şi una care nu
va fi urmată. Structura de arbore binar este un instrument de decizie, un
separator de mulţimi.

1.3.4.1. TAD Arbore binar

Ca şi în cazul celorlalte structuri (înlănţuite, liniare etc.) elementele trebuie


să fie de acelaşi tip (notat TElement). Un arbore este vid sau este un nod (numit
rădăcină) împreună cu doi arbori binari disjuncţi între ei şi faţă de rădăcină
numiţi subarborii stâng, respectiv drept ai rădăcinii. Fiecare nod, exceptând
rădăcina are un părinte unic. Fiecare nod are zero, unul sau doi fii. Operaţiile
vor fi descrise în continuare ţinând cont de două referinţe: a rădăcinii arborelui
şi a nodului curent – elementului curent.
RAD

A
B C

D E

F G

Crează(A) {Crează un arbore binar}


Postcondiţie: Arborele A este vid.
Vid(A) {Verifică dacă arborele A este vid}
Postcondiţie: Vid(A) este True dacă A este vid şi False altfel.
ActElem(A,e) {Actualizează elementul curent din arbore}
Precondiţie: Arborele A este nevid.
Postcondiţie: Elementul din nodul curent primeşte valoarea e.
ExtElement(A,e) {Extrage valoarea elementului curent din arbore}
Precondiţie: Arborele A este nevid.
Postcondiţie: e primeşte valoarea elementului din nodul curent al lui A
Traversează(A, Ordine) {Prelucrează fiecare element din structură o singură
dată}
Precondiţie: Arborele A este nevid.
Postcondiţie: Fiecare nod este procesat o singură dată. Ordinea procesării
este dependenţa de parametrul Ordine:
- Preordine: fiecare nod este procesat înaintea fiecărui nod din
subarborii lui;
- Inordine: fiecare nod este procesat după toate nodurile din
subarborele stâng şi înainte de toate din subarborele drept;
- Postordine: fiecare nod este procesat după toate nodurile din
subarborii lui;
MutăCursor(A, Relativ,Esec) {Stabileşte elementul curent în arbore}
Precondiţie: Arborele A este nevid.
Postcondiţie: Stabileşte nodul curent în funcţie de valoarea Relativ:
- Rădăcina: Nodul rădăcină este cel curent
- Părinte: Dacă nodul curent are părinte atunci acesta devine curent,
altfel Eşec este True;
- Stânga: Dacă nodul curent are fiu stâng atunci acesta devine nod
curent, altfel Eşec ia valoarea True;
- Dreapta: Dacă nodul curent are fiu drept atunci acesta devine nod
curent, altfel Eşec ia valoarea True.
Inserează(A,e,Relativ, Esec) {Inserează un element în arbore}
Postcondiţie: Inserează elementul e în arborele A, în funcţie de Relativ.
Elementul inserat devine cel curent. Dacă Relativ = Rădăcina atunci A trebuie
să fie vid, altfel A este nevid. Poziţia în care este inserat depinde de valoarea
lui Relativ:
- Rădăcina: e este elementul din nodul rădăcină;
- Părinte: Eşec ia valoarea True;
- Stânga: Dacă nodul curent nu are fiu stâng atunci acestuia i se
crează fiu stâng cu valoarea e, altfel Eşec ia valoarea True;
- Dreapta: Dacă nodul curent nu are fiu stâng atunci i se crează fiu
stâng cu valoarea e, altfel Eşec ia valoarea True;
Şterge(A) {Şterge un subarbore}
Precondiţie: Arborele este nevid;
Postcondiţie: Şterge subarborele care are ca rădăcina nodul curent. Nodul
curent este nodul rădăcină.
Structurile de date de tip stivă, coadă şi listă vor fi reluate în capitolul al
doilea al lucrării, într-o implementare dinamică.
CAPITOLUL

Capitolul 2 - Tipul referinţă. Structuri


de date dinamice. Operaţii aritmetice
cu pointeri

2.1. Pointeri

Din punctul de vedere al unui programator, memoria calculatorului se


prezintă ca o succesiune de octeţi, fiecare octet având o adresă binară bine
stabilită. Aceşti octeţi sunt identificaţi prin numere cuprinse între 0 şi n-1. Putem
numi această adresă numărul de ordine al unui octet. Pentru fiecare tip de dată
cunoscut există o anumită logică potrivit căreia se face memorarea efectivă a
conţinutului. O variabilă statică folosită în program are un nume (simbolic), o
valoare şi o adresă la care o găsim memorată (adresa primului octet din cei p
octeţi consecutivi ocupaţi de variabilă). În general, în limbajele evoluate nu este
necesar ca programatorul să cunoască adresa la care se găsesc variabilele cu
care lucrează.
Pentru alocarea dinamică se utilizează tipul de date referinţă (pointer).
Structurile dinamice, neavând nume, sunt accesibile prin intermediul altor
variabile, care conţin adresele lor, şi în felul acestea “le indică”. Aceste variabile
se numesc pointeri şi formează tipul referinţă. Pointerii sunt variabile statice
obişnuite şi au ca valori adrese, care pot fi adresele de început ale unor structuri
dinamice sau a unei componente a unei asemenea structuri. Deci, accesul la o
variabilă dinamică, indicată de o variabilă pointer se realizează prin adresarea
indirectă a variabilei pointer. Această indirectare se pune în evidenţă prin
ataşarea operatorului unar ‘*’ (operator de indirectare) înainte de numele
variabilei pointer. Variabila dinamică, indicată de o variabilă pointer, se va referi,
nu printr-un nume propriu, ci prin intermediul pointerului său: *variabila de tip
pointer.
Astfel, în construcţia *p operatorul ‘*’ se consideră ca fiind un operator unar
care furnizează valoarea din zona de memorie a cărei adresă este conţinută în
p (p-variabila de tip pointer,*p -variabila dinamică indicată de pointerul p).
Operatorul unar ‘*’ are aceeaşi prioritate ca şi ceilalţi operatori unari din limbajul
C. Pentru a atribui unui pointer adresa unei variabile, putem folosi operatorul
unar adresă ‘&’. Astfel, dacă dorim ca p să pointeze spre x, putem utiliza
atribuirea p=&x.

2.1.1. Declararea unui pointer

Un pointer se declară ca orice variabilă, cu singura deosebire că numele


este precedat de caracterul ‘*’. Astfel, dacă, de exemplu, dorim să declarăm
variabila p utilizată anterior pentru a păstra adresa unei variabile de tip int x,
vom folosi declaraţia int *p. Tipul int stabileşte în acest caz faptul că p conţine
adrese de zone de memorie alocate datelor de tip int. Declaraţia lui p se poate
interpreta în felul următor: *p reprezintă conţinutul zonei de memorie spre care
indică p, iar acest conţinut are tipul int.
În general, un pointer se declară prin:

tip *nume;

ceea ce înseamnă că nume este un pointer care pointează spre o zonă de


memorie ce conţine o dată de tipul tip.
O variabilă pointer dată se poate referi la variabilele indicate de un anumit
tip, conform definirii sale. Există totuşi şi pointerul nul identificat prin cuvântul
rezervat NULL şi care este compatibil cu orice tip pointer. De asemenea, există
cazuri în care dorim ca un pointer să fie utilizat cu mai multe tipuri de date. În
acest caz, la declararea lui nu dorim să specificăm un tip anume.
Aceasta se realizează folosind cuvântul cheie void:

void *nume;

Spaţiul necesar variabilelor alocate dinamic se rezervă într-o zonă


specială de memorie numită HEAP. Aşadar, valorile unui tip reper reprezintă
fie adrese din Heap ale unor variabile dinamice de tipul specificat în definiţia
tipului reper respectiv, fie valoarea constantei standard NULL.
Dimensiunile pointerilor (numărul de octeţi ocupaţi) depind de
implementarea limbajului. Pointerii pot fi, după tipul entităţii adresate, de două
tipuri:

- pointeri de date
- pointeri de funcţii
Exemple:
Fie declaraţiile:
int x,y ;
int *p;
1) y=x+100; este echivalentă cu secvenţa
p=&x;
y=*p+100; /* lui y i se atribuie suma dintre conţinutul zonei a cărei
adresă se afla în p şi 100*/
2) x=y; este echivalentă cu secvenţa
p=&x;
*p=y; /*conţinutul zonei a cărei adresă se află în p devine egal cu
valoarea lui y*/
3) x++; este echivalentă cu secvenţa
p=&x;
(*p)++; /*continuţul zonei a cărei adresă se află în p se măreşte cu
1*/
4) Fie funcţia f următoare:
void f(int x,int y)
{
int aux ;
aux=x;
x=y;
y=aux;
}
Un apel de forma f(a,b); nu are nici un efect, deoarece la acest apel
valoarea lui a se transferă parametrului x, iar valoarea lui b se transferă
parametrului y. Apoi funcţia interschimbă valorile parametrilor x şi y, însă prin
aceasta valorile parametrilor actuali a şi b rămân nemodificate. Pentru a realiza
o interschimbare a valorilor acestor variabile, este necesar să se transfere nu
valorile, ci adresele variabilelor. Acest lucru este posibil dacă modificăm apelul
în felul următor: f(&a,&b) - transmiterea parametrilor prin referinţă. Având în
vedere acest lucru, funcţia va suferi modificări:
void f(int* x,int* y)
{
int aux ;
aux=*x;
*x=*y;
*y=aux;
}
1) Utilizarea tipului void* implică conversii explicite de tip
int i;
void *p;
………..
p=&i; /* lui p i se atribuie adresa zonei de memorie alocată variabilei
i*/
*p=10; /* nu este acceptată de compilator deoarece tipul datei spre
care indică p este nedeterminat*/
*(int*)p=10; /* este corectă deoarece tipul void* este convertit spre
int* */
Tipul void* poate fi convertit în mod explicit spre orice tip de pointer.
Modificatorul const poate fi folosit şi la pointeri în sensul că se pot realiza
pointeri constanţi sau pointeri către valori constante. Fie declaraţiile următoare:
char *s= ”ABC”; /*pointer la un şir*/
const char *s1=”ABC”; /*pointer la un şir constant*/
char * const s2=”ABC”; /*pointer constant*/
const char* const s3=”ABC”; /*pointer constant la un şir constant*/
Am folosit toate combinaţiile posibile ale specificatorului const cu pointerii.
Astfel, s este un pointer variabil către un şir neavând nici o restricţie de
constantă, s1 este un pointer către un şir constant, s2 este un pointer de adresă
constantă către un şir, iar în ultimul caz s3 este un pointer de adresă constantă
către un şir constant.

2.1.2. Operaţii cu pointeri

1. Atribuirea: o variabilă de tip pointer primeşte valoarea unei alte variabile sau
funcţii de acelaşi tip pointer cu ea sau este iniţializată cu constanta NULL.
Înainte de atribuire: p *p

q *q

După atribuirea p=q:


p

q
2. Operaţii de incrementare şi decrementare

Asupra variabilelor de tip pointer operatorii de incrementare şi


decrementare se execută altfel decât asupra datelor de alte tipuri.
- operatorul de incrementare (++) aplicat asupra unui operand de tip pointer
spre tipul t măreşte adresa conţinută de operand cu numărul de octeţi necesari
pentru a păstra o dată de tipul t;
- operatorul de decrementare (--) se execută în mod analog, cu singura
diferenţă ca în loc să se mărească valoarea pointerului, ea se micşorează cu
numărul corespunzător de octeţi.
Aceste operaţii sunt deosebit de utile când au loc prelucrări de tablouri.
Fie următoarele declaraţii:
int tab[100] ;
int *p;
int i;
Fie atribuirea p=&tab[i]; unde 0<i<100. În acest caz, instrucţiunea p++;
măreşte valoarea lui p cu 2 (tipul int se păstrează pe doi octeţi) şi deci în acest
moment p conţine adresa elementului tab[i+1]. În mod analog, instrucţiunea p-
-; micşorează valoarea lui p cu 2 şi deci în urma acestei decrementări p conţine
adresa elementului tab[i-1].

3. Adunarea şi scăderea unui întreg dintr-un pointer


Dacă p este un pointer, sunt corecte expresiile de forma: p+n şi p-n unde
n este de tip întreg.
- Expresia p+n măreşte valoarea lui p cu cu n*t, unde t este numărul de octeţi
necesari pentru a memora o dată de un tip spre care indică p;
- În mod analog, expresia p-n micşorează valoarea lui p cu n*t.
Dacă x este un tablou de tipul t, atunci x este pointer, deci o expresie de
forma x+n este corectă şi deoarece x este un pointer spre primul său element
x[0], x+n va fi un pointer spre elementul x[n].
Rezultă că valoarea elementului x[n] se poate
reprezenta prin expresia *(x+n) care este o expresie
cu pointeri.

Astfel, o expresie cu indici se poate înlocui printr-o expresie cu pointeri.


Acest lucru permite ca la tratarea tablourilor să se folosească expresii cu
pointeri în locul variabilelor cu indici

4. Compararea a doi pointeri

Doi pointeri care indică spre elementele aceluiaşi tablou pot fi comparaţi
folosind operatorii de relaţie şi de egalitate.
Astfel, dacă p şi q sunt doi pointeri care indică spre elementele t[i]
respectiv t[j] ale tabloului t, expresia p<q are sens şi ea este adevărată dacă
i<j. De asemenea, p!=q are valoarea adevărat dacă i  j.
Observaţii:
a) Pointerii nu pot fi comparaţi decât în condiţia amintită mai sus.
b) Operatorii de egalitate ( = = şi ! = ) permit totuşi compararea unui pointer cu
constanta simbolică NULL. Aceste comparaţii permit să stabilim dacă un
pointer conţine o adresă sau nu.

5. Diferenţa a doi pointeri

Doi pointeri care indică spre elementele aceluiaşi tablou pot fi scăzuţi.
Rezultatul diferenţei a doi pointeri este definit astfel: fie a un tablou de un tip
oarecare şi p, q doi pointeri: p conţine adresa elementului a[i], iar q conţine
adresa elementului a[i+n]. Atunci diferenţa q-p are valoarea n.
Exemple:
1) unsigned lungime(char *x)
/* returnează lungimea şirului spre care pointează x */
{
int i;
for(i=0;*x!=’\0’;i++)
x++;
return i;
}
Observaţii:
- Condiţia *x!=’\0’ poate fi înlocuită cu *x, deoarece *x!=’\0’ este adevarată când
*x este diferit de zero şi invers.
- Ciclul for poate fi compactat şi mai mult: for(i=0;*x++ ;i++) ;

2) void copiază(char *x, char *y)


/* copiază şirul spre care indică y în zona spre care indică x*/
{
while(*x++=*y++);
}
Expresia de atribuire *x++=*y++ realizează atribuirea *x=*y utilizând valorile
neincrementate ale lui x şi y. Dacă valoarea atribuită este diferită de zero,
expresia de atribuire se consideră adevarată, deci ciclul continuă. În momentul
în care se atribuie valoarea 0, adică s-a ajuns la sfarşitul şirului spre care indică
y, expresia de atribuire este falsă şi ciclul se întrerupe.

3) void concatenează(char *x,char *y)


/* concatenează şirul spre care indică y la sfârşitul şirului spre care indică x*/
{
/* se avansează cu pointerul x până la sfârşitul şirului */
while(*x) x++;
/* se copiază şirul spre care indică y în zona spre care indică x */
while(*x++=*y++);
}
4) int compară(char *x, char *y)
/* returnează o valoare negativă dacă x<y, zero dacă x=y respectiv o valoare
pozitivă dacă x>y */
{
while(*x==*y)
{
/* ciclul funcţionează cât timp caracterele curente din cele două şiruri sunt
egale*/
if(*x==’\0’)
/* dacă s-a ajuns la sfârşitul sirului din x, s-a ajuns şi la cel din y şi toate
caracterele corespunzătoare au fost egale, deci şirurile sunt egale */
return 0 ;
/* se trece la perechea următoare de caractere */
x++; y++;
}
/* deoarece ciclul s-a terminat, rezultă că s-au găsit cel puţin două caractere
diferite */
return *x-*y ;
/* dacă diferenţa caracterelor este negativă atunci x<y, altfel x>y */
}

2.2. Legătura dintre pointeri şi tablouri. Folosirea pointerilor


şi tablourilor ca parametri în funcţii

În primul rând, numele unui tablou este un pointer deoarece el are ca


valoare adresa primului său element. Totuşi există o diferenţă între numele unui
tablou şi o variabilă de tip pointer, deoarece dacă unei variabile de tip pointer i
se poate atribui o adresă, acest lucru nu se poate realiza pentru numele unui
tablou, el fiind întotdeauna un pointer spre primul element al tabloului, deci un
pointer constant.
Exemple:
1) Fie int a[100] un tablou. Următoarele secvenţe sunt echivalente, deoarece
fiecare din ele reprezintă adresa primului element din tablou:
1) a 2) &a[0] 3) &*a
Prima expresie reprezintă cele spuse înainte conform definiţiei. În a doua
expresie, &a[0] reprezintă adresa elementului de index 0 al tabloului. Cum 0
reprezintă poziţia primului element al tabloului, rezultă că a doua expresie
reprezintă adresa de început a tabloului. Compunerea operatorilor & şi * îşi
anulează semnificaţia, deci a treia declaraţie este echivalentă tot cu a.
2) Fie declaraţiile:
int a[10],b[10],*c;
………….
a=b; /* greşit deoarece a şi b sunt pointeri constanţi */
c=a; /* corect deoarece c este un pointer variabil */
b=c; /* greşit deoarece chiar dacă c este un pointer variabil, pointerul din
partea stânga a atribuirii, b, este constant */
Un tablou poate fi declarat incomplet, prin omiterea dimensiunii, dacă:
- Declaraţia se referă la un tablou extern pentru care s-a rezervat spaţiu în
alt fişier sursă;
- Tabloul declarat este un parametru formal al unei funcţii; în acest caz ea
este echivalentă cu cea a unui pointer;
- Declaraţia conţine o iniţializare pe baza căreia se determină numărul de
elemente din tablou.

2.2.1. Tratarea tablourilor unidimensionale folosind pointeri

Aşa cum am precizat anterior, numele unui tablou este un pointer constant
care are ca valoare adresa primului său element. Pentru declaraţia tip tab[…];
identificatorul tab are ca valoare adresa elementului tab[0], adică valoarea sa
este &tab[0].
Fie declararea: tip *p; Atunci o atribuire de forma p=tab; este corectă şi în
urma acestei atribuiri, p are ca valoare tot adresa lui tab[0].
Dacă tab este un parametru formal ce corespunde unui parametru efectiv
care este un nume de tablou, tab poate fi declarat fie ca tablou, fie ca un pointer
spre tipul tabloului.
Exemplu:
Fie funcţia: unsigned lungime(char tab[]) care se apelează prin expresii de
atribuire de forma: a = lungime(x); unde x este un tablou de tip caracter în care
se păstrează şirul de caractere pentru care se determină lungimea. Antetul
funcţiei lungime poate fi schimbat în felul următor: unsigned lungime(char *tab);
Identitatea dintre cele două declaraţii rezultă din cele spuse mai sus,
deoarece declaraţia char tab[]; defineşte pe tab ca numele unui tablou de tip
character, dar atunci el este un pointer spre caractere, deci se poate declara
prin char *tab.
În concluzie, dacă avem ca parametru formal un tablou unidimensional tab
în antetul unei funcţii f atunci se foloseşte unul din formatele:
……f(tip tab[]) sau …..f(tip *tab).
Indiferent care din antete se alege, în corpul funcţiei f se pot folosi atât
variabila cu indici: tab[exp] cât şi expresii cu pointeri *(tab+exp) pentru a face
acces la elementele tabloului tab.
În paragraful anterior am arătat ca în general, dacă tab este un tablou
unidimensional de tipul tip, atunci tab+n este chiar adresa elementului tab[n].
Deci: x=tab[n] sau x=*(tab+n) sunt atribuiri care au acelaşi efect (atribuie lui x
valoarea elementului tab[n]). Expresiile cu pointeri pot fi folosite şi în stânga
operatorului de atribuire, adică:
tab[n]=x si *(tab+n)=x
au acelaşi efect.
Aşadar, variabilele cu indici se pot echivala prin expresii cu pointeri. Este
posibil să procedăm şi invers, adică să înlocuim expresiile cu pointeri prin
variabile cu indici, deşi acest lucru nu este recomandabil.
De exemplu, fie declaraţia tip *p=(tip *)malloc(…);

Expresia *(p+n) este echivalentă cu expresia p[n]

Exemple:
1. Definesc o funcţie care realizează următoarele:
- afişează un text explicativ definit de primul parametru al funcţiei;
- citeşte un întreg de tip int şi-l păstrează într-o zonă spre care indică cel de-al
doilea parametru al funcţiei;
- returnează 0 la întâlnirea sfârşitului de fişier şi 1 altfel;
Funcţia testează dacă la intrare s-a tastat un întreg. În caz că la intrare nu s-a
aflat un întreg, se afişează un mesaj de eroare şi se reia citirea întregului:
int cit(char text[], int *n)
/* - afişează şirul de caractere păstrat în tabloul text;
- citeşte întregul de la intrarea standard şi-l păstrează în zona spre care indică
n;
- returnează : 0 – la întâlnirea sfârşitului de fişier
1 – altfel */
{
char t[255] ;
for( ;;)
{
printf(text);
if(gets(t)==0) /* s-a întâlnit sfârăitul de fişier */
return 0;
if (sscanf(t,”%d”,n)==1) return 1;
/* nu s-a tastat un întreg deoarece sscanf nu a returnat 1; se afişează mesaj şi
se reia citirea numărului */
printf( ”Nu s-a tastat un intreg\n”) ;
printf( ”Se reia citirea intregului\n”);
}
}
Observaţie:
În funcţia cit s-au folosit funcţiile gets şi sscanf pentru a realiza recuperarea
după eroare.

2. Funcţia citlim definită în continuare citeşte un întreg care aparţine la un


interval dat [inf, sup]. Ea utilizează funcţia cit definită în exemplul precedent.
int cit (char text[], int *n)
{

}
int citlim(char text[], int inf, int sup, int *n)
/* - afişează şirul de caractere păstrat în tabloul text;
- citeşte un întreg care aparţine intervalului [inf,sup] şi-l păstrează în zona spre
care indică n;
- returnează: 0 – la întâlnirea sfârşitului de fişier;
1 – altfel */
{
for( ;;)
{
if (cit(text,n)==0) return 0; /* s-a tastat <Ctrl> Z */
if(inf<=*n && *n<=sup) return 1;
printf( ”Nu s-a tastat un intreg\n”);
printf( ”din intervalul [%d,%d]\n”,inf,sup);
printf( ”Se reia citirea intregului\n”);
}
}

1.2.2. Tablouri de pointeri şi pointeri la tablouri

Pointerii fiind variabile, pot fi folosiţi pentru a forma alte tipuri de date
compuse. Spre exemplu se pot forma tablouri de pointeri. Sintaxa generală de
utilizare este:

Tip *tablou[dim];

Exemple:
1. Declaraţia char *s[25]; reprezintă un tablou de 25 pointeri la caracter.
2. Sortarea unor şiruri de caractere:
#include<iostream.h>
#include<string.h>
void sort_lines(char *tp[], int n)
{
int i, sort=0;
char *temp;
while (!sort)
{
sort=1;
for(i=0;i<n-1;i++)
if(strcmp(tp[i],tp[i+1])>0)
{
strcpy(temp,tp[i]);
strcpy(tp[i],tp[i+1]);
strcpy(tp[i+1],temp);
sort=0;
}
}
}
int main()
{
int i;
char *sir[]=({“manual”}, {“carte”}, {“mare”},
{“12345”}, {“4542”});
sort_lines(sir,5);
for(i=0;i<5;;i++)
cout<<sir[i]<<’ ‘;
cout<<endl;
return 0;
}

Pentru a arăta că folosim pointeri la tablouri (şi nu tablouri la pointeri)


avem pentru declaraţie sintaxa următoare:

Tip (*p) [dim] ;

Diferenţa dintre pointerii la tablouri de un tip şi tablourile de pointeri la


acelaşi tip este modul de stabilire a unităţii de deplasare.
În acest sens, sunt concludente următoarele exemple:
1. În definiţia
a) int (*x) [50];
x este un pointer la un tablou de 50 întregi.
b) int* x[50];
x este un tablou de 50 pointeri la întregi.
Se observă diferenţa de semnificaţie care are loc o dată cu folosirea
parantezelor.

2. Fie declaraţia
short (*n) [10];
În acest exemplu n reprezintă adresa unui tablou de 10 întregi. Chiar
dacă acest lucru este iniţial sinonim cu adresa de început a tabloului, diferenţa
este esenţială: aritmetica acestora cu numerele întregi. Astfel, incrementarea
lui n va avea ca efect deplasarea cu 10 întregi de tip short (deci saltul este de
20 de octeţi), pe când în cazul unui pointer la întreg deplasarea ar fi fost de 2
octeţi.
Astfel, în programul:
/* deplasarea pentru un tablou la pointer */
#include<stdio.h>
void main()
{
short *a, (*b) [10], c[10];
a=c;
b=c;
printf(“\nInainte de incrementare:\n Adresa pointer la intreg:%p\t Adresa
pointer la tablou de intregi: %p”,a,b);
a++ ;
b++ ;
printf(“\nDupa incrementare:\n Adresa pointer la intreg:%p\t Adresa
pointer la tablou de intregi: %p”,a,b);
}

S-au obţinut rezultatele:

Înainte de incrementare:
Adresa pointer la întreg: FFE2 Adresa pointer la tablou de întregi:
FFE2
După incrementare:
Adresa pointer la întreg: FFE4 Adresa pointer la tablou de întregi:
FFF6

3. Declaraţiile următoare sunt corecte:


void matr(int *a[], int n); /* a este un tablou de pointeri */
void matr(int **a, int n);
În ambele antete, primul parametru poate fi folosit pentru matrici de
dimensiune variabilă.

1.2.3. Tratarea tablourilor bidimensionale folosind pointeri


Numele unui tablou bidimensional, la fel ca numele unui tablou
unidimensional, are ca valoare adresa primului element al tabloului.
Fie, de exemplu, declaraţia:

tip tab[…][…] ;

Atunci tab are ca valoare adresa lui tab[0][0].


Dacă în cazul tablourilor unidimensionale, tab+n este adresa elementului
tab[n], adică &tab[n], în cazul tablourilor bidimensionale, expresia tab+n este
adresa elementului tab[n][0].
Această interpretare rezultă din faptul că un tablou bidimensional trebuie
considerat ca fiind un tablou de tablouri unidimensionale. În general, un tablou
k-dimensional este un tablou de tablouri k-1 dimensionale.
Fie, de exemplu, declaraţia: tip tab[m][n];
Tabloul tab poate fi privit ca un tablou de tablouri unidimensionale. Astfel,
tab[0], tab[1], …, tab[m-1] sunt cele m elemente ale lui tab şi fiecare este un
pointer spre câte un tablou unidimensional de n elemente.
De aici rezultă că tab[0] are ca valoare adresa lui tab[0][0], tab[1] are ca valoare
adresa lui tab[1][0], iar

în general tab[i] are ca valoare adresa lui tab[i][0].


Cum *(tab+i) are ca valoare chiar tab[i], rezultă că
tab[i][0] are aceeaşi valoare cu *(*(tab+i)).

De asemenea, tab[i]+j are ca valoare adresa lui tab[i][j]. Deci tab[i][j] are aceeaşi
valoare ca şi expresia *(tab[i]+j), iar aceasta din urmă are aceeaşi valoare cu
expresia *(*(tab+i)+j).

Înseamnă că atribuirile *(*(tab+i)+j)=x si tab[i][j]=x sunt


echivalente.

Dacă tab este un tablou unidimensional declarat prin: tip tab[…]; atunci
tab are tipul tip* adică este pointer spre tip.
Dacă tab este un tablou bidimensional declarat prin tip tab[m][n]; atunci
tab are tipul tip (*)[n]; adică pointer spre un tablou de n elemente de tipul tip.
Menţionez că în declaraţia de mai sus m şi n sunt expresii constante.
Să presupunem că tab este parametru la apelul funcţiei f: …f(tab). În
acest caz, parametrul formal al funcţiei f poate fi declarat în următoarele
moduri:…f(tip t[][n]) sau …f(tip(*p)[n]).
Fie declaraţia: tip *tab1[n];
În acest caz, tab1 este un tablou unidimensional de pointeri spre tipul tip ,
adică fiecare element din cele n ale tabloului tab1 este un pointer spre tip.
Tablourile tab şi tab1 nu trebuie confundate. Tabloului tab i se alocă o memorie
de m*n*sizeof(tip) octeţi. Tabloului tab1 i se alocă n*sizeof(tip*) octeţi.
Dacă o funcţie q are la apel ca parametru pe tabloul tab1:…q(tab1)
atunci parametrul formal al funcţiei q poate fi declarat în următoarele
moduri:…q(tip *p[]) sau …q(tip **p).
Exemple:
1. Fie declaraţiile:
double tab[2][3]={{0,1,2},{3,4,5}}
double *p;
Atunci avem:
VALOAREA
INSTRUCŢIUNI ELEMENTUL AFIŞAT
ELEMENTULUI
p=tab[0];
tab[0][0] Zero
printf(”%g”,*p) ;
p=tab[1];
tab[1][0] 3
printf(”%g”,*p) ;
printf(”%g”,*(*(tab))) ; tab[0][0] Zero
printf(”%g”,*(*(tab+1)+2)) ; tab[1][2] 5

2. Considerăm funcţia f definită astfel:


void f (double (*p)[3])
{
int i,j;
for (i=0;i<2;i++)
for(j=0;j<3;j++)
printf(“%g ”,p[i][j]);
}
La apelul f(tab); unde tab este tabloul definit la exemplul anterior, se
afişează valorile elementelor lui tab separate de câte un spaţiu:
0 1 2 3 4 5.
Expresia p[i][j] poate fi înlocuită cu *(*(p+i)+j).
3. Fie declaraţiile:
double *t[2];
double t0[3]={10,11,12};
double t1[3]={13,14,15};
şi atribuirile t[0]=t0; t[1]=t1;
Definim funcţia f1 astfel:
void f1(double *p[])
{

}
unde corpul funcţiei f1 coincide cu al funcţiei f.
La apelul funcţiei f1(t); se listează valorile elementelor tablourilor t0 şi t1,
separate prin câte un spaţiu, adică: 10 11 12 13 14 15
Acelaşi rezultat se obţine dacă antetul lui f1 se schimbă cu: void
f1(double **p).
În ambele situaţii, expresia p[i][j] poate fi schimbată cu *(*(p+i)+j).

2.3. Pointeri la funcţii

Numele unei funcţii este un pointer spre funcţia respectivă. El poate fi folosit ca
parametru efectiv la apeluri de funcţii. În felul acesta, o funcţie poate transfera
funcţiei apelate un pointer spre o funcţie. Aceasta, la rândul ei, poate apela
funcţia care i-a fost transferată în acest fel.
În instrucţiunile în care se atribuie pointeri la funcţii, tipurile de funcţii
trebuie să corespundă exact.
Sintaxa de declaraţie este:

tip functie(*pointer_functie)(lista_parametri);

Exemple:
1. Se observă importanţa folosirii parantezelor rotunde pentru pointeri la funcţii.
Fără acestea nu s-ar mai considera un pointer la funcţie ci o funcţie care
întoarce un pointer de un anumit tip.
a) Fie declaraţia
int *s(int *s1, int *s2);
În acest caz avem o funcţie care întoarce pointer la int.
b) În declaraţia
int (*s)(int *s1, int *s2);
avem un pointer la o funcţie care întoarce o valoare de tip int.
c) În declaraţia
int (*f (int,int)) [10];
În acest caz se defineşte o variabilă de tipul unei funcţii cu doi parametri de tip
int care întoarce ca valoare un pointer la un tablou de 10 întregi.
1. Declaraţia:
void (*v(int,int))[10] ;
nu este acceptată. Nu este acceptat pointerul la un tablou de tip void.
2. Voi da o schemă de program care foloseşte un tablou de pointeri la funcţii
predefinite.

/* tablou de pointeri la funcţii*/


#include<stdio.h>
#include<math.h>
double(*func_mat[])(double)={sin, sinh, cosh, acos, tan, atan};
void main()
{
int i;
double x;
for (x=0.01; x<1.01; x+=0.01)
{
for(i=0;i<6;i++)
printf((“ %9.5lf ”, (*func_mat[i])(x)) ;
printf(“\n”);
}
}

3. În continuare, voi da un exemplu de program care foloseşte un tablou de


pointeri la funcţii definite:
#include<stdio.h>
typedef int (*func)(); /* Pointer la funcţie de tip întreg */
void tiparire()
{
printf((“\nFuncţia de tiparire”) ;
}
void afisare()
{
printf((“\nFuncţia de afisare”) ;
}
void scriere()
{
printf((“\nFuncţia de scriere”) ;
}
void verificare()
{
printf((“\nFuncţia de verificare”) ;
}
func tf[]={introducere, scriere, verificare, afisare, tiparire};
/* declaratia tabloului de pointeri la funcţii */
void main()
{
int i;
for(i=0;i<5;i++)
/* Apelul unei funcţii din tabloul de pointeri la funcţii */
(*tf[i])();
}

2.3.1. Folosirea pointerilor şi tablourilor ca parametri în funcţii

În lista de parametri a unei funcţii pot apărea atât parametri de tip tablou cât şi
pointeri la un tip de dată. În cazul tablourilor nu se încarcă în stivă tot conţinutul
tablourilor ci numai adresa primului element. Este recomandată utilizarea ca
parametri a pointerilor în locul tablourilor. Pentru a vedea mai clar, vom defini
aceeaşi funcţie folosind pe rând tablouri şi apoi pointeri.
Exemple:
1. Funcţia lungime calculează lungimea unui şir de caractere. Varianta din
stânga defineşte funcţia prin utilizarea tabloului, varianta din dreapta defineşte
funcţia prin utilizarea pointerilor.
int lungime (char s[]) int lungime(char *s)
{ {
int i; char *p;
for(i=0;s[i];i++); for(p=s; *p; p++);
return i; return p-s;
} }

Există diferenţe semnificative între timpii de execuţie ai celor două funcţii.


Pentru primul caz, la fiecare iteraţie se face incrementarea şi apoi indirectarea
pe când în al doilea caz se face numai incrementarea. De aici eficienţa
implementării cu pointeri.
2. Următoarea funcţie face transferul datelor între două zone de memorie.
Funcţia copiere are ca parametri:
- dest = adresa zonei destinaţie;
- sursa =adresa zonei sursă;
- nr =numărul de octeţi care vor fi copiaţi.

void copiere(void *dest, void *sursă, int nr)


{
while (nr--)
*((char*) dest)++=*((char*)sursa)++ ;
}

Pointerii vor fi convertiţi la char pentru a face accesul la nivel de octet. La fiecare
secvenţă de ciclare se transferă un octet şi se micşorează numărul de octeţi
transferaţi cu 1. În momentul în care nr devine 0 se iese din ciclul de transfer.
3. Produsul elementelor de pe diagonala principală a unei matrici de tip int:
Pointerul p este iniţializat cu adresa de început a matricei. Prin adunarea cu
valoarea n+1 se face mereu poziţionarea pe următorul element de pe diagonala
principală. Variabila k este înmulţită pe rând cu elementele de la adresa lui p.

long produs(void *a, int n)


{
int *p=(int*)a,m;
long k=l;
for(m=n; m--; k*=*p, p+=n+1);
return k;
}
2.4. Alocarea dinamică a memoriei

Odată cu gestiunea pointerilor apare şi posibilitatea utilizării variabilelor


dinamice. Spre deosebire de variabilele statice, aşa cum sugerează şi
denumirea, variabilele dinamice sunt variabile care sunt create şi eliminate la
cererea programatorului şi a căror dimensiune se poate modifica pe parcursul
execuţiei programului. Zona de memorie în care se face alocarea dinamică a
variabilelor se numeşte heap.
Alocarea de zone de memorie şi eliberarea lor în timpul execuţiei
programelor permite gestionarea optimă a memoriei de către programe. Un
astfel de mijloc de gestionare a memoriei se numeşte alocare dinamică a
memoriei.
Biblioteca standard a limbajului C pune la dispoziţia utilizatorului funcţii
care permit alocarea dinamică a memoriei. Prototipurile acestor funcţii se află
în bibliotecile alloc.h (în unele implementari malloc.h) şi stdlib.h. Principalele
funcţii sunt:

malloc – permite alocarea unui bloc de memorie a cărui


dimensiune se specifică în octeţi. Funcţia returnează un pointer
spre începutul zonei alocate.

Deoarece acest pointer trebuie să permită memorarea oricărui tip de dată în


zona alocată, el este de tip void*.
Prototipul funcţiei este: void* malloc(unsigned n); unde n este numărul
de octeţi ai zonei de memorie care se alocă. Dacă alocarea nu s-a putut face,
funcţia returnează pointerul NULL.

calloc - are prototipul void* calloc(unsigned nrelem, unsigned


dimelem); unde: dimelem este dimensiunea în octeţi a unui
element de dată; nrelem este numărul elementelor pentru care
se alocă memorie.

Prin această funcţie se alocă nrelem*dimelem octeţi. Ea returnează


pointerul spre începutul zonei rezervate sau pointerul NULL în cazul în care
numărul octeţilor este prea mare (depăşeşte zona de memorie liberă afectată
alocărilor dinamice).
Elementele din zona de memorie alocată prin calloc au valoarea 0.

free – eliberează o zonă de memorie care în prealabil a fost


alocată prin malloc sau calloc. Prototipul ei este:void free(void
*p); unde p este pointerul returnat de malloc sau calloc la
alocare, deci este pointerul spre începutul zonei care se
eliberează.

realloc – face realocarea unei zone de memorie heap.

Odată cu realocarea, pointerul la începutul zonei îşi poate modifica


valoarea. Funcţiile întorc un pointer la zona de memorie realocată sau NULL
daca nu s-a putut face realocarea. Sintaxa este: void* realloc(void* block,
unsigned dimelem);
Exemple:
1) Funcţia memzona memorează un şir de caractere într-o zonă de memorie
alocată prin funcţia malloc. Ea returnează adresa de început a zonei în care s-
a salvat şirul de caractere, deci returnează un pointer spre tipul char.

#include<stdio.h>
#include<alloc.h>
#include<string.h>
char *memzona(char* s)
/* memoreaza şirul de caractere spre care indica s în zona de
memorie furnizata de malloc */
{
char *p;
if((p=(char*)malloc(strlen(s)+1))!=NULL)
{
strcpy(p,s);return p;
}
else return NULL;
}
Funcţia malloc se apelează pentru a rezerva strlen(s)+1 octeţi. Cum în zona
de memorie rezervată prin malloc se pastrează şi caracterul NUL, lungimea
returnată de funcţia strlen s-a mărit cu 1.
Pointerul returnat de malloc a fost convertit spre char*, deoarece este de tip
void*. Acest pointer se atribuie lui p, deci p indică spre începutul zonei de
memorie alocate prin apelul funcţiei malloc. Se testează dacă acest pointer este
diferit de NULL (dacă s-a putut aloca memoria de dimensiunea cerută). În caz
afirmativ, se transferă şirul prin apelul funcţiei strcpy, returnându-se apoi
valoarea pointerului p.

2) Programul următor citeşte şiruri de caractere din fişierul de intrare stdin,


afişând în final şirul de lungime maximă. În acest scop, programul determină la
fiecare citire lungimea şirului citit şi o compară cu lungimea maximă a şirurilor
citite până în momentul rrespectiv. Dacă şirul curent are lungimea mai mare
decât cea maximă, el se păstrează într-o zonă de memorie furnizată de funcţia
malloc, utilizându-se funcţia memzona definită mai sus, iar lungimea sa intră în
evidenţă ca lungimea maximă întâlnită până în acel moment. Ori de câte ori un
şir nou se păstrează prin malloc, şirul vechi este eliminat cu ajutorul funcţiei
free.
#include<stdio.h>
#include<alloc.h>
#include<string.h>
#define MAX 255
main()
/* citeste şiruri de caractere de la intrare şi-l rescrie pe cel mai mare */
{
int max, i;
char t[MAX+1]; char *p;
char *memzona(char*) ; //prototip
p=NULL ; max=0;
while (scanf(“%s”,t ) !=EOF)
{
if ((i=strlen(t))>max)
{
/* şirul curent are lungimea mai mare decat cele citite pana în acest
moment*/
/* elibereaza zona ocupata de şirul de lungime max */
free(p);
/* se salveaza şirul curent fiind de lungime maxima */
p=memzona(t);
max=i ;
}
}
printf(“şirul cel mai lung este:\n”);
printf(“%s\n”,p);
}
char *memzona(char *s) /* memoreaza şirul de caractere spre care indica s în
zona de memorie furnizata de malloc */
{
char *p;
if((p=(char*)malloc(strlen(s)+1))!=NULL)
{
strcpy(p,s);
return p;
}
else return NULL;
}

2.4.1. Operatorul de alocare a memoriei - new

În afara funcţiilor prezentate anterior, limbajul C++ permite alocări în zona heap
prin intermediul operatorului new. Acesta este un operator unar şi are aceeaşi
prioritate ca şi ceilalţi operatori unari.
Operatorul new are ca valoare adresa de început a zonei de memorie
alocată în memoria heap sau zero (pointerul nul) în cazul în care nu se poate
face alocarea.
Operandul operatorului new în cea mai simpla formă, este numele unui
tip (predefinit sau definit de utilizator).
Exemple:
1) int *pint;
pint=new int;
Prin intermediul acestei expresii, se alocă în memoria heap o zonă de memorie
în care se pot păstra date de tip int. Adresa de început a zonei alocate se
atribuie pointerului pint.
Expresia: *pint=100; păstrează întregul 100 în zona respectivă.
Aceeaşi alocare se obţine, în limbajul C, folosind funcţia malloc ca mai jos:
pint=(int*)malloc(sizeof(int));
2) int& i=*new int;
Prin intermediul acestei declaraţii (definiţii) se alocă în memoria heap o zonă
de memorie în care se pot păstra date de tip int. Numele i permite referirea la
întregul păstrat în zona respectivă. Expresia de atribuire: i=100 păstrează
întregul 100 în zona respectivă.
Zonele de memorie alocate cu ajutorul operatorului new pot fi iniţializate. În
acest scop se utilizează o expresie de forma:

new tip(expresie)

unde:
tip – este numele unui tip;
expresie – este o expresie a cărei valoare iniţializează zona de memorie
Exemple:
1. double *pdouble;
pdouble=new double(3.14159265);
Această instrucţiune realizează următoarele:
- alocă în memoria heap o zonă de memorie în care se pastrează valoarea
3.14159265 în flotantă dublă precizie;
- adresa de început a acestei zone de memorie se atribuie variabilei pdouble.

2. double pi=*new double(3.14159265);


Prin această declaraţie se rezervă, în memoria heap, o zonă de memorie în
care se păstrează valoarea 3.14159265 în flotantă dublă precizie. Data
respectivă se poate referi cu ajutorul numelui pi. De exemplu, pi poate fi utilizat
în mod obişnuit în expresii de forma:
pi*r*r
sin(pi/2)
x*180/pi
etc.

O altă utilizare importantă este aceea de alocare a unei zone de memorie, în


memoria heap, pentru tablouri.
În acest scop, utilizăm o expresie de forma:

new tip[expresie]

unde expresie – expresie de tip intreg;


Prin această construcţie se rezervă, în memoria heap, o zonă de memorie de
exp*sizeof(tip) octeţi.
Valoarea expresiei de mai sus, este adresa de început a zonei de memorie
rezervată prin operatorul new.
Exemplu:
double *tab;
int m,n;
…..
tab=new double[m*n];
Această instrucţiune rezervă în memoria heap o zonă de
m*n*sizeof(double) octeţi. Adresa de început a acestei zone de memorie se
atribuie pointerului tab.
Elementele unei astfel de zone de memorie nu pot fi iniţializate decât
numai prin secvenţe de program corespunzătoare. De exemplu, pentru a anula
cele m*n elemente de tip double rezervate ca mai sus, putem folosi
instrucţiunea for de mai jos:
for(int i=0; i<m*n ;i++)
tab[i]=0.0;

2.4.2. Operatorul de dezalocare a memoriei - delete


O zonă de memorie alocată prin operatorul new se eliberează prin
operatorul delete.
Daca p este un pointer spre tip:
tip *p;
şi
p=new tip;
atunci zona din memoria heap alocată cu ajutorul lui new se eliberează folosind
construcţia: delete p.
De asemenea, operatorul delete se utilizează pentru a dezaloca tablourile
alocate prin new.
Fie alocarea:

tip *p=new tip[expresie];

Această zonă se eliberează folosind o construcţie de forma:

delete [expresie] p;

Menţionăm că expresia care defineşte numărul elementelor tabloului nu


este totdeauna necesară la dezalocare.
La utilizarea operatorului delete este important ca pointerul la care se
aplică să aibă o valoare obţinută ca rezultat al mişcării prealabile a operatorului
new.
Dacă operatorul delete se aplică la un pointer nenul a cărui valoare nu a
fost obţinută ca rezultat al aplicării operatorului new, atunci efectul aplicării lui
delete este imprevizibil.
2.5. Stiva implementată dinamic

Structurile de stivă şi coadă au fost prezentate în primul capitol. Revin


asupra lor, pentru a vedea cum aceleaşi structuri pot fi implementate folosind
alocarea dinamică.
Reamintesc că stiva este formată dintr-o mulţime ordonată de elemente în
care accesul se realizează conform principiului LIFO (Last In First Out). Pentru
a putea realiza implementarea dinamică a stivei, elementele unei astfel de
structuri vor fi de tip structură, cu două feluri de informaţii: informaţia propriu-
zisă (conţinutul efectiv al elementului respectiv şi care variază în funcţie de
problemă – notată cu inf care este de un anumit tip de date tip) şi informaţia de
legătură (care este un pointer ce conţine adresa elementului precedent din stivă
– notat cu leg). Astfel tipul de date necesar implementării dinamice a structurii
de tip stivă este:

typedef struct tnod


{
tip inf; // informatia propriu-zisa
struct tnod *leg; // informatia de legatura
} TNOD;

Adăugarea sau extragerea unui element se face la un singur capăt numit vârful
stivei. Elementul introdus primul în stivă se afla la baza stivei. Pornind de la
această definiţie, se poate deduce ce informaţie de legătură este necesară.
Astfel, informaţia de legătură a fiecărui element din stivă reprezintă adresa
elementului pus anterior în stivă, excepţie făcând elementul de la bază, a cărui
informaţie de legătură este NULL.

Se observă că este necesar şi suficient să fie reţinută adresa elementului


din vârful stivei într-un pointer pe care îl voi nota cu vf(TNOD *vf), celelalte
elemente putând fi accesate cu ajutorul informaţiei de legătură de care dispune
fiecare element al stivei.
Structura de tip stivă am prezentat-o în capitolul precedent, aşadar acum
reamintesc operaţiile ce se pot efectua asupra stivei (operaţii ce au fost
implementate cu ajutorul tablourilor).
Stiva se poate reprezenta grafic astfel:

Operaţia Init(St):
Precondiţie: True.
Postcondiţie: St este o stivă vidă.
Operaţia Adaug (St,Element):
Precondiţie: Stiva St= (x1,x2,...,xn), n0.
Postcondiţie: Stiva St= (y1,y2,...,yn,yn+1), unde y1=Element iar yi+1=xi, pentru
i=1,2,..,n.
Operaţia Extrag (St,Element):
Precondiţie: Stiva St= (x1,x2,...,xn), n>0.
Postcondiţie:Element=x1 iar Stiva St= (y1,y2,...,yn,yn-1), unde yi=xi+1, pentru
i=1,2,..,n-1.
Funcţia StVida (St):
Precondiţie: St este o stivă arbitrară.
Postcondiţie: StVida este True dacă numărul elementelor din stivă St este 0.
Funcţia Cardinal (St):
Precondiţie: St este o stivă arbitrară.
Postcondiţie: Cardinal = Numărul elementelor din stiva St.
Aceste operaţii pot fi implementate dinamic, în felul următor:
Astfel, având următoarele declaraţii:

typedef struct tnod


{
tip inf; // informatia propriu-zisa
struct tnod *leg; // informatia de legatura
} TNOD;
TNOD *vf; // vf - varful stivei

implementarea dinamică a operaţiilor cu stiva se poate face astfel:


1) Iniţializarea stivei:

void init( TNOD* vf)


{
vf=NULL;
}

2) Adăugarea unui element x în vârful stivei:


Deoarece toate adăugările şi ştergerile se fac la un singur capăt al stivei,
singura posibilitate de a adăuga un element în stivă este în vârf. Acest lucru se
realizează astfel:

- Se alocă memorie pentru noul element (a);


- Se iniţializează zona de informaţie propriu-zisă (utilă) a acestuia (b);
- Se iniţializează informaţia de legătură cu adresa elementului care a fost
anterior în vârful stivei, adresă păstrată în variabila vf (c);
- Se actualizează variabila vf cu adresa noului element alocat (d).
Putem observa că acest algoritm este corect şi dacă stiva era vidă înainte de
adăugare(vf=NULL).
void adaug(tip x,TNOD *vf)
{
TNOD *p; // pointer de lucru
p=new TNOD; // (a)
p->inf=x; // (b)
p->leg=vf; // (c)
vf=p; // (d)
}

Această operaţie se poate reprezenta grafic astfel:

3) Extragerea elementului din vârful stivei


Prin extragerea unui element se înţelege eliminarea acestuia din stivă. Această
operaţie se poate realiza numai dacă stiva este nevidă şi în caz afirmativ se va
şterge elementul din vârful stivei. Operaţia se efectuează astfel:

- Într-un pointer de lucru notat p, se reţine adresa elementului din vârful stivei;
(a)

- În variabila q se extrage elementul din vârful stivei;


- Adresa elementului următor celui din vârful stivei devine adresa noului vârf al
stivei; (b)
- Se eliberează memoria ocupată de elementul care a fost anterior în vârful
stivei.(c)

void extragere( TNOD *vf,tip *q)


{
TNOD *p; // pointer de lucru
p=vf; // (a)
*q=vf->inf; // Se extrage în variabila *q valoarea din
varful stivei
vf=vf-leg; // (b)
delete p; // (c)
}

Grafic operaţia de ştergere se poate reprezenta în felul următor:


4) Verificarea dacă stiva este vidă

int stvida( TNOD *vf)


{
return vf==NULL;
}

5) Numărarea elementelor din stivă

int cardinal(TNOD *vf)


{
int m=0; // contorizeaza elementele stivei
TNOD* p; // pointer de lucru
p=vf;
while (p!=NULL)
{
m++;
p=p->leg;
}
return m;
}
2.6. Coada implementată dinamic

O structură de date care respectă disciplina FIFO (First In First Out) se


numeşte coadă. Pentru a respecta această disciplină, vom efectua adăugarea în
coada listei, iar extragerea din capul cozii.
O coadă este un tip de date cu operaţii caracteristice comportării primul
venit/primul servit. Elementul care poate servi este cel care a sosit în coadă cel
mai devreme. Dacă acesta a fost scos din coadă, atunci următorul element care
a sosit cel mai devreme devine elementul care va putea fi servit în continuare.
O astfel de structură a fost prezentată în primul capitol folosind o implementare
statică cu ajutorul tablourilor. În continuare, voi da şi o implementare dinamică
structurii de tip coadă.
În cazul implementării dinamice, un element al cozii conţine două tipuri de
informaţii: informaţia utilă (inf) şi informaţia de legătură (leg) - care este de fapt
un pointer ce conţine adresa următorului element din coadă.

Ultimul element al cozii nu mai are succesor, deci informaţia sa de legatură are
valoarea NULL. De asemenea, având în vedere că structura de coadă are două
capete (primul şi ultimul) sunt necesare două variabile de tip referinţă care să
indice primul element din coadă (prim) şi ultimul element din coadă (ultim). În
cazul în care coada este vidă, prim şi ultim au valoarea NULL. Astfel, o
reprezentare grafică a cozii poate arăta în felul următor:

Reamintesc specificarea operaţiilor cu coada făcute şi în primul capitol:

Operaţia Crevida (c): {c:= coada vidă}


Precondiţie: True {adică fără restricţii la intrare}
Postcondiţie: c este o coadă vidă.
Operaţia Adaug (c, Element): {Adaugă pe Element în c}
Preconditie: c = (x1,x2,...,xn), n0.
Postconditie: c = (x1,x2,...,xn,xn+1), unde xn+1=Element.

Operaţia Extrag (c, Element): {Element:=Capul cozii}


Precondiţie: C = (x1,x2,...,xn), n>0.
Postcondiţie: Element=x1 iar C = (y1,y2,...,yn,yn-1), unde
yi=xi+1, pentru i=1,2,..,n-1.

Operaţia CVida (c): {Cvida este True dacă c e vidă}


Precondiţie: c = (x1,x2,...,xn), n>=0.
Postcondiţie: Dacă n=0 atunci Cvida=True altfel Cvida=False.

Operaţia Cardinal (c): {Cardinal = n}


Precondiţie: c = (x1,x2,...,xn), n>=0.
Postcondiţie: Cardinal = n.

Pentru implementarea dinamică a cozii, sunt necesare următoarele declaraţii:

typedef struct tnod


{
tip inf; // informatia propriu-zisa
struct tnod *leg; // informatia de legatura
} TNOD;
TNOD *prim, *ultim; // adresa primului,
respectiv a ultimului element din coada

Având aceste date, operaţiile cu coada folosind alocarea dinamică a memoriei, în


limbajul C++ se pot implementa astfel:
1) Iniţializarea cozii:

void Crevida (TNOD *prim, TNOD *ultim)


{
prim=ultim=NULL;
}

2) Adăugarea unui element x în coadă:


Având în vedere definiţia structurii de coadă, se poate face observaţia că
adăugarea unui element se poate face numai la sfârşitul cozii, după ultimul
element.
Dacă coada este vidă, atunci la inserarea unei valori se creează de fapt primul
element al cozii. În acest caz prim şi ultim indică acelaşi element (au aceeaşi
valoare).

Astfel etapele acestei operaţii sunt:


- Alocarea unei zone de memorie pentru noul element; (a)
- Se introduce informaţia utilă pentru acest element; (b)
- Informaţia de legatură a elementului creat se completează cu NULL; (c)
- Se reiniţializează informaţia de legatură a elementului indicat de ultim cu
adresa noului element; (d)
- Se modifică valoarea pointerului ultim dându-i ca valoare adresa noului
element introdus.(e)

void adaug(tip x; TNOD *ultim) {


TNOD *p; // pointer de lucru
if (prim==NULL)
{
prim=ultim=new TNOD;
prim->inf=x;
prim->leg=NULL;
}
else
{
p=new TNOD; // (a)
p->inf=x; // (b)
p->leg=NULL; // (c)
ultim->leg=p; // (d)
ultim=p; // (e)
}
}
Adăugarea unui element într-o coadă nevidă se poate reprezenta grafic astfel:

Dacă coada era iniţial vidă, după adăugarea unui element arată astfel:

3) Extragerea unui element din coadă (a primului element)


Operaţia de extragere se poate face doar asupra primului element din coadă.
Bineînţeles, putem extrage un element numai dintr-o coadă care nu este vidă.
Se observă că primul element din coadă fiind eliminat va fi înlocuit de cel care
iniţial era al doilea. Deci, se pot deduce următoarele etape ale extragerii din
coadă:

- Se reţine într-o variabilă (*q) informaţia utilă din primul element al cozii; (a)
- Se reţine într-un pointer de lucru adresa acestui element (să numim pointerul
de lucru p); (b)
- Se actualizează valoarea pointerului prim cu adresa următorului element din
coadă; (c)
- Se eliberează zona de memorie ce fusese alocată iniţial primului element din
coadă (acum indicat de pointerul p); (d)

void extrag(TNOD *prim,tip *q)


{
TNOD *p; // pointer de lucru
*q=prim->inf; // (a)
p=prim; // (b)
prim=prim->leg; // (c)
delete p; // (d)
}
Operaţia de ştergere, se poate reprezenta grafic astfel:

4) Verificarea dacă coada este vidă

int cvida (TNOD *prim)


{
return (prim==NULL);
}

5) Numărarea elementelor din coadă

int cardinal (TNOD *prim)


{
int m=0; // contorizează elementele cozii
TNOD *p; // pointer de lucru
p=prim;
while(p !=NULL)
{
m++;
p=p->leg;
}
return m;
}
2.7. LISTE SIMPLU ÎNLĂNŢUITE

Lista simplu înlănţuită este structura de reprezentare a informaţiilor cea mai


cunoscută şi implicit cea mai utilizată atunci când ne referim la alocarea
dinamică a memoriei.

O listă simplu înlănţuită este formată dintr-o colecţie de elemente de acelaşi tip.
Fiecare element conţine în afară de elementul propriu-zis şi o legatură care ne
spune unde putem găsi un alt element din mulţime. Elementele listei vor fi
numite şi noduri. Ideea este că fiecare nod dintr-o listă simplu înlănţuită conţine
informaţii despre cum putem localiza un alt nod dintr-o mulţime de noduri.
Accesul imediat la fiecare nod din mulţime nu este necesar pentru că fiecare
nod conduce la un altul.

inf leg

Acest tip de element se numeste NOD.

Prin inf înţelegem informaţia ataşată elementului respectiv, şi care poate fi de


orice tip de date cunoscut de către limbajul C++, iar prin leg înţelegem un câmp
de tip referinţă care va conţine adresa următorului element din mulţimea de
elemente.

Pentru a putea construi şi a folosi cât mai eficient o listă simplu înlănţuită este
necesară o variabilă de tip referinţă care să indice primul element din listă.
Convenim să notăm cu prim – adresa primului nod. Uneori, întâlnim aplicaţii
care necesită şi folosirea adresei ultimului nod, notată cu ultim.

O formă grafică sugestivă pentru o listă simplu înlănţuită ar fi următoarea:


Listele simplu înlănţuite reprezintă un capitol foarte important în alocarea
dinamică a memoriei deoarece:

- În primul rând, sunt mai flexibile decât stiva şi coada (care restricţionează
operaţiile de adăugare, acces şi ştergere a elementelor conform definiţiilor lor)
- Se recomandă folosirea listelor simplu înlănţuite în rezolvarea problemelor
specifice vectorilor deoarece se utilizează eficient memoria care poate fi
alocată sau eliberată în funcţie de cerinţele programatorului
- Anumite genuri de probleme (cum ar fi operaţiile cu matrici rare; respectiv
polinoame rare) îşi găsesc o rezolvare mai rapidă, eficientă şi utilă folosind
listele
Definiţia listei simplu înlănţuite permite o mai mare diversitate a operaţiilor care
se pot face asupra ei şi astfel o mai largă aplicabilitate a acesteia.

Declaraţiile necesare lucrului cu o listă simplu înlănţuită sunt:

typedef struct tnod


{
tip inf; // informatia propriu-zisa
struct tnod *leg; // informatia de legatura
} LISTA;
LISTA *prim, *ultim; // adresa primului,
respectiv a ultimului element din lista simplu
inlantuita
Cu listele simplu înlănţuite se pot face următoarele operaţii:

1. Iniţializarea listei (crearea unei liste vide)

void init(TNOD *prim)


{
prim=NULL;
}
2. Adăugarea unui element în listă

Aceasta operaţie se poate face în trei moduri, în funcţie de locul unde se


inserează elementul în listă. Astfel putem avea:

a) Inserarea unui element la începutul listei;


b) Inserarea unui element la sfârşitul listei;
c) Inserarea unui element în interiorul listei;

a) Adăugarea unui element la începutul listei se poate reprezenta grafic astfel:

Etapele adăugarii unui element la începutul listei:

- alocarea zonei de memorie necesare noului element (Se foloseşte un pointer


de lucru p); (a)
- completarea informaţiei utile pentru noul element (notată cu nou); (b)
- completarea informaţiei de legătură cu adresa conţinută în variabila prim
(ţinând cont că acesta va deveni primul element al listei şi, conform definirii
acesteia, trebuie să conţină adresa elementului următor din listă, deci cel care
era primul înainte de a face inserarea); (c)
- Actualizarea variabilei referinţă prim cu adresa elementului creat, care în acest
moment devine primul element al listei; (d)

void adaugi( tip x, LISTA *prim)


/*x reprezinta informatia ce se adauga la începutul listei */
{
LISTA *p; // pointerul de lucru
p=new LISTA; // (a)
p->inf=x; // (b)
p->leg=prim; // (c)
prim=p; // (d)
}
Se poate observa că aceşti paşi sunt valabili şi în cazul în care lista era iniţial
vidă (prim=NULL), însă cu o completare. În acest caz, elementul adăugat
reprezintă şi primul şi ultimul nod al listei.

b) Adăugarea unui element la sfârşitul listei, presupune inserarea acestuia


după ultimul nod al listei. În acest caz avem nevoie de variabila ultim care indică
nodul după care se va insera. Descrierea operaţiilor necesare se pot deduce şi
de această dată folosind o reprezentare grafică a listei:

Paşii algoritmului de adăugare a unui element la sfârşitul listei:

- Alocarea zonei de memorie necesară pentru noul element; (a)


- Completarea informaţiei de legătură a elementului creat cu NULL, deoarece
el va deveni ultim element; (b)
- Completarea informaţiei utile; (c)
- Informaţia de legatură a celui ce a fost înainte ultimul element al listei îşi
schimbă valoarea cu adresa noului element (îl va indica pe acesta); (d)
- Se actualizează pointerul ultim cu adresa nodului adăugat listei; (e)

void adaugs( tip x, LISTA *ultim)


// realizeaza adaugarea valorii x la sfarşitul listei
{
LISTA *p; // pointer de lucru
p=new LISTA; // (a)
p->leg=NULL; // (b)
p->inf=x; // (c)
ultim->leg=p; // (d)
ultim=p; // (e)
}
c) Adăugarea unui element în interiorul listei

Această operaţie se poate face înaintea sau după un element al listei. Cel mai
comod se face inserarea după un element specificat al listei. Deoarece se
realizează o inserare după un nod, acest lucru poate determina o adăugare la
sfârşitul listei în cazul în care nodul respectiv este ultimul nod din această listă,
operaţie descrisă anterior în funcţia adaugs. Sunt necesari doi pointeri de lucru:
q – indică nodul după care este facută inserarea; p – pointer de lucru necesar
pentru crearea unui nou element. Presupunem că avem o listă cu cel puţin două
elemente, unde după nodul indicat de q vom adăuga un nou element cu
valoarea informaţiei propriu-zise x.

Succesiunea logică a etapelor necesare inserării după un nod (indicat de q)


este următoarea:

- alocarea zonei de memorie necesară noului element (folosirea pointerului p);


(a)
- iniţializarea informaţiei utile ( cu valoarea notată nou ); (b)
- iniţializarea informaţiei de legătură cu adresa următorului nod (cu adresa
reţinută în acest moment în variabila q^.leg ); (c)
- actualizarea informaţiei de legatură din nodul după care s-a inserat noul
element cu adresa zonei de memorie alocată pentru acesta (p); (d)
void adaugd( int x, LISTA *q)
{
// adauga valoarea lui x într-un nod ce urmeaza nodului indicat de
q în lista
LISTA *p; // pointer de lucru
p=new LISTA; // (a)
p->inf=x; // (b)
p->leg=q->leg; // (c)
q->leg=p; // (d)
}

Cealaltă situaţie de inserare a unui nod în interiorul listei este de a realiza


aceasta înaintea unui nod indicat de q. Pentru această situaţie putem folosi
următoarea solutie, care este cea mai utilizată fiind mai rapidă şi eficientă şi va
fi descrisă în următorii paşi:

- alocarea unei zone de memorie pentru noul element, dar cu scopul de face
inserare după nodul referit de q (folosind pe p); (a)

- se completează acest nod cu informaţia *q (se realizează o dublură a


informaţiei propriu-zise din nodul indicat de q); (b)

- se actualizează câmpurile inf şi leg din nodul q;(c,d)

Reprezentarea grafică corespunzătoare este următoarea:


void adaugint( tip x, LISTA *q)
{
LISTA *p; // pointer de lucru
p=new LISTA; // (a)
p->inf=q->inf; // (b)
p->leg=q->leg ; // (b)
q->inf=x; // (c)
q->leg:=p; // (d)
}

Aceste inserări în interiorul unei liste ne demonstrează flexibilitatea structurii de


listă simplu înlănţuită şi prin urmare larga sa aplicabilitate, ceea ce se va
observa şi în rezolvarea problemelor de cele mai diverse tipuri.

3. Traversarea ( parcurgerea ) listei


Reprezintă o operaţie necesară pentru afişarea sau prelucrarea elementelor
listei, ce constă în trecerea prin fiecare element al listei o singură dată. Se
foloseşte un pointer de lucru pe care-l voi nota cu p şi care va fi iniţializat cu
valoarea prim, iar apoi îşi va schimba valoarea cu adresa nodului următor
(folosind atribuirea p=p->leg), ceea ce se va repeta până când p va avea
valoarea NULL (ceea ce înseamnă că a fost prelucrat şi ultimul nod). La fiecare
schimbare a valorii pointerului p, se va afişa informaţia utilă din nodul indicat de
p. Bineînţeles, lista nu trebuie să fie vidă. Parcurgerea unei liste simplu
înlănţuite se face secvenţial, într-un singur sens, de la primul către ultimul nod.

Aleg ca scop afişarea elementelor listei pentru exemplificarea procedurii de


parcurgere a listei:

void parcurgere ( LISTA *prim)


{
LISTA *p;
p=prim;
while (p!=NULL)
{
cout<<p->inf;
p=p->leg;
}
}
4. Ştergerea unui element din listă

Operaţia de ştergere este destul de complexă şi presupune mai multe cazuri,


fiecare cu particularităţile lui. Astfel distingem următoarele cazuri de ştergere a
unui element:

a) Ştergerea primului element;


b) Ştergerea ultimului element;
c) Ştergerea unui element din interiorul listei;

a)Ştergerea primului element din listă determină schimbarea valorii variabilei


prim deoarece nodul pe care îl indică iniţial trebuie să fie eliminat. Astfel prim
devine adresa celui de-al doilea element din listă care acum devine primul
element al listei. Pornind de la o reprezentare grafică asemănătoare celei ce
urmează, se poate deduce algoritmul de ştergere pentru această situaţie:

Pentru aceasta este necesar un pointer p pe care-l folosim pentru a reţine


adresa primului element (valoarea iniţială a lui prim) pentru a putea elibera zona
de memorie alocată acestuia.

b) Ştergerea ultimului element al listei are ca efect schimbarea pointerului ultim


precum şi a informaţiei de legătură din penultimul nod care va deveni NULL,
acest nod devenind astfel ultimul. Reprezentarea grafică a acestei situaţii este
următoarea:
c) Ştergerea unui nod din interiorul listei presupune ştergerea unui nod referit
de un pointer r, obţinut prin localizarea anterioară a acestuia. Se realizează o
copie a nodului care urmează celui pe care-l vom şterge (indicat de r->leg), iar
apoi îl vom şterge pe acesta ( pe cel referit de r->leg ).

Pe baza observaţiilor făcute anterior, următoarea funcţie de eliminare a unui


element din listă va lua în considerare toate cele trei cazuri. Îi vom transmite un
singur parametru şi anume adresa nodului ce urmează a fi şters (r).

void stergere(LISTA *r)


{
LISTA *s,*q;
if (r==prim)
{
// Se va şterge primul elemental listei
s=prim;
prim=prim->leg;
delete s;
}
else
if (r==ultim)
{
// Se va sterge ultimul nod al listei
q=prim; //va retine adresa penultimului nod
while (q->leg !=ultim)
q=q->leg;
s=ultim;
ultim=q;
ultim->leg=NULL;
delete s;
}
else
{
// stergerea unui nod din interiorul listei
s=r->leg;
// în s se retine adresa nodului care va fi sters efectiv,
adica cel caruia îi vom face dublura
r->inf=r->leg->inf;
r->leg=r->leg-leg;
// am creat dublura nodului urmator
delete s;
}
}

5. Căutarea unui element în listă


De multe ori apar situaţii când este necesar să căutăm anumite informaţii în
listă. Pentru aceasta, se va parcurge lista până când este găsită informaţia
respectivă sau, în caz contrar, este epuizată lista şi nu am găsit-o. Este indicat
să folosim o variabilă care să indice dacă am gasit informaţia în listă sau nu
(notată gasit 1-dacă s-a găsit elementul, 0-în caz contrar). Pentru a face cât
mai utilă operaţia de căutare, şi având în vedere că elementul pe care îl vom
găsi va fi folosit ulterior, în general avem nevoie de pointerul ce îl indică. Astfel
putem folosi o funcţie ce are ca rezultat pointerul ce indică elementul căutat.
Dacă nu este găsit, acest pointer are valoarea NULL:

LISTA* caut(int x)
// x-informatia pe care o cautam în lista
{
LISTA *P // folosit pentru parcurgerea listei
int gasit;
gasit=0;
p=prim;
while (p!=NULL && !gasit )
if (p->inf==x) gasit=1;
else
p=p->leg;
if (gasit) return p;
else return NULL;
}
}
Acestea sunt principalele operaţii care se pot realiza cu listele simplu înlănţuite
şi pe baza cărora se poate rezolva o gamă largă de probleme, multe dintre ele
rezolvate anterior cu tablouri. Este bine să se facă o paralelă între rezolvarea
aceleiaşi probleme cu ajutorul listelor şi rezolvarea folosind vectorii. Astfel se
pot evidenţia avantajele folosirii alocării dinamice (probleme ce prelucrează:
matrici rare, polinoame, numere mari etc.).

Folosind inserarile la începutul şi la sfârşitul listei, se pot realiza două moduri


de creare a listei:

a) Crearea prin inserare la sfârşitul listei presupune introducerea nodurilor unul


după altul în ordinea citirii datelor de la tastatură. Se crează mai întâi primul
nod al listei, iar apoi voi ataşa dupa el celelalte elemente. Evident, elementele
unei liste pot fi introduse prin citire, atribuire de valori sau diverse operaţii
aritmetice. Aleg varianta citirii informaţiei propriu-zise din fiecare nod. O astfel
de creare a listei are la baza operaţie de adăugare a unei informaţii la sfârşitul
listei.

void creares(LISTA *prim, LISTA *ultim)


{
int x;
char c;
ultim=prim=new LISTA; /*este necesara folosirea
pointerului ultim deoarece adaugarile de elemente se fac
la sfarşitul listei */
cout<< “Introduceti prima informatie a listei: “;
cin>>prim->inf;
prim->leg=NULL;
cout<<”Continuati sa introduceti elemente?(D/N)”;
cin>>c;
while (toupper(c)==’D’)
{
cin>>x;
adaugs(x, ultim); // funcţie definite anterior
cout<<”Continuati sa introduceti
elemente?(D/N)”;
cin>>c;
}
}
b) O altă modalitate de creare a unei liste este adăugarea elementelor la
începutul listei, iniţial vidă. Bineînţeles se va folosi funcţia de adăugare la
începutul listei.

void crearei(LISTA *prim)


{
int x;
char c;
init(prim);
cout<<”Continuati sa introduceti elemente?(D/N)”;
cin>>c;
while (toupper(c)==’D’)
{
cin>>x;
adaugi(x,prim);
cout<<”Continuati sa introduceti
elemente?(D/N)”;
cin>>c;
}
}
2.8. LISTE DUBLU ÎNLĂNŢUITE

Listele dublu înlănţuite se deosebesc de cele simplu înlăţuite prin faptul că


fiecare nod are două referinţe, spre succesorul respectiv predecesorul lui, ca în
figura următoare.
Cap

E1 E2 En- En
1
NULL NIL
NULL

Fiecare element al unei liste dublu înlănţuite are două câmpuri de legătură: ant
– adresa nodului precedent din listă şi urm – adresa nodului următor din listă.
Se observă că datorită câmpului ant structura de listă dublu înlăţuită este mai
flexibilă decât cea de lista simplu înlănţuită. În primul rând este posibilă o
parcurgere în ambele sensuri a listelor dublu înlănţuite, iar pe de altă parte
dubla informaţie de legatură ne permite să accesăm mai uşor datele care ne
interesează din listă. Având în vedere prezentarea detaliată făcută anterior
listelor simplu înlănţuite, listele dublu înlănţuite le voi prezenta pe scurt
insistând asupra funcţiilor ce implementează operaţiile necesare.

Declaraţiile necesare pentru implementarea operaţiilor cu listele dublu


înlănţuite sunt:

typedef struct tnod


{
tip inf; // informatia propriu-zisa
struct tnod *ant, *urm; // informatiile de
legatura
} LISTA;
LISTA *prim, *ultim; // adresa primului,
respectiv a ultimului element din lista
Pointerii prim şi ultim indică primul respectiv ultimul nod al listei. Evident, primul
element al listei are pentru câmpul ant valoarea NULL (nu are predecesor), iar
ultimul element are pentru câmpul urm tot valoarea NULL (nu are succesor).
Bineînţeles, pentru parcurgerea listelor dublu înlănţuite se poate porni de la
primul element spre ultimul sau de la ultimul element spre primul, datorită
existenţei dublei informaţii de legătură.

Aceasta va permite o anumită lejeritate în rezolvarea problemelor ce implică


liste dublu înlănţuite. Chiar operaţiile ce se efectuează asupra listelor dublu
înlănţuite vor demonstra acest lucru.

Ca şi la listele simplu înlănţuite, avem următoarele operaţii posibile cu liste


dublu înlănţuite: iniţializarea listei, adăugarea unui element (la începutul,
sfârşitul şi în interiorul listei ), căutarea unei valori, parcurgerea listei, ştergerea
unui element.

1) Iniţializarea listei (crearea unei liste vide)

void init(TNOD *prim, TNOD *ultim)


{
prim=ultim=NULL;
}

2) Adăugarea unui element în listă

a) Adăugarea unui element la începutul listei

Inserarea la începutul listei presupune modificarea variabilei de tip referinţă ce


indică primul element al listei şi este efectuată respectând următorii paşi:
- alocarea zonei de memorie necesare noului element (Se foloseşte un pointer
de lucru p); (a)
- completarea informaţiei utile pentru noul element; (b)
- completarea câmpului urm cu adresa conţinută în variabila prim (ţinând cont
că acesta va deveni primul element al listei şi, conform definirii acesteia, trebuie
să conţină adresa elementului următor din lista, deci cel care era primul înainte
de a face inserarea); (c)
- completarea câmpului ant cu valoarea NULL, deoarece nodul adăugat va fi
primul nod al listei şi nu va avea predecesor; (d)
- Actualizarea variabilei referinţă prim cu adresa elementului creat, care în acest
moment devine primul element al listei; (e)

void adaugi (tip x, LISTA *prim)


/*x reprezinta informatia ce se adauga la inceputul listei */
{
LISTA *p; // pointerul de lucru
p=new LISTA; // (a)
p->inf=x; // (b)
p->urm=prim; // (c)
p->ant=NULL; // (d)
prim=p; // (e)
}

b) Adăugarea unui element la sfârşitul listei

Inserarea la sfârşitul listei are ca efect atât modificarea pointerului ultim cât şi a
câmpului urm al ultimului nod.

Paşii algoritmului de adăugare a unui element la sfârşitul listei:

- Alocarea zonei de memorie necesară pentru noul element; (a)


- Completarea câmpului urm al elementului creat cu NULL, deoarece el va
deveni ultimul element al listei; (b)
- Completarea câmpului ant al elementului creat cu adresa ultimului nod al listei
(care va deveni penultimul); (c)
- Completarea informaţiei utile; (d)
- Câmpul urm al celui ce a fost înainte ultimul element al listei îşi schimbă
valoarea cu adresa noului element (îl va indica pe acesta); (e)
- Se actualizează pointerul ultim cu adresa nodului adăugat listei; (f)

void adaugs (tip x, LISTA *ultim)


// realizeaza adaugarea valorii x la sfarşitul listei
{
LISTA *p; // pointer de lucru
p=new LISTA; // (a)
p->urm=NULL; // (b)
p->ant=ultim; // (c)
p->inf=x; // (d)
ultim->urm=p; // (e)
ultim=p; // (f)
}

c) Adăugarea unui element în interiorul listei

Operaţia de inserare în interiorul listei se face mai uşor având în vedere dublul
acces la adresele elementelor listei. Deoarece se realizează o inserare după
un nod, acest lucru poate determina o adăugare la sfârşitul listei în cazul în care
nodul respectiv este ultimul nod din această listă, operaţie descrisă anterior în
funcţia adaugs. Sunt necesari doi pointeri de lucru: q – indică nodul după care
este facută inserarea; p – pointer de lucru necesar pentru crearea unui nou
element. Presupunem că avem o listă cu cel puţin două elemente, unde după
nodul indicat de q vom adăuga un nou element cu valoarea informaţiei propriu-
zise x.

Succesiunea logică a etapelor necesare inserării după un nod (indicat de q)


sunt următoarele:

- alocarea zonei de memorie necesare noului element (folosirea pointerului p);


(a)
- iniţializarea informaţiei utile; (b)
- iniţializarea câmpului urm al noului nod cu adresa nodului ce urmează în listă
după nodul indicat de q;(c)
- iniţializarea câmpului ant al noului nod cu valoarea q (nodul ce va precede
noul nod);(d)
- actualizarea câmpului urm din nodul după care s-a inserat noul element cu

adresa zonei de memorie alocată pentru acesta (p); (e)

void adaugd( int x, LISTA *q)


{
// adauga valoarea lui x intr-un nod ce urrmeaza nodului
indicat de q in lista
LISTA *p; // pointer de lucru
p=new LISTA; // (a)
p->inf=x; // (b)
p->urm=q->urm; // (c)
p->ant=q; // (d)
q->urm=p; // (e)
}

De asemenea, se poate realiza adăugarea unui nod înaintea celui indicat de q.


O astfel de operaţie devine mult mai simplă, deoarece adresa nodului
precedent lui q este uşor de găsit, datorită dublei legături:

- alocarea unei zone de memorie pentru noul element; (a)

- completarea informaţiei utile a noului nod; (b)

- iniţializarea câmpurilor de legatură ale nodului nou; (c şi d)

- actualizarea câmpului urm al nodului precedent lui q cu adresa noului nod ;


(e)
- actualizarea câmpului ant al lui q cu adresa nodului creat; (f)

void adaugint (tip x, LISTA *q)


{
LISTA *p; // pointer de lucru
p=new LISTA; // (a)
p->inf=x; // (b)
p->urm=q ; // (c)
p->ant=q->ant; // (d)
q->ant->urm=p; // (e)
q->ant=p; // (f)
}

3) Traversarea ( parcurgerea ) listei


Parcurgerea pentru diverse prelucrari a unei liste dublu înlănţuite se poate face
în două sensuri, atât de la primul nod la ultimul, cât şi invers, de la ultimul nod
la primul, datorită dublei legături.

- parcurgerea de la primul catre ultimul nod

void parcurgere1 ( LISTA *prim){


LISTA *p;
p=prim;
while (p!=NULL)
{
prelucrare(p->inf); // o operaţie oarecare asupra
informaţiei din listă
p=p->urm;
}
}

- parcurgerea de la ultimul nod către primul:

void parcurgere2 ( LISTA *ultim){


LISTA *p;
p=ultim;
while (p!=NULL)
{
prelucrare(p->inf);
p=p->ant;
}
}
4) Ştergerea unui element din listă

Operaţia de ştergere a unui element al listei dublu înlănţuite este în principiu


aceeaşi cu cea de la listele simplu înlănţuite, însă ţinând cont de legăturile
duble:

void stergere (LISTA *r)


{
// r - adresa nodului care va fi şters
LISTA *s,*q;
if (r==prim)
{
// Se va şterge primul elemental listei
s=prim;
prim=prim->urm;
prim->ant=NULL;
delete s;
}
else
if (r==ultim)
{
// Se va şterge ultimul nod al listei
s=ultim;
ultim=ultim->ant;
ultim->urm=NULL;
delete s;
}
else
{
// ştergerea unui nod din interiorul listei
s=r;
// în s se reţine adresa nodului care va fi şters
efectiv
r->urm->ant=r->ant;
r->ant->urm=r->urm;
delete s;
}
}
Spre deosebire de listele simplu înlănţuite, crearea unei liste dublu înlănţuite se
face prin adăugarea de elemente la sfârşitul listei, deoarece este necesară
adresa ultimului nod din lista.

void creares (LISTA *prim, LISTA *ultim)


{
int x;
char c;
ultim=prim=new LISTA; /*este necesara folosirea
pointerului ultim deoarece adaugarile de elemente se fac
la sfarşitul listei */
cout<< “Introduceti prima informatie a listei: “;
cin>>prim->inf;
prim->urm=prim->ant=NULL;
cout<<”Continuati sa introduceti elemente?(D/N)”;
cin>>c;
while (toupper(c)==’D’)
{
cin>>x;
adaugs (x,ultim); // funcţie definita anterior
cout<<”Continuati sa introduceti
elemente?(D/N)”;
cin>>c;
}
}
CAPITOLUL

3
Capitolul 3 - Aspecte metodice cu
privire la predarea alocării dinamice a
memoriei

3.1 Obiectivele generale ale disciplnei Informatică în învătământul


preuniveristar

Consideraţii generale

Transformările societăţii româneşti din ultimii ani, dezvoltarea şi


răspândirea informaticii, pătrunderea hardware-ului şi software-ului modern în
viaţa economică, socială şi în învăţământ, impun o pregătire diversificată a
tinerilor în acest domeniu. Învăţământul preuniversitar de informatică trebuie să
asigure dobândirea, fie a unor cunoştinţe de informatică la nivel de cultură
generală, necesare continuării studiului, fie a unor cunoştinţe de informatică
având caracter aplicativ la un nivel mediu de profesionalism care să asigure
posibilitatea găsirii unui loc de muncă.
Toţi tinerii trebuie să-şi asigure un minim de cunoştinţe de tehnologia
informaţiei, necesare utilizării calculatoarelor în rezolvarea problemelor
profesionale în diverse domenii ale vieţii economice. Indiferent dacă vor absolvi
sau nu o instituţie de învăţământ superior vor avea extrem de mult de câştigat
dacă vor avea cunoştinţe de informatică, reuşind astfel să corespundă
cerinţelor pe care locurile de muncă ale prezentului şi viitorului apropiat le vor
ridica în faţa lor.
Predarea informaticii diferă în conţinut şi stil faţă de predarea altor
discipline. În predarea informaticii nu există şabloane sau reţete care să fie
obligatorii, în schimb este nevoie de talent şi de dorinţa de a descoperi
chemarea, vocaţia, pentru meseria de profesor. Această chemare trebuie
constietizată. Profesorul trebuie să descopere secretele modului în care trebuie
educată viitoarea generaţie care trebuie să dobândească o viziune cu totul
nouă despre lume. Societatea superinformatizată va solicita din partea
membrilor săi nu doar cunoaşterea calculatorului şi a modului de utilizare a
acestuia, ci şi o atitudine curajoasă, flexibilă şi dinamică în faţa unor situaţii sau
instrumente informatice noi, necunoscute. Cultura informatică (Computer
Literacy) va trebui să devină parte integrantă din cultura generală a fiecărei
persoane, fapt ce impune învăţarea elementelor ei de bază în şcoală. [4, 5, 6,
7, 8, 9]

Obiectivele generale ale disciplinei informatică în învăţământul preuniversitar

a) Pornind de la faptul că nu există domeniu de activitate unde să nu se


prelucreze şi să nu se transmită informaţii atât în cadrul domeniului respectiv
cât şi spre exteriorul lui, afirmăm că azi informaţia este foarte valoroasă, ea
trebuie stocată, prelucrată şi transmisă în condiţii care asigură corectitudine şi
exactitate, deci la nivel profesional. Rezultă direct că unul din obiectivele
învăţământului de informatică trebuie să fie asigurarea înţelegerii tuturor
problemelor legate de informaţie şi de stocarea, prelucrarea, respectiv
transmiterea ei.

b) Dezvoltarea deprinderilor moderne de utilizator, adică pregătirea elevilor


astfel încât să poată beneficia de lumea calculatoarelor, respectiv să poată
folosi posibilităţile asigurate de cultura informatică, trebuie să stea în atenţia
învăţământului preuniversitar. Aceasta presupune identificarea şi înţelegerea
principalelor componente ale calculatorului, precum şi a funcţionării reţelelor de
calculatoare. Elevii trebuie să cunoască interfeţele utilizator ale sistemelor de
operare şi a celor mai răspândite utilitare, modul de instalare, exploatare şi
utilizare a acestora, să dobândească deprinderi necesare cunoaşterii şi folosirii
oricărui software nou, precum şi a versiunilor noi pentru cel existent.

c) Dezvoltarea gândirii algoritmice este un obiectiv la realizarea căruia


informatică are o contribuţie esenţială şi eficientă. Asemenea matematicii,
informatică dezvoltă gândirea în general, şi are în şcoală dar şi în viaţa de zi cu
zi, un rol esenţial în procesul de învăţare, în formarea caracterului şi a
personalităţii. Dar informatică (în plus faţă de matematică) dezvoltă gândirea
algoritmică, diferită faţă de gândirea matematică (preponderent teoretică şi
abstractă) prin faptul că obligă elevii să finalizeze rezolvări ale unor aplicaţii
practice concrete. Această gândire nu se leagă doar de cunoştinţele de
programare, ci şi de cunoştinţele referitoare la gestionarea bazelor de date, la
utilizarea tabelatoarelor, editoarelor de texte etc. Demonstrarea teoretică a
existenţei unei soluţii pentru o problemă dată (ca în matematică) chiar dacă
este importantă, nu este echivalentă cu rezolvarea problemei specificate. Este
nevoie de dezvoltarea abilităţilor concrete de a rezolva probleme.

d) Dezvoltarea deprinderilor necesare muncii individuale se realizează într-un


proces firesc, în dialog cu calculatorul. Acesta este un instrument care
reactionează imediat la încercările elevului şi care totodată nu îşi pierde
răbdarea niciodată, oferă şansa unei învăţări conform ritmului propriu al
fiecăruia, oferă posibilitatea lucrului diferenţiat cu elevii talentaţi sau cu cei care
lucrează mai lent.
Informatica este esenţial legată de lucrul individual cu un calculator, deci
dezvoltă într-un mod firesc deprinderea de a lucra individual. Din nefericire,
aceasta poate conduce la formarea unor trăsături cum ar fi individualismul sau
egoismul. Aici intervine rolul profesorilor să încurajeze şi să organizeze
activitatea în grupuri.

e) Prin folosirea reţelelor de calculatoare a aparut posibilitatea unui schimb de


informaţie între utilizatorii de calculatoare, mult mai eficient decât cel clasic
(poşta, telefon, telex etc.). Educarea elevilor în sprijinul unei activităţi
desfăşurate în grup, în colaborare, se finalizează prin predarea informaticii
orientate pe proiecte. Realizarea unor aplicaţii mai complexe impune lucrul în
grup, modularizarea programului şi păstrarea contactelor cu ceilalţi membri ai
grupului. În viaţa reală majoritatea activităţilor nu se desfaşoară izolat, de aceea
profesorii trebuie să stimuleze acest fel de activităţi. Proiectele trebuie să fie
împărţite în activităţi repartizate pe individ, interconectate şi elevii trebuie
învăţaţi să preia şi să transmită informaţii respectând anumite specificaţii.
Evident, profesorul are rol de supervizor.
Obişnuirea elevilor cu diverse responsabilităţi, cu răspunderea privind
finalizarea propriei munci şi asigurarea înlănţuirii unor elemente realizate în
paralel, îi va pregăti pentru o activitate pe care cu siguranţă o vor întalni în viitor.

f) Este important ca elevii să fie capabili să aleagă din instrumentarul existent


pe cel de care are nevoie, să identifice şi să folosească software-ul cel mai
potrivit aplicaţiei pe care o realizează. Rezultă că trebuie să fie capabili să
analizeze problema, să descopere cerinţele şi să decidă ce software şi ce
instrumente ale acestuia sunt cele mai utile. Pe de altă parte, pentru ca elevul
să poată ”alege”ceva, el trebuie să afle măcar de existenţa şi caracteristicile
esenţiale mai multor tipuri de software.

g) Educarea elevilor, urmărind atent dezvoltarea spiritului inventiv şi creator se


realizează în mai multe sensuri în cadrul disciplinei informatică. Indiferent de
conţinutul programului, sau al aplicaţiei, ceea ce realizează elevul trebuie să
funcţioneze, trebuie să fie utilizabil; altfel spus, trebuie să aibă toate calităţile
unui produs finit. Aceste cerinţe în informatică se concretizează prin:
- interfaţa prietenoasă;
- asigurarea funcţionării aplicaţiei în mod inteligibil chiar şi în cazul unui
utilizator neautorizat, sau al unuia care nu cunoaşte aplicaţia;
- fiabilitate; aplicaţiile trebuie verificate şi testate;
- performanţa; analiza complexitatii (în cazul algoritmilor) şi a eficientei
(în cazul aplicaţiilor nealgoritmice) trebuie să devină obişnuinţă;
- portabilitate.
h) În liceu informatica trebuie să pornească de la un nivel de bază, incluzând
Tehnologia informaticii (Computer Literacy). La acest nivel, nu putem spune că
informatică este o disciplină izolată sau independenăa. Un scop important este
ca elevii să ştie să folosească tehnologia informaţiei pentru a rezolva diverse
probleme. Astfel, profesorii altor discipline pot prezenta sau solicită realizarea
unor aplicaţii de tip software educaţional, deci elevii ar trebui să ştie să utilizeze
cunoştinţele dobândite la orele de informatică, realizând la rândul lor,
instrumente noi, care se pot folosi în cadrul altor lecţii.
Principalele domenii care ar trebui abordate sunt:
- cunoaşterea şi utilizarea calculatorului;
- procesare de text ;
- procesoare grafice;
- algoritmi simpli şi noţiuni de programare;
- baze de date;
- procesoare de calcul tabelar;
- servicii Internet;
- documente HTML;
- facilităţi multimedia;
Pe de altă parte, elevii trebuie să fie capabili să elaboreze, programeze
şi execute algoritmi simpli care rezolvă probleme elementare sau care pot fi
utilizate în cadrul altor discipline: matematică, fizică, chimie etc. Această
introducere în programare nu trebuie să fie cel mai important capitol; acesta
poate fi abordat şi accentuat în mod diferit în clasele cu profil tehnic în funcţie
de specialitatea studiată.

i) Elevii trebuie să conştietizeze influenţa informaticii asupra societăţii şi invers.


Dezvoltarea impetuoasă a informaticii modifică societatea, de aici rezultând
necesitatea înţelegerii rolului pe care îl au calculatoarele în schimbările din viaţa
socială, economică şi ale aspectelor etice în ceea ce priveşte utilizarea lor.
Elevii trebuie să conştietizeze avantajele care derivă din utilizarea
calculatoarelor, respectiv a reţelelor. În schimb, etica are rolul de a-i atenţiona
asupra dreptului de autor, a confidenţialităţii informaţiilor, a protecţiei bazelor
de date, asupra efectelor spargerii unor reţele, conturi, ale virusilor etc.
Concepte false legate de disciplina Informatică

Temele, domeniile abordate în cadrul disciplinei Informatică dau


naştere, în permanenţă, unor polemici în rândul profesorilor de informatică,
precum şi în rândul celor care predau alte discipline, al profesioniştilor şi al
părinţilor. Domeniile care se vor învăţa şi importanţa lor se pot pune în lumină
pornind de la conceptele ”extremiste” legate de subiect. Dintre aceste
”concepte”, voi enumera câteva:
- Disciplina informatică = ” Să vorbim despre informatică în general!”
- Predarea informaticii = pregătirea unor specialişti
- Predarea informaticii = pregătire (doar) utilizatori
- Pregătirea de utilizatori = predarea funcţiilor unui utilitar
- Predarea informaticii = pregătire (doar) de programatori
- Pregătirea de programatori = învăţarea unui singur limbaj de
programare
- Predarea informaticii = predarea unor domenii având aceeaşi
”greutate”
- Predarea informaticii = predarea unor teme alese “samavolnic”
- Predarea informaticii = predarea integrală a unor instrumente
- Predarea informaticii = predarea secvenţială a unor teme independente
- “Totul trebuie predat la zi, adică ultimele noutăţi” ( !)
- ”Profesorul are mai multe cunoştinţe decât elevul” ( !)
- ”Pentru predarea informaticii nu este necesară disciplina informatică”
(!)
OBSERVAŢIE:
Fiecare concept conţine şi un miez de adevăr, dar acceptarea lor
integrală sigur este greşită !!!

Strategii posibile în realizarea obiectivelor


Nu voi intra în prezentarea conţinuturilor învăţarii, ci voi prrezenta câteva
idei generale referitoare la modul în care se va împărţi conţinutul disciplinei în
cadrul unui an şcolar. Din acest punct de vedere există trei categorii de domenii:
- Conţinutul din subdomeniu poate fi predat continuu, în blocuri mari de
cunoştinte (de exemplu, nu este bine ca predarea unui editor de texte să fie
făcută câteva ore, apoi întreruptă câteva ore şi iar continuată).
- Conţinutul din subdomeniu poate fi predat în blocuri de 1-2 ore maximum,
orice încercare de a lungi subiectul conduce la eşec (de exemplu, în şcoala
generală nu se va preda un sistem de operare pe durata unui semestru – copiii
se vor plictisi şi nu ar putea asimila cunoştinţele stufoase, referitoare la un
singur subiect).
- Conţinutul subdomeniului va necesita doar părţi de 5-10 minute din cadrul
unei ore (în această categorie intră elemente de: istoric, aspecte legate de
echipă etc.); nu există disciplină separată cu titlul “Istoric” sau “Etică”, dar se va
căuta să se împrospateze o lecţie grea sau o prezentare mai monotonă cu
elemente din aceste domenii. [4, 5, 6, 7, 8, 9]

3.2 Domeniile Informaticii în programele scolare. Clasificarea lor

Domeniile Informaticii – gruparea lor

Cunoştinţele de informatică se pot clasifica în foarte multe moduri.


Pentru fiecare domeniu voi prezenta obiectivele specifice, urmărite în procesul
de instruire în cadrul disciplinei Informatică.
Din obiectivele învăţământului de informatică rezultă ce scopuri trebuie
urmărite în cadrul disciplinelor, ce anume se va preda şi ce anume se va utiliza
în cadrul altor discipline. Obiectivele specifice, în funcţie de domeniu, vor fi
următoarele:
a) Modelare, algoritmizare, programare
Din acest domeniu fac parte procese de baza ce rezultă din conceptul
axiomatic valabil privind rolul calculatorului în realizarea unor aplicaţii
aparţinând diferitelor sfere ale vieţii de zi cu zi. Analiza unei probleme, alegerea
structurilor de date, a paşilor algoritmului şi programarea în sine, toate aparţin
acestui domeniu; necesită formarea unor deprinderi speciale dobândite prin
învăţare şi exersare.
Lumea, mediul înconjurător, sunt înţelese pe baza unor modele.
Dezvoltarea deprinderilor de modelare, obişnuirea elevilor cu gândirea logică
se poate (depinde de talentul şi priceperea profesorului) realiza eficient pe
parcursul învăţării metodelor de programare.
Obligaţia unor formalizari necesită o gândire precisă, riguroasă. Pe
parcursul construirii programelor formalizarea apare ca proces în alegerea
(crearea) structurilor de date şi în proiectarea algoritmului. Formalizarea este
un proces care trebuie introdus treptat, cu mare grijă, în funcţie de categoria de
vârstă, pentru a nu “speria” elevii. Este important să se acorde ponderea
adecvată predării acestui domeniu deoarece prin metode corespunzătoare se
poate realiza dezvoltarea pe de o parte a deprinderilor de abstractizare, pe de
altă parte, a unei gândiri algoritmice, disciplinate. Conform studiilor psihologice,
perioada cea mai receptivă din viaţă unui individ este adolescenţa; în aceşti ani
se pot forma obişnuinte extrem de valoroase cum ar fi: gândirea independenţa,
logică şi algoritmică, respectiv capacitatea de a analiza şi de a sintetiza.
Scopul principal al utilizării calculatorului este de a se obţine, pe baza
datelor de intrare, date de ieşire (date noi). În cazul învăţării algoritmicii, analiza
problemei îi conduce pe elevi la modele. Va trebui stabilit modelul prin care se
vor reprezenta datele (de intrare şi de iesire), apoi va trebui stabilit modelul
pentru acele acţiuni care, pe baza datelor de intrare, determină rezultatele
(datele de ieşire). Rezultă că învăţarea algoritmilor nu se poate separa de
învăţarea structurilor de date.
Trebuie să se atingă performanţa ca elevii să înteleagă că în procesul de
rezolvare de probleme cu ajutorul calculatoarelor etapa cea mai importanta
este cea a descoperirii algoritmului şi nu scrierea efectiva a programului
(codificarea). Dar pentru a programa corect şi eficient sunt necesare cunoştinţe
practice de programare. Altfel spus, nu se poate învăţa programare pe “hârtie”.
Este nevoie stringentă de calculatoare, pentru ca elevii să se poata verifica, să
acumuleze succes, să fie stimulate de rezultatele obtinuţe.
Concluzii:
- Învăţarea unui limbaj de programare nu este un scop în sine (limbajul este un
instrument similar cu instrumentul numit calculator)
- Elevii trebuie să înveţe structurile de control de bază independent de limbajele
de programare. (Ulterior, se poate atrage atenţia asupra diferenţelor dintre
algoritmi, datorate diferitelor implementări, dar elevii trebuie să fie pregătiţi
pentru viitor, când vor fi nevoiţi să schimbe limbajul de programare.)
- Elevii trebuie să înteleagă că programul este un produs (deci trebuie să
posede toate condiţiile necesare utilizabilităţii) – şi anume faptul că un program
este corect dacă:
- este codul (corect) al unui algoritm corect;
- pe baza datelor de intrare corecte produce rezultate corecte;
- prelucrând date de intrare oarecare se finalizează în mod inteligibil;
- are o interfaţă prietenoasă;
- este lizibil, uşor de modificat şi de întreţinut;
- produce rezultate într-un interval de timp rezonabil.
Recomandări:
- Se vor învăţa metode de verificare a algoritmilor cum ar fi: “metoda cutiei
negre” şi “metoda cutiei transparente”.
- Nu se vor constrânge elevii să memoreze “reţete”, se va pune accent pe
înţelegerea paşilor unui algoritm şi se vor încuraja elevii în a dezvolta şi
prezenta ideile lor originale.

b) Instrumentele programării
Din acest domeniu fac parte cunoştinţele privind instrumentele soft care
sunt necesare pentru implementarea algoritmilor şi structurilor de date, de
asemenea pentru verificarea şi depanarea lor.
Din această grupă fac parte metodele de reprezentare a algoritmilor
(scheme logice, diferitele variante de pseudocod, organigrame etc.), limbajele
de programare, instrumentarul oferit de mediile de programare pentru
urmărirea/depanarea programelor.
Învăţarea acestor instrumente nu se poate separa de cunoştinţele învăţate
la punctul a), rezultă deci că nu este indicată predarea independenţa a lor.
Legat de un limbaj de programare, se va preda atât cât este necesar pentru
rezolvarea şi verificarea problemelor enuntate.
În condiţii ideale, limbajul de programare rămâne la latitudinea profesorului
şi va fi ales în funcţie de problemele propuse spre rezolvare, de categoria de
vârstă şi de obiectivele generale urmărite.

c) Rezolvarea problemelor având caracter utilitar


Aici se studiază acele procese aparţinând instruirii informatice care se referă
la probleme ale căror rezolvare necesită utilizarea unui editor grafic sau de
imagini, a unui editor de texte, a unui tabelator, a unui sistem de gestiune a
bazelor de date etc.
Se recomandă ca utilitarele să se studieze în funcţie de problemele concrete
care urmeaza a fi rezolvate. Accentul se va pune pe posibilităţile oferite şi nu
pe modalităţile de realizare. Atenţia nu se va concentra asupra instrumentului
(hard sau soft) ci pe cunoaşterea “filozofiei” produsului.

d) Cunoaşterea şi folosirea utilitarelor


Trebuie realizată o viziune de ansamblu din care să se desprindă
caracteristicile clasice în majoritatea utilitarelor din clasa respectivă, de
particularităţile specifice produsului; de asemenea vor fi evidenţiate acele
aspecte care, probabil, se vor îmbunătăţi în versiunile următoare.
Nu se va aşeza în centrul programei un utilitar, nu se va preda utilitarul pe
baza meniurilor, ci se vor realiza aplicaţii cu ajutorul lor. Accentul se va pune
pe funcţionalitatea softului utilizat.
Elevii vor învăţa editare de texte, vor desena sau vor crea baze de date, vor
rezolva problema propusă, deci vor folosi aceste utilitare şi vrând nevrând se
vor familiariza cu ele. Evident, şi de data aceasta vor avea nevoie de
certitudinea că au lucrat corect, deci va trebui să realizeze şi să finalizeze
practic aplicaţiile.

e) Rezolvarea unor probleme practice din viaţa de zi cu zi sau propuse de alte


discipline cu ajutorul instrumentelor informatice
În acest domeniu punctul de pornire îl constituie problema concretă care
urmează a fi rezolvată. Tot mai multe probleme, având caracter practic, se vor
rezolva în şcoli cu ajutorul calculatoarelor cu aplicaţii finalizate de către elevi:
evidenţa bibliotecii, evidenţe legate de concursuri etc.
Dacă şcoala solicita instrumente informatice, este benefic pentru procesul
instructiv în ansamblul său, că aceste aplicaţii să fie realizate de elevi şi să fie
dezvoltate de la un an la altul. De asemenea, sunt profesori de la alte discipline
care solicită programe de instruire asistate de calculator. Aceste probleme se
vor rezolva de către elevi sub îndrumarea dublă a profesorului de la disciplina
respectivă şi a celui de informatică.
În aceste situaţii va fi nevoie de alegerea instrumentelor, de combinarea şi
de cunoaşterea lor.
Nu se vor preda cunoştinţe noi, ci se vor rezolva probleme noi pe baza
cunoştinţelor existente.
Din această categorie de activitate face parte şi realizarea de proiecte. În
noul plan de învăţământ există menţionate câteva elemente ale obiectivelor
strategice, generale ale întregului învăţământ. Printre ele un loc important îl
ocupă realizarea de proiecte în grup sau, mai rar, individual. Accentul se va
pune pe utilitatea, utilizabilitatea şi finalizarea acestor proiecte.

f) Funcţionarea instrumentelor informatice, utilizarea lor


Elevii, de regulă nu despart aspectele soft de cele specifice de hard. Pentru
ei calculatorul este un instrument “care ştie să facă o serie de lucruri” şi nu ţin
neapărat la învăţarea “separată” a celor două laturi: hard şi soft. Chiar dacă în
învăţământul preuniversitar de informatică nu există disciplina care să se
ocupe separat cu hardware-ul, nu se pot evita în totalitate informaţiile privind
aceste cunoştinţe.
Obiectivul cel mai important rămâne şi de data aceasta învăţarea utilizării.

g) Informatica şi societatea
Elevii trebuie să cunoască istoricul informaticii ca subdomeniu al culturii; la
fel de important este să ne ocupăm şi de “prezicerea” viitorului, respectiv de
prezentarea efectelor informaticii în zilele noastre asupra societăţii. Nu se va
preda într-un bloc contiguu tot ceea ce trebuie să înveţe elevii despre relaţia
informatică-societate, ci sub forma unor părţi de 5-10 minute din anumite lecţii.
Nu sunt suficiente doar enumerările, respectiv prezentările “distante”;
trebuie accentuate modificările care intervin deodată cu aceste “prezenţe” ale
informaticii în viaţa şi munca de zi cu zi.

h) Matematica informaticii
Se referă la acele cunoştinţe din matematică (de bază) care la această
disciplină, matematică, fie nu sunt tratate deloc, fie sunt tratate într-un moment
nepotrivit scopurilor noastre. De exemplu, în cadrul disciplinei matematică elevii
se intâlnesc cu noţiunea de matrice doar în clasa a XI-a, iar profesorul de
informatică are nevoie de noţiunea de tablou în clasa a IX-a.
Se vor prezenta noţiuni matematice doar atunci şi acolo unde rezolvarea
problemei necesită cunoaşterea acestor noţiuni de bază.
Este important să nu se trateze superficial aceste noţiuni de matematică,
dar totodată să nu se supraliciteze în detrimentul disciplinei matematică. Chiar
dacă este vorba despre aceeaşi noţiune, informaticianul o va privi altfel decât
matematicianul, în primul rând datorită faptului că el este interesat în rezolvarea
unei probleme concrete, a unei aplicaţii.

i) Cunoştinţe elementare (de bază) în informatică


În acest domeniu se va discuta despre cunoştinţe elementare care din
cauza utilizării lor multiple şi în multe forme, ar putea constitui partea
introductivă a mai multor discipline de informatică.
Aceste noţiuni trebuie foarte bine fundamentate. De exemplu: structuri de
date, structuri de control, principiile programării structurate etc. Evident, ele se
tratează în mod diferit în cazul cazul diferitelor categorii de vârstă, dar tocmai
acesta este şi motivul pentru care trebuie tratate cu precizie şi nu cu
superficialitate. Numai aşa se creeaza premisele necesare pentru ca elevul să
poată “construi” în mintea lui, fără ca reluările să creeze haos.
Nu este necesară tratarea teoretică şi completă, în schimb trebuie verificat
întotdeauna ce ştiu deja elevii, ce anume nu este încă suficient de clar pentru
ei, apoi urmează precizările noi.
Nu există disciplină care să conţină numai cunoştinţe de bază, ele apar pe
parcurs în cadrul fiecarei discipline de informatică, pe măsura rezolvării
problemelor de complexitate mereu mai ridicată.

Domeniile informaticii prevăzute în programele şcolare. Cunoaşterea şi analiza


programelor şcolare

Acest subiect abordează strategiile de bază ale proiectării programei


analitice, utilitatea conţinuturilor prin precizarea obiectivelor generale şi
specifice.
Deoarece obiectivele generale ale diciplinei informatică au fost trecute în
revistă, voi fixa doar câteva principii care trebuie să stea la baza aplicării
acestor programe. Accentul va fi pus pe latura aplicativă. Este foarte important
să se ţină cont de categoria de vârstă cu care se lucrează.
Planul de învăţământ reprezintă documentul prin care se precizează
disciplinele specifice învăţământului informatic pe ani de studii şi numărul de
ore pentru fiecare obiect de studiu. Planul de învăţământ este elaborat de
Ministerul Educaţiei şi Cercetării şi are caracter unitar şi obligatoriu pentru
fiecare dintre stadiile de pregătire. Planul de învăţământ a suferit multiple
modificari de-a lungul anilor, în acest moment fiind conceput astfel încât la toate
clasele de liceu să fie minim o oră de informatică pe săptămână, respectiv
tehnologia informaţiei (clasele de la alte profile decât matematică-informatică),
iar la clasele de profil matematică-informatică numărul de ore de informatică
creşte treptat, pe ani de studiu, în funcţie de cantitatea şi consistenţa materiei
de studiat.
Programa şcolară (sau analitică) de informatică stabileşte conţinutul
obiectului informatică pentru fiecare an de studiu şi pentru fiecare disciplină,
fixând natura şi volumul cunoştintelor, priceperilor şi deprinderilor care se vor
însuşi într-o perioadă de timp. Programa şcolară prezintă succesiunea
cunoştinţelor care urmează a fi predate şi împărţirea acestora pe capitole,
subcapitole, teme şi lecţii, indicându-se numărul de ore necesare.
Manualul şcolar reprezintă documentul de bază folosit în procesul de
învăţământ, constituind materialul bibliografic esenţial pentru elev în însuşirea
cunostinţelor. Manualul şcolar concretizează şi dezvoltă conţinutul programelor
şcolare specifice fiecărei discipline de studiu informatic. Manualul şcolar este
util în condiţiile în care îndeplineşte cerinţele unui manual modern, al cărui
conţinut trebuie să fie structurat în funcţie de obiectivele operaţionale pe care
le urmăreşte predarea obiectului de studiu respectiv. Manualul de informatică
trebuie să îndrume elevul spre formarea şi consolidarea unei gândiri
algoritmice, obişnuindu-l astfel cu munca independentă, creatoare.

Strategii posibile în realizarea obiectivelor


- predarea liniară – presupune o secvenţialitate a temelor tratate; la niveluri
diferite de clase se vor preda teme diferite
- predarea ciclică, concentrică
Atât în programele analitice cât şi detaliat în manuale, se revine la acelaşi
conţinut, în clase succesive, dar pe o treaptă superioară. Revenirea se face din
două motive: la prima întâlnire a elevului cu noţiunea (metoda) acesta nu o
poate cuprinde în toată rigoarea ei sau în toată întinderea ei. Astfel, unele
cunoştinţe se prezintă în sistem concentric calitativ când însuşirea completă,
riguroasă se face prin restructurări, reinterpretări pe diferite trepte de
şcolaritate, începând cu clasele mai mici până în clasele mari.
În această categorie intră cunoştinţe legate de sisteme de operare, medii
de programare, metode şi tehnici de programare etc.
Vor fi şi cunoştinţe de informatică ce se vor preda în şcoală concentric
cantitativ. Nu se poate preda aceeaşi cantitate de cunoştinţe în gimnaziu şi în
liceu. Atunci când anumite domenii se reiau în liceu, profesorul trebuie să ştie
ce anume şi cât a învăţat elevul în clasele mai mici. De asemenea, trebuie să
se ţină cont de cunoştinţele acumulate la alte discipline pentru a şti pe ce
anume se poate baza.
O altă problemă importantă se leagă de modul în care se va împărţi
conţinutul disciplinei în cadrul unui an şcolar. Din acest punct de vedere, există
trei categorii de domenii:
- Conţinutul din subdomeniu poate fi predat continuu, în blocuri mari de
cunoştinţe;
- Conţinutul din subdomeniu poate fi predat în blocuri de 1-2 ore maximum,
orice încercare de a lungi subiectul, chiar dacă avem cele mai bune intenţii,
conduce la eşec;
- Conţinutul subdomeniului va necesita doar părţi de 5-10 minute din cadrul
unei ore.
Atunci când se construieşte, se formează disciplina, trebuie să se ţină cont
de următoarele criterii:
1) Disciplina Informatică trebuie să poată fi predată
- trebuie să existe profesor cu calificare adecvată care s-o predea;
- trebuie să existe dotarea necesară care permite profesorului să predea
eficient;
- trebuie să corespundă posibilităţilor categoriei de vârstă;
- nu trebuie să cauzeze supraîncărcarea elevilor.
2) Disciplina Informatică trebuie să poată fi învăţată
- va trebui să stimuleze şi să dezvolte gândirea;
- va trebui să sprijine elevii în dezvoltarea capacităţii de a se concentra
asupra esenţei;
- va trebui să–i ajute în dezvoltarea capacităţii de a analiza şi de a sintetiza;
- va trebui să-i stimuleze în direcţia rezolvării problemelor şi mai ales în a
finaliza rezolvările.
3) Disciplina Informatică trebuie să fie orientată spre aspecte practice
- nu va fi o ”joacă” de dragul utilizării calculatorului;
- în orice subdomeniu al informaticii se vor evita prezentările teoretice
exagerate.
4) Disciplina Informatică trebuie să stimuleze munca individuală
5) Conţinutul disciplinei trebuie să fie în aşa fel construit încât să permită
profesorului să se convingă că a fost asimilat
- Elevii, pe tot parcursul procesului de învăţare, trebuie să realizeze cât
ştiu în raport cu cerinţele şi, de asemenea, în raport cu ceilalţi elevi din clasă.
Analiza greşelilor tipice sau specifice trebuie să fie conţinută în temele
disciplinei.
6) Conţinutul disciplinei trebuie să fie, dacă se poate, şi interesant!
Pe baza acestor criterii, domeniile disciplinei informatică se pot grupa în
jurul a două domenii principale:
- Algoritmizare, modelare, programare
- Rezolvarea problemelor având caracter utilitar prin intermediul unor
medii existente
În aceste două domenii intră cunoştinţe care nu se pot dobândi fără aportul
creator şi activ al elevilor. Dobândirea lor le asigură senzaţia de succes; de
asemenea, datorită utilizării calculatorului, feed-back-ul funcţionează continuu.
În cadrul disciplinei, aceste două domenii pot alterna chiar pe parcursul
unui an şcolar. În clasele unde scopul este predarea unor cunoştinţe de bază,
nu se va prefera predarea monolitică a acestor cunoştinţe într-o secvenţialitate
întâmplătoare, ci se va căuta combinarea lor astfel încât să se poată realiza
obiectivele generale ale învăţământului de informatică. Astfel, se va evita ca
disciplina să devină monotonă şi plictisitoare.
Nici unui profesor de informatică nu i se poate pretinde să cunoască totul,
din toate domeniile. De asemenea, din aceste domenii se va preda doar cât
este absolut necesar pentru a atinge obiectivele celor două mari domenii:
Algoritmizare, modelare, programare, respectiv Rezolvarea problemelor cu
caracter utilitar prin intermediul unor medii existente.

3.3. Continutul programei scolare

Pentru învăţământul liceal, în funcţie de filiere, profiluri şi specializări,


disciplinelor de informatică le sunt alocate un număr variabil de ore:
- filiera teoretică:
- specializările filologie, ştiinţe sociale, ştiinţe ale naturii: de la 1 la 2
ore pe săptămână;
- specializare matematică-informatică: 3 - 5 ore pe săptămână;
- filiera tehnologică: la majoritatea specializărilor, 2 ore pe săptămână;
- filiera vocaţională: de la 1 la 4 ore pe săptămână, în funcţie de specializare.
O categorie aparte o reprezintă, de altfel, clasele de liceu cu specializarea
matematică-informatică, profil informatică - intensiv, aprobate prin ordin M.E.N.
numărul 3879 din 26.05.1999 [4, 5, 6, 7, 8, 9] care dispun atât de un număr de
3-5 ore de aplicaţii practice de laborator, efectuate cu grupe de 10-12 elevi, cât
şi de 2 ore de teorie cu întreaga clasă, săptămânal.
Programele şcolare au trecut printr-un proces complex de elaborare şi
revizuire în viziune curriculară, presupunând o reproiectare interactivă a
obiectivelor, conţinuturilor, activităţilor de învăţare şi a principiilor şi metodelor
de evaluare.
Programele şcolare (analitice) stabilesc conţinutul disciplinelor de
informatică, pentru fiecare an de studiu şi materie, pe nivele, filiere, profiluri şi
specializări, precum şi pe forme de învăţământ. Acestea precizează ce
cunoştinţe, priceperi, deprinderi trebuie să-şi însuşească elevii în anul de studiu
respectiv şi care este succesiunea în care trebuiesc dobândite acestea.
Programele sunt elaborate de către Comisia de specialitate a Ministerului
Educaţiei şi Cercetării, sub coordonarea Consiliului Naţional pentru Curriculum,
din care fac parte cadre didactice cu experienţă din învăţământul universitar,
profesori de liceu cu rezultate deosebite în activitatea de la catedră, inspectori
şcolari din inspectoratele judeţene şi ai Ministerului Educaţiei şi Cercetării,
psihopedagogi şi cercetători din Institutul de Ştiinţe ale Educaţiei.
Realizate în concordanţă cu noile planuri cadru, urmărind o
descongestionare raţională a conţinuturilor, actualele programe şcolare
reprezintă totuşi o adevărată revoluţie didactică în ceea ce priveşte conceptele
de formare a competenţelor de nivel superior, de învăţare în clasă, de studiu în
grup, de învăţare asistată de calculator, de autodocumentare, etc.
Programa şcolară reprezintă un instrument al procesului instructiv-educativ
la o disciplină de învăţământ. Descrie condiţiile deziderabile pentru reuşita
învăţării în termeni de obiective, conţinuturi, activităţi de învăţare.
Programa şcolară descrie „oferta educaţională" la o disciplină pe o
perioadă limitată de timp (un an şcolar) şi oferă sugestii metodologice de
abordare a conţinuturilor astfel încât să se atingă obiectivele stabilite sau
competenţele vizate.
Noile programe şcolare sunt elaborate în concordanţă cu noile Planuri -
cadru de învăţământ.
"Viziunea curriculară" de alcătuire a programelor şcolare permite o „bună
orientare" a predării / învăţării în raport cu „obiectivele de formare care vizează
competenţele de nivel superior, de aplicare a cunoştinţelor şi competenţelor în
contexte noi şi de rezolvare de probleme teoretice şi practice".
Noile programe şcolare nu mai reprezintă o „înşiruire" de conţinuturi
grupate în capitole şi lecţii, ci în interiorul lor, conţinuturile sunt privite ca
„vehicule de formare a competenţelor intelectuale şi relaţionale de nivel
superior, a atitudinilor şi comportamentelor necesare unui tânăr într-o societate
democratică a timpului nostru".
O programă şcolară adecvată este rezultatul unui exerciţiu colectiv,
desfăşurat sub semnul unui profesionalism specific, dar nu exclude inovaţia
curriculară locală, la nivelul individului sau colectivului didactic. Este imperios
necesară parcurgerea următoarelor etape: elaborarea individuală (propuneri de
programă), care se face de către colectivele de catedră ale unităţilor de
învăţământ sau de către cadrele didactice, individual; analiza propunerilor şi
elaborarea colectivă; aceasta presupune stabilirea formei finale a unei
propuneri de programă de către echipe de lucru, stabilite - de regulă de către
Comisia de specialitate a Ministerului Educaţiei şi Cercetării; prezentarea şi
argumentarea în faţa Comisiei de specialitate a Ministerului Educaţiei şi
Cercetării a formei stabilite de către echipele de lucru.
După o perioadă de 2-3 săptămâni, răgaz în care fiecare membru
analizează programa rezervată subcomisiei din care face parte, aceasta este
rediscutată şi i se aplică modificările necesare. Programele astfel finalizate sunt
supuse aprobării Consiliului Naţional pentru Curriculum din cadrul Ministerului
Educaţiei şi Cercetării.
Elaborarea programelor şcolare trebuie să îndeplinească anumite cerinţe
de ordin ştiinţific, psihologic, didactic şi metodic. Programa şcolară pentru un
obiect de studiu conţine:
- o notă informativă cu privire la scopurile şi obiectivele predării; indicaţii
relative la ordonarea materiei şi repartizarea orelor pe capitole, subcapitole,
teme, etc; îndrumări cu privire la folosirea manualelor, materialului bibliografic,
etc.;
- materia de predat, detaliată şi prezentată în succesiunea abordării ei,
numărul de ore afectat lucrărilor scrise, recapitulărilor, evaluării, ore la
dispoziţia profesorului etc.;
- modalităţi de folosire a manualelor şi a materialului documentar
complementar (culegeri de probleme, documentaţii de, firmă, manuale de
utilizare, ş.a.m.d.).
Programa actuală nu prevede un număr de ore pentru fiecare temă în
parte, aceasta fiind lăsată la aprecierea profesorului, în funcţie de
particularităţile claselor şi de condiţiile specifice de predare.
Preocupările privind elaborarea programelor şcolare pentru disciplinele
de informatică sunt îndreptate spre îmbunătăţirea programelor în sensul punerii
de acord a conţinuturilor cu cerinţa socială. Astfel se încearcă să se realizeze
o pregătire a elevilor în direcţia satisfacerii cerinţelor necesare integrării rapide
a absolvenţilor în activitatea economică. Dinamica conţinuturilor este o cerinţă
esenţială pentru programa şcolară a disciplinelor de informatică, necesară
menţinerii pasului cu progresele realizate în domeniu.
O tendinţă cu efecte nu tocmai benefice este aceea de realizare a unei
programe la un nivel foarte ridicat. Nu trebuie scăpat din vedere nici un moment
faptul că o programă şcolară, concepută şi aprobată, este obligatorie pentru toţi
elevii, iar aceştia nu sunt toţi foarte dotaţi şi motivaţi.
Elaborarea curriculum-ului este un proces continuu, care marchează
perioade de schimbări profunde, dar care ţinteşte îndelungi perioade de
stabilitate. Noul curriculum îşi propune să realizeze stabilitatea printr-un
echilibru între componenta naţională (care vizează trunchiul comun) şi
componenta locală (care vizează oferta curriculară a şcolii). Elaborarea
curriculum-ului local devine o componentă esenţială a activităţii didactice, o
rezultantă a eforturilor reunite a conducerii şcolii, cadrelor didactice, elevilor,
părinţilor, altor parteneri sociali.
Programa şcolară pentru disciplina Informatică. Profilul matematică-informatică

Având în vedere tematica acestei lucrări, consider că este suficient să


prezint conţinutul programei şcolare doar pentru clasele de liceu, profil
matematică-informatică unde se încadrează predarea structurilor de date.

Organizarea pe ani de studii a disciplinei Informatică

Trunchi comun (2 ore)


Curriculum la decizia
desfaşurate în laboratorul de
şcolii
An de studiu informatică
Aspecte Aspecte teoretice şi
Aspecte practice
teoretice practice
- Aprofundarea
temelor din trunchiul
comun
- Programare grafică
- Utilizare Internet
- Reţele de
calculatoare
- Sisteme de
Algoritmi şi - Programare
operare şi
elemente de avansată
Clasa a IX-a aplicaţii de
limbaj de - Limbaj de
programare.
programare programare
- Utilitare
- Limbaj de asamblare
- Tehnoredactare
- Foi de calcul
- HTML
- Editor grafic
- Sisteme de operare
- Aplicaţii mutimedia
- Aprofundarea
temelor din trunchiul
comun
- Programare
avansată
- Limbaj de
- Programare programare
modulară - Limbaj de asamblare
Metode şi - Recursivitate - Utilizare Internet
Clasa a X-a tehnici de - Metoda Divide - Reţele de
programare et impera calculatoare
- Metoda - Tehnoredactare
Backtracking - Foi de calcul
- HTML
- Editor grafic
- Sisteme de operare
- Aplicaţii mutimedia
- Programare pe
obiecte
- Aprofundarea
temelor din trunchiul
comun
- Programare
avansată
-Alocare
- Limbaj de
dinamică
Structuri de programare
Clasa a XI-a - Aplicaţii
date avansate - Limbaj de asamblare
elementare cu
- Tehnoredactare
grafuri şi arbori
- Foi de calcul
- HTML
- Editor grafic
- Sisteme de operare
- Aplicaţii mutimedia
- Teoria grafurilor
- Reţele de
calculatoare
- Programare pe
obiecte
- Programare pe
Internet
- Programare în
mediul vizual
- Aplicaşii de
proiectare
- Aprofundarea
temelor din trunchiul
comun
- Programare
avansată
- Limbaj de
programare
- Limbaj de asamblare
Baze de date - Tehnoredactare
(Modele, - Foi de calcul
Proiectarea şi
structuri, - HTML
Clasa a XII-a întreţinerea
moduri de - Editor grafic
bazelor de date
organizare a Sisteme de operare
datelor) - Aplicaţii mutimedia
- Teoria grafurilor
- Reţele de
calculatoare
- Programare pe
obiecte
- Programare pe
Internet
- Baze de date
- Criptografie
- Programare în
mediul vizual
- Analiză numerică
- Aplicaţii de
proiectare

Profilul matematică-informatică poate funcţiona în licee care dispun de o


dotare care poate asigura realizarea programei şcolare. Numărul de
laboratoare trebuie să asigure acoperirea orelor de laborator solicitate atât de
trunchiul comun cât şi de curriculum la decizia şcolii, cu cel mult doi elevi la
calculator.
Între componentele procesului de învăţământ, conţinutul învăţământului
ocupă locul central deoarece formarea tânărului se bazează pe informare, pe
calitatea informaţiilor şi pe modalităţile participative de achiziţionare a acestora.
Proiectarea întregului demers didactic se realizează în funcţie de conţinuturile
învăţării.
Conceptul de conţinut al procesului de învăţământ defineşte: „ansamblul
valorilor specifice şi dominante într-o societate, selectate din ceea ce a creat
mai valoros umanitatea, din cultura epocii structurate în cunoştinţe ce conduc
la formarea unor priceperi, deprinderi, capacităţi, modele de acţiune şi trăiri
afective în conformitate cu cerinţele actuale şi de perspectivă ale societăţii".
Proiectarea conţinutului se realizează pornind de la câteva întrebări: „Ce
se va preda? Câte valori urmează să fie transmise şi asimilate? Cum sunt
structurate aceste valori? Ce fel de personalităţi vrem să formăm ?" şi se
materializează în instrumentele cu care lucrează învăţământul: plan cadru,
programa şcolară, manual. Odată cu structurarea Planului cadru se stabilesc
obiectele de învăţământ de-a lungul anilor de studiu, „într-o succesiune, ordine
şi gradare, avându-se în vedere complexitatea, dinamică şi specificitatea
conţinutului, sarcinile de învăţare pe care le solicită raportate la posibilităţile şi
nivelul dezvoltării ontogenetice a elevilor din diferite grade de şcolarizare"
Conţinutul învătării pentru curriculum obligatoriu este conceput astfel
încât să asigure un bagaj minim de cunoştinţe şi deprinderi din domeniul
informaticii, în timp ce curriculum la decizia şcolii poate oferi module derivate
din materia studiată, teme care nu sunt incluse în programa de trunchi comun
sau teme integratoare pentru arii curriculare cu aplicabilitate în informatică.
Programa pentru disciplina Informatică, profilul matematică-informatică
este orientată pe obiective, profesorul având posibilitatea de a alege activitaţile
specifice atingerii acestora. De asemenea, există clase de profil matematică-
informatică, intensiv informatică unde numărul de ore din trunchiul comun este
mai mare decât la celelalte clase de matematică-informatică şi elevii au
posibilitatea de a aprofunda materia predată de profesor (clasa a IX-a - 5 ore,
unde 3 ore sunt de laborator; clasa a X-a - 6 ore, unde 4 ore sunt de laborator;
clasa a XI-a – 7 ore, unde 4 ore sunt de laborator; clasa a XII-a – 7 ore, unde 4
ore sunt de laborator). De asemenea, elevii de la profilul matematică-
informatică, intensiv informatică au avantajul că în laboratorul de informatică au
clasa împărţită în două grupe de câte 15 elevi, ceea ce sporeşte eficienţa
procesului de predare-învăţare.
Transformările societăţii româneşti din ultimii ani, dezvoltarea şi
răspândirea informaticii, pătrunderea hardware-ului şi software-ului modern în
ţara noastră, impun o pregătire diversificată a tinerilor în acest domeniu.
Disciplina Informatică, din cadrul profilului Matematică-Informatică trebuie să
asigure dobândirea unor cunoştinţe de informatică la nivel de cultură generală,
necesare continuării studiului şi a unor cunoştinţe cu caracter aplicativ utile în
societatea în care vor trăi.
Pornind de la faptul că nu există domeniu de activitate unde să nu se
prelucreze şi să nu se transmită informaţii atât în cadrul domeniului respectiv
cât şi spre exteriorul lui, informaţia este foarte preţioasă, ea trebuie stocată,
prelucrată şi transmisă în condiţii care să asigure corectitudine şi exactitate,
adică la un nivel profesional.
Informatica a pătruns astăzi în cele mai variate domenii. Indiferent de
profesia pe care o va alege un tânăr, cu siguranţă va avea nevoie de
cunoaşterea modului de utilizare a unui instrumentar informatic. Volumul
cunoştinţelor şi deprinderilor necesare va depinde desigur de domeniu, de
exigenţele şi cerinţele concrete. Este însă o nevoie stringeafâ de iniţierea
tinerilor din toate şcolile în utilizarea calculatoarelor Ia un nivel profesional, pe
care îl numim azi - doar - nivel de cultură generală.
Dezvoltarea gândirii algoritmice este un obiectiv la realizarea căruia
Informatica contribuie esenţial şi eficient. Asemenea Matematicii, Informatica
dezvoltă gândirea care în şcoală, dar şi în viaţa de zi cu zi, are un rol esenţial
în procesul de învăţare, în formarea caracterului şi a personalităţii. Aceasta nu
se leagă doar de cunoştinţele de programare, ci şi de cunoştinţele referitoare
la gestionarea bazelor de date, la utilizarea editoarelor de texte, etc.
Informatica, prin specificul ei, este esenţial legată de lucrul individual cu un
calculator şi contribuie la dezvoltarea deprinderii de a lucra individual. Pe de
altă parte, prin intermediul reţelelor de calculatoare este posibil un schimb de
informaîii mult mai eficient decât prin orice altă metodă clasică. [4, 5, 6, 7, 8, 9]

Obiectivele cadru
- Dezvoltarea deprinderilor de utilizare a unui sistem de calcul şi a unor
produse soft de largă răspândire
- Dezvoltarea gândirii algoritmice, a spiritului inventiv şi creator
- Dezvoltarea deprinderilor necesare activităţilor individuale şi în echipă
- Conştietizarea conexiunilor dintre informatică şi societate.

Predarea structurilor de date, în liceu, începe în clasa a IX-a, unde elevilor


li se predau elemnente de bază în programare, începând cu noţiunile de date,
tipuri de date, algoritmi etc. Pe parcursul acestui an şcolar, elevii fac cunoştinţă
cu stucturile de date implementate static şi are loc o aprofundare a acestor
cunoştinţe, paralel cu dezvoltarea gândirii algoritmice şi învăţarea unui limbaj
de programare.
Programa şcolară – clasa a IX-a
Conţinuturile învăţării
1. Rolul şi funcţiile sistemelor de calcul
1.1 Structura unui sistem de calcul
1.2 Funcţiile unui sistem de calcul
1.3 Măsuri de protecţie a muncii în timpul lucrului cu calculatorul
2. Principalele funcţii ale unui sistem de operare (de exemplu Ms-Dos,
Windows, Linux)
2.1 Concepte de bază; caracteristici ale SO
2.2 Elemente de interfaţă (elemente specifice de comunicare dintre
utilizator şi sistemul de operare)
2.3 Programe de asistenţă (de exemplu Norton Commander, File
Manager, Windows Explorer)
2.4 Editorul de texte (Edit, NotePad, Wordpad, Microsoft Word)
2.5 Editorul de imagini (Art Studio, Paint) – formate de imagini
2.6 Accesorii de sistem (agendă calculator, elemente multimedia)
2.7 Configurarea sistemului (Control Panel, Config-sys, Setup)
2.8 Utilitare sistem (scandisk, arhivatoare, programe antivirus)
3. Algoritmi
3.1 Enunţul unei probleme, date de intrare şi de ieşire, etapele rezolvării
unei probleme
3.2 Noţiunea de algoritm, caracteristici
3.3 Obiectele cu care lucrează algoritmii (date, variabile, expresii,
operaţii)
4. Principiile programării structurate
4.1 Structuri de bază; descrierea acestora cu ajutorul schemelor logice
şi în pseudocod; structurile liniare alternativă şi repetitivă
4.2 Aplicaţii
4.2.1 Probleme care prelucrează date numerice
4.2.2 Probleme care prelucrează date nenumerice
5. Elemente de bază ale limbajelor de programare
5.1 Noţiuni introductive
5.1.1 Structura programelor
5.1.2 Descrierea sintaxei cu ajutorul diagramelor de sintaxă
5.2 Vocabularul limbajului
5.2.1 Setul de caractere
5.2.2 Identificatori
5.2.3 Separatori şi comentarii
5.3 Tipuri simple de date (standard)
5.4 Constante
5.5 Variabile
5.6 Expresii
5.7 Citirea/scrierea datelor
6. Structuri de control
6.1 Structura liniară; instrucţiunile de atribuire şi compusă;
6.2 Structura alternativă; instrucţiuni de decizie şi selecţie
6.3 Structuri repetitive; instrucţiuni repetitive
7. Mediul limbajului de programare studiat
7.1 Prezentare generală
7.2 Editarea programelor sursă
7.3 Compilarea, rularea, depanarea
8. Tipuri structurate de date
8.1 Tablouri
8.2 Şiruri de caractere
8.3 Tipul înregistrare
8.4 Alte tipuri specifice limbajului
9. Fişiere
9.1 Tipul fişier (definire, operaţii)
9.2 Fişiere text
10. Aplicaţii practice
10.1 Etape în realizarea unei aplicaţii
10.2 Cerinţe în realizarea programelor
10.2.1 Interfaţă prietenoasă
10.2.2 Protecţie la date incorecte
10.2.3 Criterii de optimalitate
10.3 Exemple de aplicaţii
- Determinarea de minim/maxim
- Probleme de divizibilitate
- Sortare
- Căutare
- Probleme de căutare a datelor din fişiere text
- Prelucrari de şiruri de caractere

Predarea structurilor de date alocate dinamic se va face în cadrul


disciplinei informatică - clasa a X-a.

Programa şcolara – clasa a X-a


Conţinuturile învăţării

1. Structuri dinamice de date


1.1 Structuri statice de date (recapitulare)
1.2 Alocarea dinamică
1.2.1 Tipul referinţă (pointer)
1.2.2 Variabile dinamice
1.2.3 Crearea, accesarea şi eliberarea zonei de memorie adresate
dinamic
1.3 Structuri dinamice de date
1.3.1 Liste liniare: liste simplu înlănţuite, liste dublu înlănţuite, liste
circulare
1.3.2 Structuri de tip stivă şi coadă alocate dinamic (operaţii
specifice)
1.3.3 Structuri arborescente (operaţii specifice)
2. Algoritmi pe grafuri
2.1 Grafuri neorientate
2.1.1 Noţiuni elementare
2.1.2 Moduri de reprezentare
2.1.3 Algoritmi de parcurgere
2.1.4 Conexitate
2.2 Arbori
2.2.1 Noţiuni elementare
2.2.2 Moduri de reprezentare
2.2.3 Arborele parţial de cost minim (algoritmul lui Kruskal)
2.2.4 Structuri arborescente
- Arbori binari
- Arbori de căutare
- Arbori oarecare
2.3 Grafuri orientate
2.3.1 Definire şi reprezentare
2.3.2 Drumuri
2.3.3 Tare conexitate
2.3.4 Algoritmi de drum minim/maxim

Am prezentat programele analitice la clasele a IX-a şi a X-a, matematică-


informatică, pentru a se observa rolul şi locul structurilor de date în procesul de
predare şi învăţare în cadrul disciplinei informatică, precum şi importanţa
acestora în dezvoltarea gândirii algoritmice şi activitatea de programare.
Evident, nu se poate face o separare a structurilor de date de algoritmi sau
invers; aceste noţiuni sunt strâns legate unele de altele, neputând concepe sau
folosi algoritmi fără a folosi structuri de date sau invers. [4, 5, 6, 7, 8, 9]

3.4 Predarea structurilor de date în liceu

Aşa cum am exemplificat în paragraful precedent, predarea structurilor de


date în liceu reprezintă un factor important în cadrul disciplinei informatică,
cuprinde multe capitole şi subcapitole din conţinuturile programei de liceu,
interconectându-se cu dezvoltarea gândirii algoritmice, a spiritului inventiv şi
creator. Limbajele de programare evoluate utilizează din plin cele mai variate
tipuri de date. Însă noţiunea de tip de date este strâns legată de un anumit
limbaj de programare. În situaţia în care se renunţă la această legătură, se
ajunge la noţiunea de structură de date. Modul de proiectare a structurilor de
date şi modul de elaborare a algoritmilor subliniază faptul că a sti să programezi
nu înseamnă numai a cunoaşte limbaje de programare şi sisteme de operare.
Pentru elaborarea unui program performant trebuie avute în vedere metodele
de programare şi tehnicile de lucru adecvate problemei abordate.
Elevii fac cunoştinţă cu structurile de date începând cu clasa a IX-a, în
primul rând la nivel de noţiuni intoductive (date, variabile – obiecte cu care
lucrează algoritmii) strâns legate de activitatea de predare şi învăţare a noţiunii
de algoritm, pentru că, după aceea, o dată cu predarea unui limbaj de
programare elevii să-şi poată desăvârşi şi aprofunda cunoştintele legate de
structurile de date (tipuri de date, tipuri standard, tipuri definite de utilizator,
tipuri de date simple şi tipuri de date compuse: tablouri, înregistrări etc.). Este
foarte important cum se face comunicarea informaţiilor de la profesor către elev
şi cum se desfăşoara activitatea de predare – învăţare, deoarece, pe lângă
faptul acest an de studiu (clasa a IX-a) constituie primul impact pe care îl au
elevii cu disciplina informatică, de înţelegerea şi însuşirea corectă a structurilor
de date depinde, în mare parte, înţelegerea de către elev a noţiunilor din cadrul
disciplinei informatică în clasele următoare şi formarea unei gândiri algoritmice
corecte.

Clasa a IX-a
La nivel de clasa a IX-a, profesorul va prezenta doar structurile de date
implementate static, insistând în mod deosebit pe înţelegerea şi însuşirea
acestora, în paralel cu dezvoltarea gândirii algoritmice a elevilor şi dezvoltarea
deprinderilor necesare activităţilor individuale şi în echipă, pentru a constitui o
bază pentru desfăşurarea eficienţă a actitivităţii de predare-învăţare pe
parcursul clasei a X-a, unde se insistă pe programarea modulară şi pe tehnicile
de programare. Asupra structurilor de date, dar de această dată implementate
dinamic, se va reveni în clasa a XI-a, unde o mare parte a orelor de informatică
sunt rezervate capitolului Alocarea dinamică a memoriei.
Activitatea de predare-învăţare a structurilor de date alocate static, pe
parcusul unui an şcolar (clasa a IX-a) parcurge, în conformitate cu programa
şcolara, următorii paşi:
- Prezentare noţiunilor de date, variabile, constante (ca fiind obiecte cu care
lucrează algoritmii)
Obiective:
- Însuşirea de către elevilor cu noţiunile de date şi tip de date;
- Familiarizarea cu noţiunile: variabile şi constante. Diferenţierea
acestora;
- Elevii să ştie să prelucreze date la nivel de componente (simple) ;
- Elevii să recunoască tipurile de date pe exemple concrete;
Exemple de activităţi de predare-învăţare:
- definirea noţiunii de date în general;
- definirea noţiunilor de tipuri de date (legate de un limbaj de
programare; caracteristici ale tipurilor de date), variabile, constante; noţiunea
de structură de date (prin renunţarea la legătura cu un limbaj de programare);
- clasificarea tipurilor de date în funcţie de diverse criterii:
- în funcţie de modul de definire: standard şi definite de utilizator
- în funcţie de modul de memorare a datelor în calculator: simple
şi compuse
- în funcţie de modul de implementare: date implementate static
şi date implementate dinamic
- Reprezentarea datelor în memorie
Obiective:
- Elevii trebuie să cunoască organizarea fizică a memorie;i
- Elevii trebuie să-şi însuşească codificarea caracterelor şi
codificarea datelor numerice;
- Elevii trebuie să cunoască operaţii aritmetice de bază în sistemele
de numeraţie: binar, octal, hexazecimal;
Exemple de activiiăţi de predare-învăţare:
- prezentarea organizării logice a memoriei:
- noţiunile de bit, byte, kilobyte etc.
- noţiunile de adresă fizică, segment, adresă logică
- explicarea codificării caracterelor – cel mai utilizat cod alfanumeric,
codul ASCII;
- explicarea codificării datelor numerice:
- codificarea numerelor naturale
- codificarea numerelor întregi (codul complementar)
- codificarea numerelor raţionale (reprezentarea în virgulă
mobile simplă precizie şi reprezentarea în virgulă mobilă dublă precizie)
- Prezentarea tipurilor de date compuse
Obiective:
- Elevii trebuie să-şi însuşească tipurile de date compuse
- Elevii trebuie să prelucreze date de tipuri compuse: tablouri,
şiruri de caractere, fişiere text etc.
Exemple de activităţi de predare-învăţare:
- prezentarea principalelor tipuri de date compuse
- tipul tablou (tablouri unidimensionale, bidimensionale,
multidimensionale)
- tipul şir de caractere
- tipul articol (structură, înregistrare)
- tipul fişier text
- activităţi de dezvoltare a deprinderilor de abstractizare şi
organizare a informaţiilor în diverse structuri de date
- implementarea structurilor de tip tablou, articol etc.
- formularea unor probleme care să poată fi realizate în grupuri
de elevi pe baza unor discuţii preliminare şi analiza problemei
- exerciţii de prelucrare a datelor stocate pe suport extern, în
fişiere text
- exerciţii de manipulare a fişierelor text, cu folosirea şi altor
tipuri de date compuse
- evidenţierea analogiilor şi diferenţelor între citirea/scrierea
utilizând dispozitivele standard de intrare/iesire şi fişiere text

Clasa a XI-a
La disciplina informatică, pornind de la o bază solidă de cunoştinţe
dobândite pe parcursul a doi ani de studii (clasele a IX-a şi a X-a) cu privire la
structurile de date cât şi o gândire alogoritmică deja bine conturată precum şi
un spirit inventiv şi creator, programa permite prezentarea structurilor de date
implementate dinamic.
Se începe cu o absolut necesară recapitulare a structurilor de date, cu
această ocazie profesorul putând evalua cantitatea şi calitatea cunoştintelor
actuale ale elevilor clasei. Acesta este un foarte bun punct de plecare pentru a
eficientiza activitatea de predare-învăţare în continuare. Eventual, profesorul
poate puncta elementele mai importante acolo unde este cazul.
Se vor sublinia diferenţele dintre variabilele statice şi cele dinamice, cu
această ocazie profesorul putând prezenta elevilor un tip de date nou – tipul
referinţă şi noţiunea de pointer. Pentru o corecta însuşire a noilor informaţii este
bine ca profesorul să sublinieze caracteristicile datelor alocate static şi ale
datelor alocate dinamic precum şi avantajele alocării dinamice faţă de alocarea
statică.
După ce elevii şi-au însuşit cele predate de profesor, conform programei
şcolare, se vor prezenta aplicaţii ale alocării dinamice a memoriei: stiva şi coada
alocate dinamic, listele liniare (simplu şi dublu înlănţuite), structuri
arborescente. Deoarece, programa şcolară nu rezervă capitole speciale pentru
structurile de stivă, coadă şi listă liniară implementate static, devine absolut
necesar ca profesorul să introducă aceste noţiuni, în primul rând implementate
static (cu ajutorul tablourilor). Singura structură cunoscută elevilor este cea de
stivă, prezentată succint de către profesor cu ocazia predării metodei
backtracking, în cadrul predării tehnicilor de programare (clasa a X-a). Odată
întelese aceste noţiuni de către elevi, se pot preda cu succes şi implementate
dinamic, elevii putând sesiza cu uşurinţă avantajele alocării dinamice.
Scopul final este ca elevul să-şi însuşească cunoştintele de bază cu privire
la alocarea dinamică a memoriei, să înţeleagă importanţa folosirii acesteia şi
să stie să realizeze diverse aplicaţii relativ la structurile dinamice de date. În
acest sens, elevii trebuie să-şi însuşească operaţiile ce se pot face asupra
listelor (simplu sau dublu înlănţuite), stivei sau cozii, să înţeleagă utilitatea
alocării dinamice a memoriei în implementarea listelor. Odată înţelese şi
însuşite operaţiile cu liste, se vor introduce noţiunile referitoare la arbori. Este
important ca elevii să cunoască operaţiile elementare asupra arborilor binari (în
special arborii binari de căutare): creare, parcurgere, etc. De asemenea, elevii
trebuie să-şi însuşească minimul de cunoştinţe referitoare la arborii oarecare,
a căror importanţă nu trebuie neglijată, chiar dacă reprezintă un capitol mai
dificil.
Pornind de la atingerea acestor obiective, se pot realiza în cele din urmă
aplicaţii complexe care să valorifice capacitatea creatoare a elevului şi care în
acelasi timp să testeze calitatea şi cantitatea cunoştinţelor acumulate. Este
important ca elevii să nu înveţe pe dinafară operaţiile ce se pot face asupra
listelor şi arborilor, ci să deducă logic modul de realizare a acestora. În acest
scop este indicat (şi cred eu cel mai eficient) să folosim principiul vizualizării în
predarea alocării dinamice. Elevii vor fi sigur mai receptivi şi vor înţelege mai
bine ceea ce profesorul doreşte să le comunice.
Activitatea de predare-învăţare a structurilor de date alocate dinamic, pe
parcursul unui semestru dintr-un an şcolar (clasa a XI-a) parcurge, în
conformitate cu programa şcolară, următorii paşi:
- Structuri statice de date (recapitulare)
Obiective:
- Elevii să-şi reamintească cunoştinţele dobândite în clasele
precedente cu privire la structurile de date
- Elevii să-şi fixeze cunoştinţele legate de structuri de date, necesare
trecerii la predarea alocării dinamice a memoriei
Exemple de activităţi de predare-învăţare:
- Testarea de către profesor a cunoştinţelor elevilor
- Evidenţierea, prin exemple, a caracteristicilor datelor implementate
static
- Alocarea dinamică a memoriei
Obiective:
- Elevii să-şi însuşească noul tip de date – tipul referinţă
- Elevii să cunoască şi să înteleagă caracteristicile structurilor statice
şi dinamice
- Elevii să ştie să foloseascş operaţiile cu pointeri şi legatura dintre
pointeri şi tablouri
- Elevii trebuie să recunoască situatiile în care alocarea dinamică
este impusă de contextul de prelucrare specific unor probleme
- Elevii trebuie să cunoască modul de declarare şi apel al
subprogramelor
- Elevii să poată formula modul în care un subprogram comunică cu
programul apelant
Exemple de activităţi de predare-învăţare:
- Definirea şi discutarea conceptelor de baza ale modului de alocare
dinamică a datelor
- Clarificarea avantajelor şi dezavantajelor folosirii structurilor
dinamice de date
- Prezentarea operaţiilor cu pointeri
- Explicarea şi exemplificarea legăturii dintre pointeri şi tablouri
- Folosirea pointerilor ca parametri în funcţii
- Exersarea creării şi folosirii subprogramelor pentru rezolvarea unor
probleme cunoscute, rezolvate anterior fără utilizarea subprogramelor
- Evidenţierea instrumentelor existente pentru realizarea transferului
de date între diferite module de program (variabile globale şi parametri)
- Discutarea situaţiilor în care un subprogram necesită transfer de
date prin intermediul parametrilor (transmisi prin referinţă/valoare)
- Structuri dinamice de date
Obiective:
- Elevii să înteleagă şi să-şi însuşească noţiunile de stivă, coadă, listă
liniară, arbore, în primul rând implementate static, iar apoi dinamic
- Elevii să fie capabili să aleagă şi să folosească tipul de structură
alocată dinamic adecvată metodei de rezolvare a unei probleme
- Elevii să înţeleagă mecanismele de lucru cu structuri de tip coada
şi stivă
- Elevii să înteleagă mecanismele de lucru cu structuri de tip listă
liniară
- Elevii să înţeleagă mecanismele de lucru cu structuri de tip arbore
binar de căutare
- Formarea de priceperi şi deprinderi în utilizarea structurilor de date
alocate dinamic
- Elevii să fie capabili să finalizeze individual sau în echipa o aplicaţie
Exemple de activităţi de predare-învăţare:
- Explicarea şi discutarea noţiunilor de stivă, coadă, listă, arbore
- Identificarea diferitelor situaţii în care este necesară alegerea unui
anumit tip de structură
- Prezentarea şi discutarea operaţiilor specifice diferitelor tipuri de
structuri; realizarea acestora împreună cu elevii
- Realizarea a diverse aplicaţii ce pun în evidenţă necesitatea şi
avantajele implementării dinamice a diverselor tipuri de structuri

3.5 Sugesii în predarea alocării dinamice a memoriei. Metode


specifice de predare si evaluare

Predarea, învăţarea şi evaluarea sunt cele trei activităţi de bază ale


procesului de învăţământ, formând o unitate organică, care conduce la
realizarea obiectivelor educaţionale propuse. În acest context, predarea alocării
dinamice a memoriei în liceu, reprezintă o etapă de o importanţă deosebită în
activitatea de predare-învăţare şi, de asemenea, programa şcolară rezervă
acestui subcapitol un număr mare de ore şi un conţinut destul de stufos, aşa
acum am prezentat anterior. Pentru o bună desfăşurare a activităţii de predare
şi învăţare a alocării dinamice a memoriei contribuie mai mulţi factori de
profesorul este obligat să ţină cont:

- proiectarea şi planificarea activităţii didactice


- principiile şi strategiile didactice
- metodele specifice de predare şi învăţare
- mijloacele de învăţământ
- modurile de evaluare şi implicaţiile lor
Astfel, pentru ca predarea alocării dinamice a memoriei să se desfăşoare
în bune condiţii şi cu rezultate cât mai bune profesorul trebuie să aibă ca punct
de plecare o planificare a materiei şi a întregii activităţi didactice cât mai
judicioasă. Bineînţeles, experienţa didactică a profesorului este un factor
important în activitatea de proiectare şi planificare.
Instrumentul fundamental în proiectare îl reprezintă programa şcolară,
care este un document normativ ce stabileşte obiectele/competenţele, adică
ţintele ce urmează a fi atinse prin actul didactic. În proiectarea activităţii
didactice se ţine seama de obiective/competenţe obligatorii dar ele nu sunt o
îngrădire pentru profesor. Astfel acelaşi obiectiv/competenţă se realizează prin
mai multe conţinuturi sau mai multe obiective/competenţe pot fi realizate cu
acelaşi conţinut şi resurse.
Proiectarea activităţii didactice presupune:
- Lectura programei;
- Planificarea calendaristică;
- Proiectarea unităţii de învăţare.
În contextul noului curriculum, planificarea calendaristică se transformă
dintr-un document administrativ formal care repetă modul de gestionare a
timpului propus de programa analitică într-un instrument de interpretare
personală a programei, care asigură un demers didactic concordant cu situaţia
concretă din clasă.
Astfel profesorul trebuie să ţină cont de nivelul de cunoştinţe ale elevilor
clasei, de potenţialul acestora şi de disponibilitatea lor inventivă şi creativă.
Planificarea activităţii didactice presupune aşadar o lectură atentă şi
personală a programei şcolare în scopul de a analiza obiectivele / competenţele
şi a inventaria tipurile de activităţi şi resursele necesare.
În elaborarea planificărilor este necesară următoarea etapizare:
1. Citirea atentă a programei;
2. Stabilirea succesiunii de parcurgere a conţinuturilor;
3. Corelarea fiecărui conţinut în parte cu obiectivele de referinţă vizate;
4. Verificarea concordanţei dintre traseul educaţional propus de către
profesor şi oferta de resurse didactice de care dispune (manuale, ghiduri,
caiete, etc.);
5. Alocarea timpului considerat necesar pentru fiecare conţinut, în
concordanţă cu obiectivele de referinţă vizate.
Întregul cuprins al planificării are valoare orientativă, eventualele
modificări determinate de aplicarea efectivă la clasă putând fi consemnate în
rubrica „Observaţii„.
Planificările pot fi întocmite pornind de la următoarea rubricaţie:

Nr. Conţinutul Obiective de Număr de


Săptămână Observaţii
Crt. tematic referinţă vizate ore alocate

În procesul proiectarii didactice se pot formula anumite întrebări:

“- Ce voi face ? ”; “ - Cum voi face ? ” ; “- Cum voi şti dacă s-a realizat ceea ce
trebuia? ”.

Răspunsurile la aceste întrebări sunt oferite de următoarele etape:

- precizarea obiectivelor urmărite în cadrul disciplinei de studiu;


- analiza resurselor educaţionale;
- strategia educaţională;
- metodologia de evaluare şi autoreglare.
Parcurgerea în detaliu a fiecărei etape dintre cele enumerate anterior
concretizează operaţiile proiectării didactice.

Dintre principiile generale ale procesului de învăţământ voi exemplifica


mai jos acele principii didactice care se regăsesc în învăţământul informatic şi
care se aplică şi subcapitolului “Alocarea dinamică a memoriei”:

a) principiul participării active şi conştiente a elevilor la procesul de învăţământ;

Atitudinea conştientă a elevilor în procesul de învăţământ presupune


înţelegere.

La o lecţie de informatică, de exemplu, pentru unitatea de învăţare “Stiva”,


un obiectiv propus este “formarea conştientă de priceperi şi deprinderi în
utilizarea structurii de stivă ”. La operaţionalizarea obiectivului respectiv apar
ca sarcini:

- să definească structura de stivă;


- să precizeze operaţiile de bază ce se pot face cu stiva;
- să ştie să lucreze cu structura de stivă alocată static (folosirea
tablourilor);
- să ştie să lucreze cu structura de stivă alocată dinamic (folosirea
pointerilor);
Aceste sarcini arată respectarea principiului participării active şi profesorul
va trebui să specifice şi sarcinile care arata înţelegerea:

- să explice diferenţele dintre structura de stivă şi alte structuri de


date învăţate anterior;
- să recunoască şi să explice avantajele structurii de stivă alocată
dinamic;
- să fie capabil să recunoască problemele în care este necesară
structura de stivă;
- să rezolve probleme care utilizeaza strucura de stivă.

b) principiul sistematizarii şi continuităţii; are în vedere ordonarea informaţiilor,


eşalonarea acţiunilor, organizarea unitară a componentelor procesului de
învăţământ

Sistematizarea cunoştinţelor este realizată de către professor prin


planificarea anuală sau semestrială, respectând programa analitică.

La nivelul proiectarii lecţiei, principiul sistematizării este vizibil în relaţia


reactualizare-dobândire de cunoştinţe.

Sistematizarea cunoştinţelor este exemplificată la lecţia de reactualizare


pentru unitatea de învăţare “Alocarea dinamică a memoriei” (este vorba despre
recapitularea structurilor de date alocate static, învăţate anterior) în tabelul
următor:

Plan de idei Plan sistematizat

Definiţia noţiunilor de date, structura Noţiunea de structură de dată, în


de date general
Definiţia şi descrierea tipurilor de Legătura dintre tipurile de date şi
date limbajul de programare studiat

Clasificarea tipurilor de date Noţiunea de variabilă, definitie,


declarare
Descrierea variabilelor
Diferenţa dintre date simple şi cele
Descrierea constantelor
compuse
Definirea identificatorilor

Descrierea tipurilor simple de date

Descrierea tipurilor de date compuse

Referitor la subcapitolul structurilor de date predat în clasa a IX-a,


subliniez că are un rol important în înţelegerea de către elevi a noţiunilor de la
alocare dinamică. De exemplu, o reamintire a tipului de date articol este de bun
augur, aceasta putându-se face prin prezentatea câtorva exemple inspirate din
realitatea înconjurătoare (informaţiile dintr-o agendă telefonică, program de
evidenţă a elevilor participanţi la un examen – admitere la liceu sau bacalaureat,
ş.a.m.d.). O astfel de abordare succintă a structurilor de date – prin exemple –
reprezintă un avantaj practic imediat atât pentru profesor cât şi pentru elevi. Mă
refer la faptul la faptul că elevii vor aborda următoarele cunoştinţe care li se vor
propune, după o bază reală, privind utilitatea practică a alocării dinamice, iar
din punct de vedere al profesorului este evidentă uşurinţa în predare atunci
când elevii “văd” utilitatea listelor şi a alocarii dinamice a memoriei în general.
Eu consider că prezentarea de câte ori este posibil a unei probleme cu tentă
practică ce se poate rezolva cu ajutorul listelor, este bine venită deoarece nu
face decât să “întreţină” în mintea elevului ideea că listele nu sunt doar o
tehnică de programare care trebuie învăţată pentru că “aşa vrea profesorul”, ci
sunt o modalitate eficientă de soluţionare a unei mari varietăţi de probleme

c) principiul accesabilităţii cunoştinţelor şi deprinderilor

Principiul accesabilităţii cunoştinţelor asigură transmiterea cunoştinţelor la


nivelul de înţelegere al elevilor luând în considerare particularitătile de vârsta,
tratând cu atenţie sporită greutăţile şi dificultăţile care pot interveni în procesul
de asimilare a cunoştinţelor.

Depăşirea acestora se face gradat prin efortul personal al elevilor sub


îndrumarea profesorului.

Spre exemplu, în predarea structurilor de date alocate dinamic (stiva,


coada, lista), profesorul nu va preda în mod direct structurile respective
implementate dinamic. În primul rând le va preda ca structuri statice, ceea ce
le va face mult mai accesibile elevilor, implementarea statică a acestora fiind
iniţial foarte comodă pentru elevi deoarece se folosesc elemente de limbaj şi
programare deja bine cunoscute. Numai după ce elevii au înţeles şi şi-au însuşit
noţiunile respective, se poate trece cu succes la implementarea lor dinamică.

d) principiul corelaţiei între senzorial şi raţional în procesul de învăţământ


(principiul intuiţiei)

Eficienţa procesului de predare-învăţare este determinată de atitudinea


conştientă şi activă faţă de acest proces a celor care învăţă.

Participarea conştientă, presupune întelegerea clară a materialului


didactic, iar participarea activă presupune însuşirea materialului prin angajarea
gândirii şi prin activitate independenţa de studiu.

De exemplu, prezentarea sub o formă grafică a listelor simplu sau dublu


înlănţuite, a stivelor sau a cozilor, făcută în paralel cu prezentarea operaţiilor
ce se efectuează, este eficientă din punct de vedere al înţelegerii fenomenului
respectiv de către elevi. Aceasta, deoarece cantitatea de informaţii ce se pot
retine mai uşor de către elevi este foarte mare atunci când acestea se prezintă
sub formă vizuală. Pe lângă desenele obligatorii ce se efectuează la tablă, se
pot folosi, având un mare impact asupra elevilor, planşe care să conţină
reprezentarea operaţiilor referitoare la structurile dinamice. Cred că acest lucru
are un impact puternic asupra procesului de predare-învaţare, având implicaţii
atât asupra modului efectiv de predare, de insusire a noilor cunoştinţe de catre
elevi dar şi a modalităţilor de evaluare. Pe baza reprezentărilor respective,
elevii se pot implica direct în deducerea şi realizarea paşilor necesari diferitelor
operaţii. Acest ultim aspect merită subliniat deoarece se încadrează foarte bine
în noile tendinţe de evaluare propuse în învăţământul nostru, şi anume
implicarea elevilor pornind de la activităţi pur teoretice în activităţi practice.
Astfel, după parcurgerea în totalitate a capitolului “ Alocarea dinamică a
memoriei ”, în perioada de evaluare, elevilor li se poate propune să execute în
grupuri de câte doi-trei a unor astfel de planşe care să prezinte diferite operaţii
ce se efectuează asupra listelor, cazurile particulare de liste: stiva, coada, lista
circulară, bineînţeles sub îndrumarea profesorului. Aceste planşe vor putea
constitui mai târziu un material didactic folositor.

e) principiul paşilor mici

Principiul presupune împărţirea materiei de studiu în secvenţe


informaţionale mici pentru a uşura asimilarea şi înţelegerea noilor cunoştinţe.

De exemplu, în studiul listelor înlănţuite, acestea se împart în două


categorii:

- liste simplu înlănţuite

- liste dublu înlănţuite

Fiecare din cele două tipuri de liste se predau separat, cu asemănările şi


deosebirile respective. Asupra lor se produc aceleasi operaţii, însă ţinând cont
de particularităţile fiecăreia.

f) principiul asigurării progresului gradat al performanţelor în pregătire şi al


înlăturării treptate a “punctului de sprijin”

Principiul permite introducerea gradată a noilor noţiuni şi creşterea


progresivă a complexităţii materiei de studiu.

De exemplu, structurile de date alocate dinamic, se predau folosind tipul


referinţă şi operaţiile corespunzătoare, iar listele dublu înlănţuite se predau în
analogie cu cele simplu înlănţuite.
g) principiul conexiunii inverse (feedback-ului)

Principiul conexiunii inverse este principiul care asigură reglarea


procesului de învăţământ şi realizează conexiunea inversă, modificând fluxul
de intrări (asimilări) cu o mărime corectoare care permite apropierea mărimilor
de ieşire (rezultatele procesului de instruire) de mărimea de intrare sau
depăşirea acesteia dacă este posibil.

Profesorul trebuie să verifice în permanenţă înţelegerea şi însuşirea


materiei de către elevi, folosind diverse metode de evaluare, adaptându-şi stilul
şi modul de predare particularităţilor clasei. În cele din urmă, dacă rezultatele
procesului de predare-învăţare sunt bune şi foarte bune, profesorul poate apela
şi la alte modalităţi de realizare a feedback-ului. Astfel, o sugestie care se poate
face, legată de capitolul “Alocare dinamică”, este realizarea de către elevi, în
special ai celor cu cunoştinţe solide de programare a unui soft educaţional care
prezintă listele. Acest aspect merită detaliat în primul rând datorită lipsei acute
de software specializat pentru educaţie (soft educaţional), iar în al doilea rând
este cea mai eficientă modalitate de evaluare a cunoştintelor dobândite de
catre elevi, în general referitor la programare şi nu numai în particular referitor
la alocarea dinamică a memoriei. O astfel de aplicatie trebuie coordonată de la
inceput până la sfârşit de către profesor care îi explică elevului cum anume
trebuie analizată şi concepută aplicaţia respectivă. Interfaţa grafică este
esenţială în softul educaţional pentru că are rolul de a evidenţia fenomenul
respectiv şi dacă este însoţită şi de imagini în mişcare, de a-l face chiar atractiv.
Acest aspect se poate generaliza vizavi de legătura dintre informatică şi
celelalte discipline (matematică, fizică, chimie etc.). Nu este cazul să insistăm
aici dar ideea merită reţinută datorită eficientei sale practice.

Metode specifice de predare

Diferitele domenii ale informaticii necesită abordarea unor metode


specifice de predare care se vor combina optim cu metodele generale de
predare-învăţare. Se recomandă reconsiderarea utilizării uneia sau alteia dintre
metode la fiecare proiectare a unei lecţii şi nu plafonarea în sensul menţinerii
aceloraşi metode pentru fiecare oră.

Binenînţeles, metodele didactice se vor combina şi se vor dezvolta pe


baza experienţei fiecărui profesor. Dar există câteva elemente care trebuie
neapărat luate în considerare în momentul în care se alege o metodă sau o
combinaţie a mai multora:

- obiective generale sau specifice;

- conţinutul ştiinţific al subdomeniului predat;

- categoria de vârstă;

- nivelul clasei;

- personalitatea clasei;

- personalitatea profesorului;

- convingerile profesorului.

Este recomandabil să nu se utilizeze permanent o aceeaşi metodă pentru


predarea unei anumite părţi din materie. S-ar plictisi profesorii, s-ar plictisi
elevii, iar rezultatul nu va fi cel scontat.

Metodele specifice informaticii se pot clasifica în funcţie de domeniul clar


unde se aplică:

1. Metode de predare a algoritmilor şi tehnicilor de programare

2. Metode de predare a unui limbaj de programare

3. Metode de predare a sistemelor utilitare.

Activitatea de predare a alocării dinamice a memoriei foloseste atât din


metodele de predare a algoritmilor cât şi din cele de predare a unui limbaj de
programare.
1. Metodele de predare a algoritmilor şi tehnicilor de programare

a) Predarea orientată pe algoritmi

Întregul proces de programare este privit ca fiind ceva indivizibil, dar


accentul se pune pe conceperea algoritmului; restul activităţii de programare
se realizează în planul doi, având rol de verificare. În această categorie intră
predarea structurilor de date alocate static, care precede implementarea lor
dinamică. Nu se pune accent pe limbaj, ci pe înţelegerea noţiunilor şi a
operaţiilor respective, pe algoritmii necesari realizării cerinţelor respective.

b) Predarea orientată pe tipuri de probleme

Se formează seturi de probleme având dificultate gradată, fiecare set fiind


specific unei anumite clase de probleme (stiva, coada, lista simplu înlănţuită,
lista dublu înlănţuită). Dezvoltarea algoritmilor este treptată, deducându-se unul
din celălalt. Această metodă ajută mult atunci când se introduc structuri de date
noi şi determină o îmbunătăţire a tehnicilor de programare.

c) Predarea orientată pe limbaj

Aceasta metodă porneşte de la posibilităţile limbajului de programare. Se


prezintă riguros, mergând până în toate detaliile, elementele limbajului, într-o
succesiune “oarecare” şi, în funcţie de instrumentarul învăţat, se prezintă şi
cunoştinţe de programare. Procesul are loc invers faţă de predarea orientată
pe algoritmi, deoarece problema de rezolvat este o anexă, rezolvarea ei
folosindu-se în scopul verificării cunoaşterii limbajului.

Această metodă este recomandată în cazul introducerii tipului de date


referinţă, a noţiunii de pointer şi, în mod special a operaţiilor cu pointeri. Pointeri
se regăsesc atât în limbajul Pascal cât şi în limbajul C++. Însă sunt diferenţe
mari de la un limbaj la altul, iar limbajul C++ permite operaţii mult mai complexe
şi multe alte facilităţi, de exemplu legătura dintre pointeri şi tablouri; de
asemenea, transmiterea parametrilor prin referinţă se face tot cu ajutorul
pointerilor. Deci în predarea noţiunii de pointer este necesar să se facă folosind
predarea orientată pe limbaj.

d) Predarea orientată pe structuri şi instrucţiuni

Metoda seamănă cu cea precedentă, dar nu îşi fixează atenţia pe un


singur limbaj, ci pe concepte generale, valabile pe o clasă de limbaje. Este
folosită la predarea structurilor abstracte de date, independent de
implementare. Latura bună a acestei metode este că pune accent pe
prezentarea şi învăţarea unor concepte generale.

2. Metodele de predare a algoritmilor şi tehnicilor de programare

a) Predarea orientată pe utilizare

Dacă se consideră că importanţa majoră o deţine conceptul de bază pe


care a fost clădit produsul prezentat, atunci se va preda după acel concept,
apoi se va dezvolta prezentarea pe baza conceptelor derivate. Această metodă
seamănă cu cea orientată pe probleme, dar ţine cont de punctele de vedere
generale. Elementele de limbaj sau de mediu se vor introduce pe parcurs, în
funcţie de cerinţele dirijate de conceptul discutat. De exemplu, în cazul alocării
dinamice, se prezintă situaţiile în care se recomandă folosirea acestui
mecanism, apoi se învaţă cunoştinţele de bază (heap, pointer, variabilă
dinamică), urmează structuri de date alocate dinamic, operaţii cu acestea etc.,
iar în final, rezolvarea de probleme şi realizarea de proiecte.

b) Predarea orientată pe probleme

Problemele sunt gradate şi cu rolul de a fixa cunoştinţele specifice


limbajului de programare şi cu mai mic accent pe algoritmi. Tehnicile de
rezolvare a problemelor reprezintă instrumente de dobândire şi testare a
posibilităţilor limbajului.
Determinarea şi alegerea metodelor de învăţământ

Actiunea didactică începe cu sfârşitul ei, în sensul că înainte de a trece la


efectuarea propriu-zisă a acesteia, profesorul îşi proiectează în plan mintal
ceea ce urmează să fie rezultatele (performanţele) finale la care intenţionează
să ajungă cei pe care-i instruieşte. Ele analizează cu grijă şi gândeşte la ceea
ce are de înfăptuit, anticipează natura şi nivelul modificărilor ce trebuie produse
în comportamentul elevilor săi, pe plan cognitiv (a şti), afectiv (a simţi) şi
psihomotor (a face). Precizarea obiectivelor este o condiţie “sine qua non”
primordială unei instruiri eficiente.

Predarea bazată pe realizarea unor proiecte

În esenţă, practicarea acestei metode înseamnă dezvoltarea unor


procedee euristice în scopul rezolvării unor probleme practice, tehnice, reale,
din viaţa de zi cu zi.

Analizând mai de aproape câştigul din punct de vedere instructiv-educativ,


obţinut în urma aplicării acestei metode, vom constata că elevii devin mai
receptivi la problemele mediului în care trăiesc. Interdisciplinaritatea
însemnând şi integrare, este evidentă: problema, proiectul se rezolva folosind
cunoştinţele dobândite la mai multe discipline.

Dacă, în plus, se pune accent pe autonomia elevilor (pot să aleagă


subiectul proiectului) şi în centrul activităţilor se pun necesităţile elevilor, sfera
lor de interes, aceştia vor participa la procesul de instruire fără să conştietizeze
că de fapt, sunt “instruiţi”. Nu se va neglija nici evaluarea critică, împreună cu
elevii, a realizărilor conţinute în proiect.

Proiectele pot fi mari (lucrul pe grupe de elevi- participare la simpozioane,


sesiuni de comunicări), medii (realizate de elevi pe parcusul unui semestru sau
de absolvenţi pentru a obţine atestatul profesional) şi mici (teme de casă mai
complexe pentru care se va stabili un termen mai depărtat).

La baza acestei metode de predare/învăţare stau câteva concepte


specifice metodei. Învăţarea trebuie să fie un proces activ, iar această activitate
trebuie să se deruleze în context social (în grup, în colaborare). Evident, elevul
trebuie să participe “trup şi suflet” la această activitate.

Învăţarea prin descoperire

În stilul de predare clasic profesorul predă materia, explicând, prezentând


o metodă, un concept etc., iar elevul se străduieşte să reproducă, să copieze
cele prezentate. Conform acestei concepţii profesor bun este cel care explică
bine, prezintă clar rezolvările, iar elev bun este cel care înţelege repede,
asimilează şi aplică ceea ce i s-a predat, reţine în mod sigur şi după câteva
exersări poate să reproducă ceea ce a învăţat.

Învăţarea prin descoperire dirijată reprezintă o treaptă superioară în


procesul acumulării de cunoştinţe. Descoperirea va fi posibilă doar atunci când
se bazează pe cunoştinţe aprofundate anterior. Învăţarea este întotdeauna un
proces continuu, elementele noi se integrează în sistemul de cunoştinţe
existent. Intuirea unei soluţii, ideea nouă apare cu mai mare probabilitate atunci
când cunoştinţele elevilor sunt mai flexibile şi mai bine organizate. Învăţarea
prin descoperire dirijată se poate realiza prin intermediul rezolvării de probleme
– proces specific cel mai frecvent practicat pe parcursul învăţării.

Fazele rezolvării unei probleme sunt:

a) Interpretarea enunţului, eventual reformularea lui fără a-i schimba


semantica, identificarea datelor de intrare şi de iesire;

b) Căutarea şi găsirea acelor elemente de cunoştinţe şi deprinderi


(definiţii, proprietăţi, modele, structuri de date, metode) necesare pentru
rezolvarea problemei. Totdeauna vor fi identificate componente cunoscute,
exersate deja şi elemente de cunoştinţe noi;

c) Proiectarea şi reprezentarea algoritmului;

d) Scrierea programului (implementarea algoritmului);

e) Verificarea soluţiei prin testarea ei cu date de intrare acoperitoare;

f) Integrarea componentelor de cunoştinţe noi în sistemul existent prin


reveniri şi atenţionări asupra elementelor specifice;
g) Fixarea cunoştinţelor noi prin reluarea punctelor esenţiale din rezolvare.

Toate etapele conţin elemente de recapitulare şi exersare!

Învăţarea prin descoperire dirijată este indicat să fie folosită în predarea


alocării dinamice a memoriei, astfel încât, pe baza prezentării noţiunilor de bază
necesare (tip referinţă, pointer, variabilă dinamică, alocarea şi dezalocarea
memoriei) şi pe baza definiţiilor corespunzătoare, elevii pot fi ghidaţi de către
profesor pentru a descoperi singuri algoritmii necesari realizării diferitelor
operaţii asociate structurilor de date predate.

Compararea metodei clasice de predare cu cea a învăţării prin descoperire


dirijată

Predare clasică Invatare prin descoperire dirijată

Profesorul Profesorul

- împarte materia, o predă, o - oferă situaţii care provoacă


comunică întrebări, interes, gândire

- ajută elevii în rezolvarea problemei - ajută elevii astfel încât ei să se


poată ajuta pe ei înşişi în rezolvarea
problemei

- se consideră pe el însuşi instructor, - simte o responsabilitate accentuată


lector, persoană care aduce la faţă de dezvoltarea multilaterală a
cunoştinţă elevilor

- se limitează la conţinuturi - caută legături şi corelaţii cu


determinate de logica disciplinei experienţele zilnice ale elevilor

- are disponibilităţi pentru exersarea - se străduieşte să integreze


deprinderilor şi pentru o învăţare elementele de cunoştinţe în
care poate fi controlată dezvoltarea deprinderilor intelectuale

- pune un accent deosebit pe - pune accent pe asimilarea


exersarea unor mecanisme schemelor complexe.
Având în vedere această paralelă, este clar de ce folosirea învăţării prin
descoperire dirijată este recomandată în activitatea de predare a alocării
dinamice a memoriei. Înafară de câteva noţiuni de bază şi definiţiile diverselor
sructuri de date, elevii nu au nimic de memorat. Profesorul oferă situaţii care
provoacă întrebări şi ajută elevii astfel încât ei să se poată ajuta pe ei înşişi în
rezolvarea unei anumite probleme. De exemplu, după introducerea noţiunii de
listă simplu înlănţuită alocată dinamic şi prezentarea operaţiilor de bază cu
aceasta, profesorul nu trebuie să explice imediat algoritmii necesari operaţiilor
respectve, ci pe cât este posibil este bine să dirijeze elevii pentru a descoperi
ei înşişi paşii necesari. În acest sens se poate folosi cu succes conceptul
“vizualizării”. Vizualizarea în sensul larg al cuvântului înseamnă identificarea
contextului, posibil de recunoscut de către elevi, iar în sens restrâns înseamnă
reprezentare, desenare de figuri, înseamnă modelare. Tratarea capitolului de
alocare dinamică necesită foarte multe desene care se vor succede în stilul în
care se produc desenele animate. Aceste desene pun foarte bine în evidenţă
atât legăturile dintre nodurile unei liste cât şi etapele necesare operaţiilor
corespunzătoare. Sunt multilple posibilităţi de reprezentare grafică: desenul pe
tablă (cel mai des folosit), planşe, folosirea retroproiectorului sau chiar a unor
soft-uri educaţionale realizate în acest sens (pot fi realizate de către grupe de
elevii îndrumaţi de profesori).

În predarea alocării dinamice o importanţă deosebită o deţine


concretizarea. Exemplele concrete vor aduce conceptual abstract, respective
problema în “lumea” elevului, îl vor ajuta să le înţeleagă mai repede şi cu un
efort intelectual mai mic. Astfel, profesorul caută legături şi corelaţii cu
experienţele zilnice ale elevilor. De exemplu, la predarea noţiunii de stivă
profesorul poate face analogie între structura de stivă şi farfuriile dintr-o
cofetărie dispuse una peste alta, putând lua la un moment dat doar farfuria pusă
deasupra. Structura de coadă poate fi asociată cu oameni asteptând în linie la
o casă de bilete sau maşini asteptând într-o intersecţie se întâlnesc deseori.
Asemenea linii de aşteptare se formează oricând şi oriunde numărul cererilor
pentru o resursă este mai mare decât capacitatea de servire a acelei resurse.
Modelul de intrare şi ieşire din aceste aşteptări ordonate este caracterizat prin
faptul că entităţile sunt servite în ordinea sosirii.
Metodele de comunicare (expozitive şi interogative)

Sunt încă folosite pe scară largă, deoarece se poate comunica un volum


mare de cunoştinţe într-un timp scurt, la care elevul ar ajunge cu greu prin
redescoperire. Eficienţa metodelor de comunicare creşte în urma îmbinării lor
cu metode participative. Astfel, metodele de comunicare orală (explicaţia,
prelegerea, descrierea) pot dobândi valenţe formative dacă respectă anumite
cerinţe:
- precizarea obiectivelor comunicării şi motivarea acesteia;
- selectarea informaţiilor esenţiale în funcţie de obiective şi conţinut;
- structurarea logică a conţinutului de idei şi sistematizarea acestuia ;
- claritatea expunerii şi expresivitatea limbajului;
- folosirea întrebărilor-problemă şi crearea de situaţii problematice;
- expunerea liberă şi degajată, expresivă şi concisă, sugerând ideile de
bază şi ajutându-i pe elevi să le formuleze, utilizând raţionamente inductive,
deductive şi analogice
- mărirea eficienţei comunicării prin îmbunătăţirea ei cu procedee logice
cum ar fi: substituirea, asertarea, diviziunea, clasificarea, identificarea ;
- observarea reacţiilor elevilor pentru a schimba, în funcţie de acestea,
anumiţi parametri ai comunicării, cum sunt: ritmul comunicării, intensitatea,
raporturile reflexive ale comunicării.

Metodele interogative
Pot avea puternice valenţe formative dacă sunt utilizate corect, la
momentul oportun şi presupun o bună pregătire anterioară din partea
profesorului.
Conversaţia este o metodă interogativă care îmbracă mai multe forme, în
funcţie de obiectivele şi conţinutul diferitelor activităţi didactice:
- conversaţia euristică, cu scopul de a redescoperi cunoştinţele;
- conversaţia ca mijloc de aprofundare a cunoştinţelor;
- conversaţia pentru fixarea şi sistematizarea cunoştinţelor;
- conversaţia de verificare a cunoştinţelor.
Conversaţia, problematizarea şi descoperirea constituie o strategie
euristică de o mare valoare formativă. Prin folosirea euristicii ca stil cognitiv
operaţional de munca intelectuală, elevii participă prin efort propriu de gândire
şi de acţiune la însuşirea creativă a noilor cunoştinţe, îsi dezvoltă capacitatea
de a prelua şi combina în forme noi cunoştinţele.
Procesul de predare-învăţare algoritmică trebuie îmbinat cu învăţarea
euristică, profesorul redescoperind împreună cu elevii algoritmii, iar după
fixarea lor în memorie, aceştia urmând să fie utilizaţi pentru rezolvarea de
probleme de acelaşi tip.

Metodele de acţiune practică (operaţională)


Aceste metode sunt dintre cele activ-formative şi includ: metoda
exerciţiului, metoda lucrărilor practice şi de laborator şi instruirea programată
asistată de calculator.
Metoda exerciţiului constă în repetarea conştientă a unei activităţi,
urmărind formarea deprinderilor, consolidarea cunoştinţelor şi dezvoltarea
capacităţilor intelectuale.
Există mai multe tirui de exerciţii:
- după subiectii care le execută: individuale, în echipă, frontale;
- după funcţia îndeplinită: introductive, de bază, operatorii;
- după modul de intervenţie al profesorului: dirijate, semidirijate, libere;
- după obiectivul didactic urmărit: de comunicare, de rezolvare a
problemelor, de formare a deprinderilor intelectuale, de creativitate, de
autocontrol, de dezvoltare psihomotorie
Metoda lucrărilor de laborator şi a lucrărilor practice asigură legătura
strânsă dintre teorie şi practică, dezvoltă spiritul de observare al elevilor, dorinţa
de cercetare. Unele lucrări practice au la bază exerciţiul şi se desfaşoară după
modelul acestora.

Modurile de evaluare şi implicaţiile lor

Procesul educaţional presupune în acelaşi timp parcurgerea nivelurilor


învăţării (acumulării, formării) respectiv cunoaşterea, înţelegerea, aplicarea,
analiza şi sinteza precum şi evaluarea, în consecinţă necesită acţiuni de reglare
şi autoreglare continuă.
Referitor la evaluarea educaţională ne propunem să răspundem la
întrebări de genul: „Ce este evaluarea?", „Ce evaluăm concret?", „Pe cine
evaluăm?", „Când evaluăm?", „Care sunt metodele şi mijloacele de evaluare
pe care le putem folosi?", „ Cum interpretăm rezultatele evaluării?", „Cum ne
îmbunătăţim activitatea viitoare pe baza rezultatelor evaluării? " etc.
Actul evaluării presupune două momente relativ distincte: măsurarea şi
aprecierea rezultatelor şcolare". Desfăşurându-se în cea mai mare parte la
nivel de nucleu (profesor - clasă – elev) actul didactic al evaluării vizează
procesul de învăţământ în ansamblul său.
Pe baza observării clasei, a analizei muncii elevilor, a părerii lor despre
disciplină, se poate stabili calitatea muncii depuse de profesori şi elevi, de
asemenea punctele tari şi punctele slabe ale elevilor. Diagnosticul va fi
influenţat de scopul observării şi de tehnica, metoda cu care este realizată.
Scopul este de a aduna cât mai multe date privind nivelul de cunoştinţe, dar şi
atitudinea elevilor faţă de disciplina, urmând că pe baza acestora să se modifice
metodele aplicate în predarea informaticii. În acest sens sunt recomandate
chestionarele, interviurile, testele scrise sau orale.
În scopul realizării obiectivelor conţinute în programa şcolară este absolut
necesar ca pe parcursul orelor (lecţiilor) de informatică să se creeze o
atmosferă care să stimuleze elevii în sensul unei participări active la procesul
de învăţare.
Factorii care influentează atmosfera lecţiilor:
- Poate realiza profesorul asemenea ore încât elevilor să le placă ora, să
le placă să înveţe la disciplina respectivă ?
- Rezolvările de probleme, răspunsurile, interpretările, explicaţiile elevilor
fac parte integrantă din ore ?
- Au elevii posibilitatea să experimenteze, să verifice ideile originale
proprii, fără ca pentru orice răspuns să primească nota?
- Cât de diversificat se realizează evaluările?
Atmosfera bună de la ore se caracterizează prin atitudini pozitive ale
elevilor. Pentru a măsura acestea, sunt recomandate chestionarele,
observarea elevilor sau interviurile.
Elevii, în general, consideră că este mai important ceea ce accentuează
mai des profesorul, ceea ce subliniază în diverse forme şi ceea ce verifică şi
evaluează acesta în mod accentuat. Ceea ce consideră profesorul că este mai
important (rezolvarea de probleme, analiza problemelor, comparaţiile,
evidenţierea corelaţiilor, realizarea programelor modularizate) va fi considerată
de elevi importanţa doar dacă profesorul le va acorda importanţa şi cu ocazia
verificărilor. Din acelaşi motiv trebuie verificate cu atenţie şi temele de casă,
altfel elevii le vor neglija, le vor trata cu superficialitate.

Modernizarea şi optimizarea evaluării şcolare trebuie să ţină cont de:


- extinderea acţiunii de evaluare, de la verificarea şi aprecierea rezultatelor -
obiectivul tradiţional - la evaluarea procesului, a strategiei care a condus la
anumite rezultate; evaluarea nu numai a elevilor, dar şi a conţinutului, a
metodelor, a obiectivelor, a situaţiei de învăţare, a evaluării;
- luarea în calcul şi a altor indicatori, alţii decât achiziţiile cognitive, precum
conduita, personalitatea elevilor, atitudinile, gradul de încorporare a unor valori
etc.;
- diversificarea tehnicilor de evaluare şi creşterea gradului de adecvare a
acestora la situaţii didactice concrete (extinderea folosirii textului docimologic,
a lucrărilor cu caracter de sinteză, punerea la punct a unor metode de evaluare
a achiziţiilor practice);
- deschiderea evaluării spre mai multe rezultate ale spaţiului şcolar
(competenţe relaţionale, comunicarea profesor-elev, disponibilităţi de integrare
în social);
- necesitatea întăririi şi sancţionării cât mai operative a rezultatelor evaluării;
scurtarea feed-back-ului, a drumului de la diagnosticare la ameliorare, inclusiv
prin integrarea eforturilor şi a exploatării dispoziţiilor psihice ale elevilor;
- centrarea evaluării asupra rezultatelor pozitive şi nesancţionarea în
permanenţă a celor negative;
- stabilirea unui raport optim între evaluarea prin note şi evaluarea prin
calificative;
- transformarea elevului într-un partener autentic al profesorului în evaluare,
prin autoevaluare, interevaluare şi evaluare controlată.

Funcţiile evaluării
Rolul evaluatorului în evaluarea curentă precum şi în testări şi examinări
se distinge clar de cel al simplului profesor, acesta trebuind să asigure
îndeplinirea întregului proiect educaţional. Pornind de la planificarea evaluării
în funcţie de resursele proprii, interne (motivaţii, interese, timp, disponibilităţi) şi
cele externe, evaluatorul parcurge etape care necesită pregătire intensă,
cunoaştere, ajungând până la faza de „iluminare" în crearea sarcinilor de lucru
şi la aplicarea conştientă şi responsabilă asupra educabilului, în plus el
interpretează rezultatele, le analizează, sintetizează, clasifică şi asigură în final,
ameliorările necesare.
Astfel el îndeplineşte motivat, conştient, riguros, activ şi interactiv, reglativ
funcţiile evaluării.
Pornind de la ideea că „scopul evaluării nu este de a parveni la anumite
date, ci de a perfecţiona procesul educativ.", se pot face diverse clasificări ale
funcţiilor evaluării.
Clasificarea funcţiilor evaluării care vizează procesul de învăţământ în
ansamblu:
a) funcţia educativă-motivaţională - urmăreşte stimularea obţinerii de
performanţe superioare în pregătirea elevilor, ca urmare a influenţelor
psihomotivaţionale şi sociale ale rezultatelor învăţării, necesitând cu
precădere conştientizarea rezultatelor evaluării, conduce la stimularea
cunoaşterii şi autocunoaşterii, a puterii de apreciere şi autoapreciere,
raportând la obiectivele stabilite şi la rezultatele obţinute;
b) funcţia selectivă - presupune ierarhizarea şi selectarea elevilor sub
raport valoric şi al performanţelor în cadrul grupului studios, se obţine în urma
testelor standardizate, sau nu, cu scop normativ;
c) funcţia diagnostică - evidenţiază valoarea, nivelul şi
performanţele pregătirii elevilor la un moment dat (a punctelor tari şi a celor
slabe în diferite zone de interes), se obţine prin teste diagnostice
(psihologice, docimologice, de cunoştinţe, etc);
d) funcţia prognostică - pe baza analizei rezultatelor în comparaţie cu
obiectivele, prevede probabilistic zonele, nivelul şi distribuţia
performanţelor ce trebuie obţinute în viitor de către educabili, se obţine prin
teste de aptitudini, capacităţi şi abilităţi specifice, corelate cu teste şi/sau
chestionare de opinie, de atitudine, etc.;
e) funcţia de certificare - conduce la recunoaşterea oficială a unui statut
dobândit de către educabili, eventual în urma unui examen, prin acordarea de
certificate, diplome, sau alte documente de acest tip;
f) funcţia cibernetică (sau de feed-back) - conduce la ideea de optimizare
a procesului de predare-învăţare prin aplicarea reglajelor şi autoreglajelor;
g) funcţia de consiliere - conduce la orientarea şcolară şi profesională a
elevilor în cadrul sesiunilor de consiliere ale elevilor sau ale familiei;
h) funcţia social-economică - în planul macro - socio - economic şi în plan
individual referitor la performanţele pregătirii fiecărui elev - se referă la eficienţa
învăţământului.

Vizând în principal obiectivele operaţionale care sunt formulate şi


raportate la actul evaluării se disting, pe scurt funcţiile:
a) constatativă (în urma adunării şi stocării datelor ce vor fi interpretate);
b) de diagnosticare (analiza datelor);
c) predictivă, de prognosticare (interpretarea datelor).
Referitor la o secvenţă de învăţare, asemănător celor de mai sus se pot
distinge funcţiile:
a) verificarea, sau identificarea achiziţiilor şcolare;
b) perfecţionarea şi regularizarea căilor de formare a indivizilor,
identificarea celor mai facile şi mai pertinente căi de instrucţie şi educaţie;
c) sancţionarea sau recunoaşterea socială a schimbărilor operate asupra
elevilor.
Raportând la nivelul unei clase se impun trei funcţii:
a) orientarea deciziilor de natură pedagogică în vederea asigurării unui
progres armonios şi continuu în dezvoltarea elevului, prin stabilirea celor mai
bune căi de încorporare a cunoştinţelor şi deprinderilor;
b) informarea elevilor şi părinţilor asupra stadiului formării şi a progreselor
actuale sau posibile;
c) stabilirea unei ierarhii implicite sau explicite, prin atribuire, în funcţie de
rezultat, a unui loc, sau rang valoric.
Ponderea uneia sau alteia dintre funcţii poate fi diferită de la un act
evaluativ la altul, dar conduc cu precădere la deducerea a două operaţii
complementare, măsurarea şi evaluarea ce au un efect deosebit de complex
de îndeplinire a obiectivelor evaluării.

Moduri de evaluare şi implicaţiile lor

La orele de informatică, metodele şi procedeele de evaluare sunt diverse


şi se aleg în funcţie de tipul lecţiei care se proiectează.
Metodele şi procedeele cele mai des folosite sunt:
- chestionare scrisă sau orală;
- exerciţii practice;
- rezolvare de probleme;
- concursuri de durată scurtă în cadrul orei;
- utilizarea poştei electronice;
- completarea de teste (de tip grilă şi altele)
Examenele pot fi evaluări autentice, reale, extrem de utile. Se bazează pe
programe de examen stabilite anterior. Produc o evaluare cu caracter normativ,
naţional (în cazul examenelor naţionale) şi garantează protejarea oportunităţilor
egale pentru toţi candidaţii, pe de o parte, precum şi asigurarea calităţii (prin
satisfacerea criteriilor de validitate şi fidelitate stabilite) pe de altă parte, având
o miză ridicată.
Principalele forme de evaluare întâlnite în practica didactică sunt:

a) Evaluarea iniţială care conduce la formarea unei imagini despre bagajul


de cunoştinţe cu care elevul porneşte la drum. Trebuie să ne asigurăm de ceea
ce cunoaşte elevul înainte de a-1 învăţa alte lucruri. Această formă de verificare
creează şi o imagine asupra posibilităţilor de progres ale elevului, asupra
capacităţii lui de învăţare, în funcţie de care se va stabili programul de instruire.
O astfel de evaluare se impune înainte de a începe predarea capitolului Alocare
dinamică a memoriei deoarece numai plecând de la noţiunile bine însuşite de
către elevi cu privire la structurile de date, se poate începe predarea noului
capitol. O astfel de evaluare se poate face prin chestionare orală completată cu
punctări ale profesorului asupra elementelor de bază. Întrebările se vor formula
într-o formă simplă, clară şi urmăresc reproducerea cunoştinţelor, interpretarea
şi prelucrarea lor.

b) Evaluarea formativă (continuă) este forma de evaluare pe care


profesorul o aplică pe întreaga durată a programului de instruire în cadrul
lecţiilor şi la încheierea unui capitol. Această formă de verificare oferă
permanent informaţii cu privire la eficienţa programului de instruire şi permite
profesorului să ia cele mai potrivite măsuri de prevenire a insuccesului şcolar,
ajutând totodată la ameliorarea metodelor de predare-învăţare. Verificarea
ritmică oferă, pe baza mecanismului de feed-back continuu, semnalele
necesare atât elevului cât şi profesorului, fiind un veritabil metronom al activităţii
didactice.
O astfel de evaluare este indicată pe tot parcursul predării capitolului
Alocare dinamică a memoriei, pentru a avea un permanent control asupra
cantităţii şi calităţii cunoştinţelor dobândite de către elevi, profesorul putând
astfel să-şi organizeze activitatea de predare în funcţie de rezultatele obtinute
în urma evaluării. O asfel de evaluare determină relaţii de cooperare profesor-
elev şi cultivă capacitatea de evaluare şi autoevaluare. Elevul poate constietiza
cât şi cum a asimilat cunoştinţele noi şi îşi poate îmbunătăţi activitatea şi stilul
de învăţare.
c) Evaluarea sumativă (cumulativă) este forma tradiţională de evaluare
realizată la sfârşitul unui capitol, semestru, an şcolar şi cuprinde întreaga
materie conform programei şcolare, pe intervalul de timp la care se aplică
verificarea. Rezultatele acestei forme de verificare nu reflectă întotdeauna
adevăratul nivel de performanţă al elevilor, dar prin faptul că determină o
recapitulare şi o abordare globală a materiei parcurse, are efecte pozitive în
direcţia dezvoltării capacităţii de cuprindere şi de sinteză a elevului.
O astfel de evaluare este necesară atât după ce s-a încheiat predarea
capitolului Alocare dinamică a memoriei, cât şi după fiecare subcapitol: Tipul
referinţă, Stiva şi Coada, Listele. Deoarece o testare la sfârşitul capitolului
Alocare dinamică a memoriei, necesită o parcurgere a unei cantităţi mari de
materie şi poate genera stress şi chiar comportamente inadecvate ale elevilor,
iar pe de altă parte are efecte reduse pentru ameliorarea procesului de predare-
învăţare, este necesară şi o evaluare pe subcapitole, astfel procesul de
evaluare având un grad mult mai de obiectivitate.

Superioară prin caracterul ei predictiv, evaluarea formativă trebuie totuşi


completată şi cu celelalte forme. Ultimele două strategii este avantajos să fie
aplicate prin îmbinare şi complementaritate.
Criteriile care au condus prin îmbinare la această clasificare sunt:
1. Cantitatea de informaţie (sau experienţă) ce poate fi asimilată
(dobândită) de către elevi
2. Perspectiva temporală în funcţie de aceste criterii se deduc implicit
clasificările:
Tipuri de
Criteriul Caracteristici Metode Tehnici
evaluare
- se verifică elemente
1. Cantitatea de - ascultare curentă -
cognitive sau
informaţii ce Parţială extemporale - probe
comportamentale
poate fi practice
secvenţiale
asimilată de
- se verifică o cantitate
către elevi Globală - examene - concursuri
mare de cunoştinţe şi
deprinderi obţinute prin
cumulare

- se face la începutul - teste predictive -


Iniţială
unei etape de instruire concursuri
2. Perspectiva - se face în timpul - tehnici curente de
Continuă
temporală secvenţei de instruire ascultare -teze
- se realizează la
- lucrări scrise -
Finală sfârşitul perioadei de
examene
formare

Cele mai utilizate metode şi tehnici de evaluare utilizate sunt:


- observarea şi aprecierea orală;
- chestionarea orală şi scrisă;
- lucrările scrise (de tip compunere, eseu, rezolvare de exerciţii şi
probleme);
- testele (de cunoştinţe nestandardizate, diagnostice, docimologice-
standardizate, teste de aptitudini, de tip grilă, etc.);
- lucrările practice;
- examenele;
- scările de apreciere;
- cu ajutorul maşinilor şi a altor mijloace auxiliare etc.
Examinarea cu scoaterea la tablă se face cu unul sau mai mulţi elevi, în
timp ce elevii pregătesc răspunsurile, se poate lucra cu clasa sau verifica tema
de acasă. Când elevii răspund, este bine ca profesorul să se asigure că toată
clasa este atentă şi pregătită să intervină. Profesorul poate să pună întrebări
suplimentare sau ajutătoare atât elevilor ascultaţi cât şi celor din bănci. Prin
întrebări se caută să se pună în evidenţă aspectele esenţiale ale lecţiei.
Profesorul trebuie să-şi pregătească dinainte întrebările şi nu trebuie să
transforme verificarea într-o scoatere cu sila la tablă şi punerea unui noian de
întrebări care duc chiar până la sugerarea răspunsului.
Rezultatele şcolare sunt obiectivate în cunoştinţele acumulate, în priceperi
şi deprinderi, capacităţi intelectuale, trăsături de personalitate şi de conduită ale
elevilor.
Proiectarea obiectivelor de evaluare

Obiectivul de evaluare este un enunţ sintetic, vizând rezultatele concrete


ale procesului de învăţare (asimilare, formare) ce trebuie demonstrate de către
persoana evaluată. Fiind formulat în termenii comportamentului observabil
urmărit face posibil ca mai mulţi evaluatori să ajungă la aceeaşi judecată de
valoare referitoare la îndeplinirea, sau nu, a obiectivului. Din formularea
obiectivului trebuie să rezulte clar nivelul de performanţă necesar a fi atins de
către cel evaluat şi condiţiile necesare atingerii acestei performanţe. Obiectivele
de evaluare se formulează pe baza operaţionalizării obiectivelor curriculare.
După R.F.Mager (1972) [16.] modelul de operaţionalizare simplificat presupune
formularea unui astfel de enunţ prin specificarea a trei elemente:
- comportamentul necesar a fi demonstrat;
- condiţiile în care se produce comportamentul;
- nivelul de performanţă dorit, sau criteriul de reuşită.
Precizarea comportamentului observabil se face în mod tradiţional
folosind taxonomia lui B.S.Bloom, care a asociat fiecărui nivel de complexitate
a învăţării verbe de acţiune concrete:
Cunoaştere: să definească, să descrie, să identifice, să numească, să
selecteze, să reproducă, să enumere, etc.
Înţelegere: să transforme, să diferenţieze, să estimeze, să explice, să
generalizeze, să exemplifice, să parafrazeze, să rescrie, să rezume, să
argumenteze, să extindă, etc.
Aplicare: să aplice, să calculeze, să înlocuiască, să schimbe, să
descopere, să modifice, să prepare, să producă, să indice, să rezolve, să
utilizeze, să opereze, etc.
Analiză: să discrimineze, să descompună în componente, să diferenţieze,
să identifice, să ilustreze, să arate legăturile, să selecteze, să separe etc.
Sinteză: să clarifice, să combine, să compileze, să compună, să creeze,
să elaboreze, să organizeze, să planifice, să reconstruiască, să rezume, să
combine etc.
Evaluare: să justifice, să argumenteze, să interpreteze, să aprecieze, să
compare, să concluzioneze, să critice, să descrie, să discrimineze, să explice,
să rezume, etc.
Condiţiile de producere a comportamentului pot fi precizate prin formulări
de tipul: oral, scris, practic, dintr-o enumerare dată, pe baza textului din manual,
dintr-un text la prima vedere, aplicând regula (axioma, principiul, legea, etc.),
cu ajutorul profesorului, folosind tabelul (harta, diagrama, desenul) etc.

Criteriul de reuşită este precizat:


a) Cantitativ - prin precizarea limitei de timp, de dimensiune (lungime),
numărului de exemple dorite, procentul de realizare considerat satisfăcător
(sau minim);
b) Calitativ - prin enunţuri de tipul: enumerând ideile principale, corect,
sintetic, pe scurt, utilizând limbajul ştiinţific adecvat, în ordine cronologică, în
ordinea preferinţelor, pe baza unei anumite reguli, etc. şi complementaritate.

Instrumente de evaluare
Rezultatele şcolare ale fiecărui elev se concretizează în efectele
(rezultatele) învăţării personale. Deoarece aceste efecte nu se pot măsura
direct pentru că sunt constituite din comportamente formate în sfera psihică a
individului, apare necesitatea ca ele să fie exteriorizate şi traduse în mărimi
măsurabile. Aceste mărimi măsurabile nu sunt altele decât rezultatele probate
de elevi şi care pun în evidenţa nivelul de formare a comportamentelor dorite şi
exprimate prin obiective pedagogice. Deci, pentru obţinerea unor informaţii de
evaluare şcolară sunt necesare următoarele acţiuni:
- probarea de către elevi a nivelului la care au ajuns în realizarea
obiectivelor pedagogice;
- măsurarea rezultatelor probate;
- evaluarea lor.
Testele de evaluare
Testul reprezintă un instrument de evaluare folosit în general în sensul de
test şcolar şi cu orientări specifice de genul: test de cunoştinţe, de aptitudini, de
dezvoltare mintală, de comportament etc.
Prelucrând clasificarea tipurilor de teste de cunoştinţe relevate de
P.Lisievici [17.] se poate face clasificarea:
Criteriu Tipuri de teste Caracteristici
Utilizate în perioada preştiinţifică a evaluării
Integrative vizează structuri integrate de cunoaştere,
înţelegere, aplicare
Fiecare element de test măsoară un
Specificitate Punctuale
element cognitiv izolat, precis determinat
Introduc elemente de tip integrativ abordânc
„din generaţia a
obiective aparţinând nivelurilor cognitive
treia"
superioare
Itemi care pot fi cotaţi prin compararea
răspunsului cu un model complet a;
Obiective
răspunsului corect, cu coeficienţi de
Obiectivitate
fidelitate ridicaţi
Subiective Cu fidelitate redusă
Semiobiective Cu itemi combinaţi
Diagnostice (de Formative, nu urmăresc ierarhizarea,
progres) prezintă nevoia unei validităţi satisfăcătoare
De succes Sumative, au rol de ierarhizare, validitatea
educaţional şi fidelitatea fiind foarte importante
Ierarhizează şi permit repartizarea pe grupe
De plasament
Utilitate de nivel
Orientate către cerinţe esenţiale pentru
activitatea ulterioară (de tip TOEFL),
De capacitate
ierarhizează, presupun colaborarea unoi
(proficiency)
grupuri de experţi şi existenţa organelor
specializate de evaluare
Orale [ternii aleşi pot fi de multe ori subiectivi
Scrise Conţin itemi de toate tipurile
Forma de
Presupun existenţa şi eficienţa aparaturii
prezentare a Cu manipularea de
necesare, eventual înregistrarea
sarcinii aparate şi piese
rezultatelor intermediare
[mplică stabilirea unor grade de
De performanţă performanţă superioară, permiţând
selectarea, ierarhizarea
Necesită o stabilire riguroasă a timpului
Cu timp de
necesar de lucru pentru atingerea
Modul de execuţie limitat
performanţelor dorite
executare
Permit creaţia, pot fi evaluate de multe ori
Cu timp liber
subiectiv, pierd din validitate şi fidelitate
Construite pentru fiecare elev în parte pot fi
Individuale
standardizate sau nestandardizate
Modul de
Pe lângă performanţele dorite permit
aplicare
Colective (de grup) comunicarea, colaborarea, transmiterea,
motivarea superioară la nivelul grupului
Itemii pot fi divizaţi pentru a viza concret
Analitice
Forma de comportamentele urmărite
solicitare Cuprind itemi subiectivi, urmărind capacităţi
Sintetice
cum ar fi cea de sintetizare
Proiectarea unui test presupune legătura dintre relevanţa acestuia,
fidelitatea şi practicabilitatea să. Raportarea permanentă la obiectivele stabilite
conduce la obţinerea unei mai mari obiectivităţi a testului, aceasta reprezentând
şi calea eficientizării evaluării tradiţionale.

Caracteristici ale testelor:


După cum testele pot fi standardizate (docimologice), sau
nestandardizate, există câteva elemente definitorii care le caracterizează:
- asigurarea pe cât posibil a situaţiilor de experimentare şi măsurare
asemănătoare pentru toate persoanele testate;
- înregistrarea precisă şi obiectivă a comportamentului declanşat la
subiect;
- comportamentul înregistrat poate fi evaluat statistic prin raportare
la rezultatele aşteptate, la cele anterioare, eventual la cele ale unui grup
determinat de indivizi, etc.;
- clasificarea subiecţilor.
În plus există caracteristici generale ale testelor, de tipul:
- identifică tripletul: conţinut, condiţii de aplicare, criterii de apreciere;
- presupun respectarea stratificării materiei şi luarea în considerare
a importanţei secvenţelor de învăţare;
- conduc (în special cele docimologice) la standardizarea condiţiilor
de examinare, a modalităţilor de notare;
- conţin probe (itemi) care permit determinarea cu uşurinţă a gradului de
însuşire a cunoştinţelor şi de dezvoltare a capacităţilor;
- permit aprecierea individuală sau la nivel de clasă (serie) a elevilor;
- valorifică informaţia acumulată;
- permit extragerea esenţialului şi sistematizarea cunoştinţelor;
- se desfăşoară într-un timp optim stabilit.

Calităţile unui test bine proiectat sunt:


- fidelitatea - este îndeplinită dacă şi numai dacă aplicat în situaţii analoage
(sau identice), eventual de către specialişti diferiţi, se obţin rezultate identice
sau comparabile. Nu este niciodată absolută fiind admise abateri de 2.5% până
la 3%;
- puterea de discriminare - identificarea exactă a nivelului de performanţă
atins, precum şi a lacunelor fiecărui elev, asigurând o largă distribuţie a
scorurilor pentru grade diferite de pregătire a elevilor;
- aplicabilitatea - oferă date utile atât elevului cât şi profesorului;
- relevanţa (validitatea) - gradul în care probele alese (itemii) testează
comportamentele dorite(cunoştinţele, abilităţile vizate) şi nu altele, adică
măsoară exact ce şi-a propus să măsoare;
- echilibrul - modul în care se realizează o testare proporţională a fiecărei
componente a comportamentului, în conformitate cu intenţia celui care a
proiectat testul;
- eficienţa - măsura în care este folosit timpul profesorului pentru
proiectarea, administrarea, corectarea şi interpretarea rezultatelor testului şi
timpul elevilor pentru performarea testului respectiv;
- specificitatea - măsura în care itemii folosiţi sunt suficient de specifici
încât să se evite situaţia în care un elev poate obţine scoruri satisfăcătoare fără
să studieze materia respectivă;
- dificultatea - măsura în care itemii aleşi corespund ca grad de dificultate
nivelului subiecţilor vizaţi;
- siguranţa - măsura în care testul oferă scoruri care se corelează cu cele
obţinute prin alte metode şi instrumente de evaluare, pentru acelaşi domeniu
investigat;
- temporalitate - scorul obţinut reflectă nivelul real al elevului şi nu viteza
să de răspuns prin stabilirea unui timp adecvat de rezolvare.

Etapele realizării unui test


Proiectarea testului:
1. Precizarea obiectivelor;
2. Documentarea ştiinţifică necesară;
3. Avansarea unor ipoteze (conceperea şi/sau selecţionarea problemelor
reprezentative);
4. Stabilirea tipului de test adecvat;
5. Stabilirea tipurilor de itemi ce se vor folosi;
6. Stabilirea performanţelor minime acceptabile (barem)

Părţile componente ale unui instrument de evaluare:


a) Testul elevului (proba elevului) care reuneşte un anumit număr de itemi dat
elevilor spre rezolvare
b) Etalonul de rezolvare care cuprinde:
- răspunsurile concrete ale fiecărui item;
- punctajul care poate fi acordat pentru realizarea integrala a fiecărei sarcini
prevăzute în itemii testului;
c) Etalonul de convertire a punctajelor în note şcolare

Testul elevului: Caracterizare


- cuprinde itemi adresaţi acestuia şi care vor permite să se aprecieze efectele
acţiunii sale de învăţare;
- numărul itemilor dintr-un test este cel puţin egal cu numărul obiectivelor care
se evaluează.
Stabilirea numărului exact al itemilor rezultă din tipurile de sarcini de
instruire conţinute de obiectivele care se evaluează.

Exemplu:
"Elevul să recunoască şi să grupeze... " cuprinde două sarcini calitativ diferite
şi va trebui să fie evaluat prin doi itemi distincţi.
Deoarece evaluarea se aplică după desfăşurarea acţiunii compacte de
instruire, este indicat să se respecte regula ca "un obiectiv pedagogic să fie
evaluat printr-un singur item", acesta aducând simplificări acţiunii.
Pentru a uşura urmărirea corespondenţei dintre obiectivele care se
realizează şi itemii prin care se evaluează realizarea lor, la temele cu numărul
mare de obiective devine necesară elaborarea unei diagrame "obiective-itemi".
Itemii stabiliţi în elaborarea unui test pot fi aleşi din sursele de
documentare sau pot fi proiectaţi de către profesor. Este necesară deci
cunoaşterea diferitelor tipuri de itemi, a particularităţilor lor specifice. Evaluarea
procesului de instruire vizează aceleaşi domenii ca şi instruirea însăşi:
domeniul cognitiv (cunoştinţe), afectiv (atitudini) şi psihomotor (deprinderi), în
general nevoia de teste se adresează cu precădere domeniului cognitiv.
Tipurile reprezentative de itemi din domeniul cognitiv se pot clasifica
astfel:
1. Itemi obiectivi
- cu alegere multiplă
- cu o singură variantă de răspuns corectă
- cu mai multe variante de răspuns corecte
- cu alegere duală (de tip adevărat - fals);
- de tip cauză - efect
- cu modificarea alternativei F (fals)
- de asociere (pereche)
- de ordonare (ierarhizare)
- de tip selectare (grupare) după caracteristici
2. Itemi semiobiectivi
- cu răspuns scurt
- de completare a unei propoziţii lacunare
- cu ordine impusă de completare
- în orice ordine
- de tip întrebare structurată
3. Itemi subiectivi
- de tip rezolvare de problemă
- de tip redactare de text '
- de tip analiză, rezumat, sinteză, schematizare etc.
- de tip creaţie.
- prin răspunsuri în scris: comportamente de scriere, compunere,
recunoaştere, ordonare, identificare;
- prin răspunsuri concretizate în activităţi practice: comportamente de
tehnică profesională, deprinderi motorii şi intelectuale, executare de operaţii;
- prin răspunsuri date cu ajutorul calculatorului: comportamente de
recunoaştere, identificare, calcul;
3.6 Proiecte didactice – exemplificări sugestive

Proiectarea unităţii de învăţare

O unitate de învăţare poate acoperi una sau mai multe ore de curs. Ea
este cunoscută din punct de vedere al obiectivelor/competenţelor vizate,
prezintă o unitate din punct de vedere tematic (conţinut), se desfăşoară
continuu pe o perioadă de timp şi este finalizată prin evaluare.
Demersul pedagogic pentru o unitate de învăţare este proiectat individual
de fiecare profesor în parte. Etapele proiectării sunt înlănţuite logic şi contribuie
la detalierea conţinuturilor în scopul atingerii obiectivelor de referinţă şi
formarea competenţelor specifice.
Proiectarea se realizează ţinând cont de:
- Centrarea demersului pedagogic pe obiective/competenţe;
- Implicarea următorilor factori:
- obiective/competente (de ce?);
- activităţii (cum?);
- resurse (cu ce?);
- evaluare (cui?);
În proiectarea unităţii de învăţare se parcurg următoarele etape:
1. Identificarea setului de achiziţii anterioare necesar abordării noului conţinut:
- implică precizarea noţiunilor de bază şi a comportamentelor operatorii,
necesare pentru înţelegerea şi prelucrarea noului conţinut (achiziţii anterioare);
- se poate realiza o probă de evaluare iniţială
2. Activităţile de învăţare pregătitoare:
- se realizează prin prezentarea unor situaţii problemă desprinsă din
cotidian;
- sunt exemple din cotidian abordate prin descoperire; reprezintă
valorificarea achiziţiilor din ciclul anterior;
- conduc la compatibilizarea noilor cunoştinţe cu experienţa anterioare
a elevului într-o formă accesibilă cu realizarea unor legături interdisciplinare;
3. Introducerea suportului noţional:
- necesită esenţializarea şi sistematizarea conţinuturilor în limbaj simplu;
4. Modelarea:
- presupune aplicaţii relevante ale modelului şi evidenţierea limitelor;
permite dezvoltarea unor rezultate teoretice;
- se realizează prin decurs dirijat cu activităţii pe grupe sau individual şi
sarcini precise.
5. Exersare direcţională
- Constă din aplicaţii ordonate progresiv care conduce la elaborarea unor
strategii de rezolvare;
- Modul de organizare se adaptează nevoilor grupului de elevii şi se
personalizează pe filiere şi specializări;
- Are rol de fixare şi sistematizare;
- Include probe de evaluare formative/curente.
6. Aprofundarea / generalizarea
- Oferă oportunităţiile de învăţare necesare pentru dobândirea
competenţelor acţionale şi focalizarea pe finalitate;
- Presupune activităţi diferenţiate pentru valorificarea diferitelor stiluri de
învăţare şi a diferenţelor individuale;
- Proba de evaluare sumativă.
EXEMPLU DE UNITATE DE ÎNVĂŢARE
STRUCTURI DINAMICE DE DATE
CLASA A XI-A profil matematică-informatică
Competenţe specifice:
S1: Cunoaşterea şi înţelegerea operaţiiilor cu pointeri
S2. Aplicarea corectă a funcţiilor de alocare şi dezalocare a memoriei
S3. Înţelegerea avantajelor alocării dinamice a memoriei
S4. Cunoaşterea definiţiei de stivă şi a operaţiilor cu aceasta
S5. Cunoaşterea definiţiei de coadă şi a operaţiilor cu aceasta
S6. Cunoaşterea definiţiei de listă simplu înlănţuită şi a operaţiilor cu aceasta
S7. Cunoaşterea definiţiei de listă dublu înlănţuită şi a operaţiilor cu aceasta
S8. Recunoaşterea diferitelor tipuri de structuri în rezolvarea problemelor

Proiectarea unităţii de învăţare:


COMPETENŢE
ETAPE ALE PROIECTĂRII CONŢINUTURI ACTIVITĂŢI DE ÎNVĂŢARE EVALUARE
SPECIFICE
Achiziţii anterioare
S1 - noţiunea de pointer
Reactualizare Exerciţii recapitulative Teste grilă
S2 - funcţii de alocare şi dezalocare a
memoriei
Seturi de
S1 Compatiblizarea noilor noţiuni cu
- Identificarea problemelor care enunţuri din
S3 experienţa anterioară a elevului
cer folosirea structurilor de date care să
- exemplificarea unor situaţii din
Învăţare pregătitoare S4 - Recunoaşterea necesităţii aleagă
practică care conduc la folosirea
pentru situaţii problemă S5 folosirii alocării dinamice structurile
diverselor structuri de date
- Recunoaşterea diverselor necesare
S6 - prezentarea structurilor alocate atatic
structuri în aplicaţii Rezolvări de
S8
probleme
Esenţializarea şi sistematizarea
Prezentarea structurilor alocate
S4 rezultatelor
dinamic
Exersarea conţinutului noţional pe
S5 Prezentarea operaţiilor Itemi cu
Suport noţional exemple semnificative
S6 corespunzătoare alegere dublă
- prezentarea stivei alocate dinamic
Evidenţierea diferenţelor dintre
S7 - prezentarea cozii alocate dinamic
structuri
- prezentarea listelor alocate dinamic
Aplicaţii semnificative ce conduc la Seturi de
construirea algoritmului de lucru Aplicaţii standard din: aplicaţii
Modelare S8 - Implementarea dinamică a structurilor - stiva, coada, lista simplu Rezolvări de
- Aplicaţii ce permit dezvoltarea înlănţuită, lista dublu înlănţuită probleme
rezultatelor teoretice Probă scrisă
Aplicaţii: Proiect
S6 Aplicaţii ordonate progresiv cu scop de
Exersare direcţională - liste circulare Seturi de
S7 exersare a strategiilor de rezolvare
- liste ordonate aplicaţii
S8 - Dezvoltarea competenţelor cognitive şi - arbori Tema de
operatorii - matrici rare lucru acasă
- polinoame rare
Observare
sistematică
Activitate
S6
Aprofundare, Exemple de probleme cu grad de practică
S7 Generalizarea rezultatelor
generalizare dificultate sporit individuală
S8 Tema de
lucru pentru
acasă
Variante ale lecţiilor de informatică
Forma fundamentală de organizare a procesului de instruire este lecţia.
La conţinutul propriu-zis, se adaugă aplicarea metodelor de predare pe care
profesorul le va alege cât şi obiectivele pe care acesta şi le propune.
Nu poate fi considerată oră de curs aceea care nu leagă ceea ce s-a
studiat înainte, cunoştinţele anterior dobândite, de cunoştinţele care trebuiesc
transmise în continuare. Lecţia are un caracter unitar prin conţinutul ei, prin
procedeele ce se aplică, prin gradul de participare a elevilor la procesul
instructiv-educativ.
Orice lecţie trebuie încheiată printr-un rezumat, o recapitulare a întregului
volum de cunoştinţe abordate pe întreg cuprinsul lecţiei şi o fixare, prin care să
se finalizeze activitatea întreprinsă. Deseori se anticipează ca o necesitate
introducerea unor noi noţiuni şi se stabileşte un plan de abordare a lecţiilor
următoare.
Lecţia nu este numai o formă de organizare a muncii, o succesiune de
etape stabilite şi efectuate. Ea presupune o serie de evenimente imprevizibile
şi care se caracterizează prin particularităţi specifice. Se fac adesea tentative
de clasificare a lecţiilor (de comunicare de cunoştinţe, de studiu individual, de
descoperire, de verificare, de recapitulare, etc.). Delimitările nu sunt însă
stricte, fiecare lecţie fiind o împletire (care se doreşte armonioasă) de metode
şi tehnici care concură la realizarea obiectivelor propuse, raportul în favoarea
uneia sau altei dintre metode fiind greu de stabilit în final şi cu atât mai mult
iniţial.
În general, structura unei lecţii cuprinde:
- la început, după momentul organizatoric legat de prezenţă şi verificarea
condiţiilor (cretă, burete, material didactic, etc.) de desfăşurare a lecţiei, se
verifică tema de acasă şi se stabilesc dificultăţile întâmpinate în efectuarea ei;
- elevii sunt apoi ascultaţi din materia predată în lecţia anterioară şi se
caută să se înlăture defectele apărute în procesul de asimilare impus de
materia analizată;
- se predă lecţia nouă;
- se fixează cunoştinţele comunicate prin exerciţii;
- se stabileşte tema pentru acasă.
Anomaliile care apar (lecţie care poate fi definită ca necorespunzătoare)
sunt legate în principal de pierderea timpului cu verificarea temei de acasă şi
cu măsurile luate de profesor privitoare la nerealizarea acesteia. Cel mai mult
timp trebuie afectat comunicării cunoştinţelor noi şi fixării acestora prin exerciţii.
Tema pentru acasă nu trebuie dată în pauză sau când se sună.
Observaţie. Volumul de muncă necesar efectuării temelor pentru acasă
trebuie să se înscrie în limite rezonabile (sunt suficiente recomandări pentru
sarcinile suplimentare). Un număr mai mare de exerciţii duce la lucru de
mântuială, copieri, abandonarea întregii teme, refuz faţă de abordarea temei.
Tema trebuie să fie în corespondenţă cu posibilităţile elevilor şi legată de
însuşirea şi aplicarea cunoştinţelor predate. Ea trebuie dată diferenţiat, atunci
când între elevii aceleaşi clase sunt diferenţe mari în ceea ce priveşte
capacitatea sau pregătirea lor. Tema trebuie să fie însoţită de explicaţii
ajutătoare, de indicaţii potrivite.
Când tema presupune artificii de calcul sau cere o pricepere deosebită,
trebuie ca elevilor să li se atragă atenţia asupra acestui aspect (de exemplu,
prin exerciţii cu *, adică dificile).
Mulţi elevi învaţă pe de rost metodele de rezolvare a unor probleme şi îşi
formează şabloane pe care le aplică automat. Cu siguranţă şi algoritmii
importanţi, rezultat al analizei şi cercetării îndelungate, trebuie reţinuţi, dar
uzând-se de logica internă a acestora.
Profesorul are obligaţia să înveţe pe elevi cum să-şi facă tema, nu să
creeze în permanenţă un climat ce determină ca necesitate apariţia
meditatorului (un mediator păgubos între elev şi profesor şi nu o prelungire a
acestuia din urmă, în cazuri extreme). Temele de acasă îşi ating scopul doar
dacă sunt controlate în permanenţă de profesor.

Tipuri de lecţii specifice orelor de informatică

1) Lecţia de comunicare şi însuşire de noi cunoştinţe.


Variante: lecţii bazate pe învăţarea prin receptare a descrierii, expunerii,
explicaţiei, explicaţiei-demonstraţiei, textului din manual, instructajului,
conţinutului televizat, demonstraţiei filmice etc.;
2) Lecţia de elaborare a cunoştinţelor şi dezvoltare a strategiilor cognitive
Variante: lecţii bazate pe învăţare prin cercetare, prin descoperire;
prin observare directă şi independentă sau dirijată (intuitiv-investigativă),
observarea nemijlocită de material prelucrat, explorarea experimentală a
realităţii, studiul (analiză) de caz, cercetarea documentelor istorice, studiu
(analiză) de text, problematizare, dezbatere euristică, dialog euristic etc.;
3) Lecţia de formare a priceperilor şi deprinderilor
Variante: lecţii bazate pe învăţarea prin: exerciţii executorii, exerciţii
creative, imitaţie de modele, repetare, activităţi practice, exersare simulată etc.;
4) Lecţia de consolidare şi sistematizare
Variante: lecţii bazate pe rezolvare de exerciţii şi probleme, exerciţii de
vorbire şi scriere, discuţie de sistematizare şi clasificare, discuţie de revizie
sumară, aplicaţii practice, recapitulare, joc didactic, expunere de sinteză
(concluzii), discuţie finală etc.
5) Lecţia de aplicaţii practice, de dezvoltare a funcţiilor de acţiune sau de
transfer
Variante: lecţii bazate pe generalizări (transferuri), studiu (analiză) de caz,
rezolvări de exerciţii şi probleme, lucrări practice, lucrări experimentale, aplicaţii
tehnice, muncă de fabricaţie, exersare pe simulatoare, experienţă simulată prin
jocuri de roluri (lecţii cu caracter de joc), de caracterizare a personajelor literare
etc.;
6) Lecţia de creaţie, de dezvoltare a funcţiilor de expresie (a capacităţilor şi
aptitudinilor de creaţie)
Variante: lecţii bazate pe învăţare prin creaţie, adică pe exerciţii de creaţie,
creaţie de modele noi, compuneri libere, eseuri literare şi filozofice, creaţie
tehnică, creaţie artisitcă, aplicaţii creatoare etc.;
7) Lecţia de evaluare.
Variante: lecţii de verificare şi apreciere, de lucrări practice şi apreciere,
de lucrări scrise, de analiză şi corectare a lurărilor, de dezbatere asupra
alternativelor şi modurilor de acţiune aplicate, de evaluare a exerciţiilor (fizice
de exemplu) etc;
8) Lecţia de atitudine (motivaţie).
Variante: lecţia de sensibilizare (de sesizare a semnificaţiilor), lecţia de
introducere sau inaugurală (de sesizare a cadrului ideaţional), lecţia-
demonstraţie de sensibilizare etc.;
9) Lecţia complexă sau mixtă (de dezvoltare multilaterală).
Se poate observa că polifuncţionalitatea unor variante creează unele
dificultăţi de plasare a lor într-o categorie sau alta, de aceea se pot regăsi ca
variaţii la două sau chiar mai multe tipuri de lecţii.

Exemple de proiecte de tehnologie didactică

a) Lecţie mixtă
Caracteristici: urmăreşte realizarea aproximativ în aceeaşi măsură a mai
multor sarcini didactice (comunicare, sistematizare, fixare, verificare, etc.),
fiecăreia fiindu-i rezervată o verigă a instruirii, sarcinile profesorului şi elevilor
se situează pe acelaşi plan, succesiunea evenimentelor este variabilă, volumul
cunoştinţelor predate este mai redus.
Structură:
- organizarea clasei pentru lecţie şi captarea atenţiei elevilor;
- actualizarea elementelor învăţate anterior;
- pregătirea elevilor pentru asimilarea noilor cunoştinţe;
- comunicarea şi asimilarea noilor cunoştinţe
- fixarea cunoştinţelor predate (sistematizare, exerciţii aplicative, reluarea
într-un alt context a esenţialului, etc.);
- conexiunea inversă - pe tot parcursul lecţiei

Proiect de tehnologie didactică


Profesor: Runceanu Mihaela
Disciplina: Informatică
Clasa: a XI-a A
Data: …
Tema lecţiei: Structura de date de tip listă simplu înlănţuită alocată dinamic
Tip lecţie: mixtă (verificare şi comunicare de cunoştinţe)
Obiective operaţionale:
La sfârşitul acestei lecţii elevii vor fi capabili:
- Să poată defini o structură de date de tip listă simplu înlănţuită
- Să cunoască şi să folosească în aplicaţii principalele operaţii care se pot
efectua cu nodurile (elementele) unei liste simplu înlănţuite
- Să identifice situaţiile în care este recomandabilă utilizarea acestei
structuri de date
- Să folosească în mod optim în aplicaţii, liste simplu înlănţuite

Abordarea lecţiei presupune cunoaşterea de către elevi:


- a alocării dinamice a variabilelor;
- alocarea şi eliberarea efectivă a zonelor de memorie aferente;
- lucrul cu tipul pointer şi tipul referinţă;
- deosebirea dintre variabilelor de tip pointer şi tip referinţă.

Succesiunea şi desfăşurarea momentelor lecţiei


1. Momentul organizatoric:
- durata: maxim 2 minute;
-obiective urmărite: crearea unei atmosfere specifice bunei desfăşurări a
activităţii didactice;
- activitatea profesorului: verificarea prezenţei, a resurselor materiale şi de
soft necesare desfăşurării lecţiei (tabla, creta), funcţionalitatea staţiilor de lucru,
existenţa şi funcţionarea softului (sistem de operare, mediul C++, utilitare etc.)
- activitatea elevului: pregătirea caietelor, intrarea în mediul de programare
etc.
- metode şi procedee didactice: metoda conversaţiei

2. Verificarea temei pentru acasă şi a cunoştinţelor dobândite anterior


- durata: 8 minute
- activitatea profesorului: verificarea temei prin sondaj şi prin întrebări a
cunoştinţelor elevilor, necesare înţelegerii conţinuturilor ce vor fi comunicate în
lecţia nouă:
a) Câte moduri de alocare a memoriei cunoaşteţi? Care sunt acestea?
b) Care sunt deosebirile dintre alocarea statică şi alocarea dinamică?
c) Prezentaţi avantajele alocării dinamice.
d) Puteţi enumera şi dezavantaje?
e) Prezentaţi situaţii în care este mai avantajos un anumit mod de alocare
a memoriei şi argumentaţi răspunsul.
- activitatea elevului: ascultă întrebările şi elaborează răspunsurile în
concordanţă cu conţinuturile asimilate anterior şi cu experienţa dobândită în
aplicarea acestora în exerciţii şi probleme
- metode şi procedee didactice: metoda conversaţiei, metoda
demonstraţiei, metoda problematizării

3. Captarea atenţiei, prezentarea titlului şi obiectivelor lecţiei noi


- durata: 3 minute
- activitatea profesorului:
a) prezintă o situaţie problemă în care caută să scoată în evidenţă
utilizarea unei structuri de date de tip listă simplu înlănţuită, insistând asupra
avantajelor pe care le prezintă această structură în condiţiile impuse de
problemă;
b) este subliniată o gamă largă de probleme (gestionarea
documentelor şi reprezentările/vizualizările acestora, gestionarea unei aplicaţii,
gestionarea spaţiului de memorie liber şi/sau alocat explicit etc.) care vor putea
fi soluţionate elegant folosind structura de date de tip listă;
- activitatea elevului: ascultă şi notează cele prezentate sau notate pe
tablă de catre profesor şi pune întrebări care să poată lămuri contextul în care
se va desfaşura lecţia.
- metode şi procedee didactice: metoda conversaţiei, metoda
demonstraţiei, metoda problematizării

4. Prezentarea noilor conţinuturi:


- durata: 12 minute;
- activitatea profesorului:
Profesorul prezintă succesiv:
a) definirea tipului de date necesar
Typedef struct tnod
{

tip inf; //informatia propriu-zisa

struct tnod *leg:; //informatia de legatura

} LISTA;

b) definirea variabilelor de tip referinţă la nod

LISTA *prim,*ultim; /* adresa primului, respectiv a ultimului element


din lista */

c) operaţiile care se pot face cu nodurile unei liste simplu înlănţuite

- adăugarea unui nod;


- căutarea unui nod identificat prin informatia din nod;
- inserarea unui nod;
- ştergerea unui nod;
- parcurgerea unei liste simplu înlănţuite;
Prezentarea operaţiilor cu nodurile unei liste simplu înlănţuite vor fi însoţite
de scheme şi desene sugestive.
- activitatea elevului: ascultă şi notează cele prezentate sau notate pe
tablă de către profesor şi pune întrebări care să poată lămuri aspectele neclare,
participă activ la stabilirea instanţelor de implementare;
- metode şi procedee didactice: metoda expunerii, a demonstraţiei, a
exerciţiului, a problematizării.

5. Asigurarea conexiunii inverse:


- durata: 4 minute;
- activitatea profesorului: profesorul solicită elevilor prezentarea unor
situaţii problemă, din cele întâlnite anterior, în care se poate folosi o listă simplu
înlănţuită şi cere să se argumenteze exemplele date.
- activitatea elevului: identifică probleme şi propune soluţii în care se va
folosi structura de date învăţată, prezentând avantajele unei astfel de
implementări;
- metode şi procedee didactice: metoda învăţării prin descoperire, metoda
problematizării

6. Obţinerea performanţelor
- durata: 10 minute;
- activitatea profesorului: profesorul propune elevilor scrierea de rutine
care să implementeze în limbajul C++ operaţiile cu listele simplu înlănţuite,
îndrumă şi supraveghează activitatea elevilor.
- activitatea elevului: utilizând materialul didactic (calculatorul, notiţe,
documentaţii), elevii vor scrie rutinele corespunăatoare operaţiilor cu nodurile
unei liste simplu înlănţuite;

a) Iniţializarea listei (crearea unei liste vide)


void init(TNOD *prim)

prim=NULL;

b) Adăugarea unui element în listă

- Adăugarea unui element la începutul listei


void adaugi( tip x; LISTA *prim) /*x reprezinta informatia ce se adauga la
începutul listei */

LISTA *p; // pointerul de lucru

p=new LISTA;

p->inf=x;

p->leg=prim;

prim=p;

}
- Adăugarea unui element la sfârşitul listei
void adaugs( tip x; LISTA *ultim) // realizează adaugarea valorii x la sfarşitul
listei

LISTA *p; //pointer de lucru

p=new LISTA;

p->leg=NULL;

p->inf=x;

ultim->leg=p;

ultim=p;

- Adăugarea unui element în interiorul listei


void adaugd( int x; LISTA *q) //adauga valoarea lui x într-un nod ce urrmeaza
nodului indicat de q în lista

LISTA *p; //pointer de lucru

p=new LISTA;

p->inf=x;

p->leg=q->leg;

q->leg=p;

c) Traversarea ( parcurgerea ) listei


void parcurgere ( LISTA *prim)

LISTA *p;
p=prim;

while (p!=NULL)

cout<<p->inf;

p=p->leg;

d) Ştergerea unui element din listă

void stergere(LISTA *r)

LISTA *s,*q;

if (r==prim)

{ // Se va şterge primul elemental listei

s=prim;

prim=prim->leg;

delete s;

else

if (r==ultim)

{ // Se va sterge ultimul nod al listei

q=prim; //va retine adresa penultimului nod

while (q->leg !=ultim)

q=q->leg;

s=ultim;

ultim=q;
ultim->leg=NULL;

delete s;

else

{ // stergerea unui nod din interiorul listei

s=r->leg; // în s se retine adresa nodului care va fi sters


efectiv, adica cel caruia îi vom face dublura

r->inf=r->leg->inf;

r->leg=r->leg-leg; // am creat dublura nodului urmator

delete s;

e) Căutarea unui element în listă


LISTA* caut(int x) // x-informatia pe care o cautam în lista

LISTA *P // folosit pentru parcurgerea listei

int gasit;

gasit=0;

p=prim;

while (p!=NULL && !gasit )

if (p->inf==x) gasit=1;

else p=p->leg;

if (gasit) return p;

else return NULL;

}
- metode şi procedee didactice: metoda învăţării prin descoperire, metoda
problematizării, metoda lucrului în grupe mici

7. Dirijarea învăţării
- durata: 4 minute;
- activitatea profesorului: profesorul solicită elevilor prezentarea modului
de implementare a algoritmului de sortare prin insertie folosind o listă simplu
înlănţuită.
- activitatea elevului: elevii prezintă varianta de implementare solicitată şi
evidenţiază operaţiile care se vor efectua cu nodurile listei;
- metode şi procedee didactice: metoda conversaţiei, metoda expunerii

8. Evaluarea cunoşţintelor dobândite:


- durata: 5 minute;
- activitatea profesorului: profesorul verifică modul în care au fost realizate
rutinele care implementează operaţiile cu nodurile listelor simplu înlănţuite şi
comentează eventualele erori, apoi trece în revistă reuşitele şi erorile frecvente,
în ideea eliminării acestora;
- activitatea elevului: elevii reţin şi notează observaţiile făcute;
- metode şi procedee didactice: metoda conversaţiei, metoda expunerii

9. Prezentarea temei pentru acasă (care nu se face niciodată în pauză)


- durata: 2 minute;
- activitatea profesorului: profesorul solicită realizarea unei implementări
nerecursive a funcţiei lui Ackermann folosind o listă simplu înlănţuită (problema
a fost rezolvată folosind alocarea statică a variabilelor necesare implementării);
- activitatea elevului: notează problema propusă spre rezolvare şi
indicaţiile de implementare ale profesorului şi cere eventuale lămuriri
suplimentare;
- metode şi procedee didactice: metoda conversaţiei
b) Lecţie de comunicare şi însuşire de noi cunoştinţe
Caracteristici: concentrarea activităţii didactice în direcţia dobândirii de
către elevi a unor cunoştinţe şi dezvoltării, pe această bază, a proceselor şi
însuşirilor psihice, a capacităţilor instrumentale şi operaţionale, comunicarea
are ponderea cea mai mare în lecţie.
Structură (subsecvente):
- pregătirea elevilor în vederea asimilării noilor cunoştinţe; anunţarea
subiectului şi a obiectivelor;
- stabilirea de asociaţii cu cunoştinţele asimilate anterior; 4 fixarea finală
prin generalizări şi concluzionări.
Variante posibile:
- lecţii de descoperire pe cale inductivă;
- lecţii de descoperire pe cale deductivă;
- lecţii introductive (la începutul tratării unui capitol);
- lecţii prelegere;
- lecţii seminar;
- lecţii problematizate;
- lecţii de asimilare prin activitatea pe grupe cu sarcini diferenţiate sau
comune;
- lecţii de comunicare pe baza instruirii programate.

Proiect de tehnologie didactica


Profesor: Runceanu Mihaela
Disciplina: Informatică
Clasa: a XI-a A
Data: …
Tema lecţiei: Tipul referinţă, noţiunea de pointer. Operaţii aritmetice cu pointeri
Tip lecţie: lecţie de comunicare şi însuşire de noi cunoştinţe

Obiectiv fundamental:
Însuşirea noţiunilor de pointer şi variabilă dinamică, înţelegerea şi
însuşirea operaţiilor cu pointeri disponibile în limbajul C++.
Obiective operaţionale:
La sfârşitul acestei lecţii elevii vor fi capabili:
- Să definească noţiunile de variabilă dinamică şi pointer
- Să facă diferenţa între variabile statice şi dinamice
- Să recunoască avantajele alocării dinamice
- Să deprindă folosirea funcţiilor de alocare şi eliberare a memoriei
- Să cunoască şi să folosească în aplicaţii operaţiile care se pot efectua
cu pointerii
Metode şi strategii didactice: conversaţia frontală şi individuală, explicaţia,
expunerea etc.
Mijloace de învăţământ: manuale, culegeri de probleme
Forme de organizare: activitate frontală
Resurse:
- pedagogice – cursuri de informatică, manualul şcolar;
- oficiale: programa şcolara;
- temporale – 50 de minute;
- psihologice: cunoştinţele dobândite de către elevi la disciplina
Informatică, pe parcursul clasei a IX-a

Desfăşurarea lecţiei:

Punctul 1
Momentele lecţiei: Organizarea clasei (60 secunde)
Activitatea profesorului: Profesorul face prezenţa şi se asigură că sunt pregătiţi
pentru începerea lecţiei
Metode didactice: Activitate frontală, expunerea, explicaţia

Punctul 2
Momentele lecţiei: Enunţarea scopului lecţiei. În cadrul lecţiei care urmează vor
fi expuse urmăatoarele probleme legate de alocarea dinamică a memoriei în
limbajul C++:
- noţiunile de tip referinţă şi pointer
- declararea unui pointer
- utilizarea funcţiilor de alocare şi eliberare a memoriei
- prezentarea şi folosirea operaţiilor cu pointeri

Reactualizarea cunoştinţelor dobândite anterior:


Ce înseamnă tip de date?
Cum se clasifică tipurile de date?
Ce este o variabilă şi prin ce se caracterizează?
Ce se înţelege prin adresa unei variabile?
Activitatea elevilor: ascultă întrebările şi elaborează răspunsurile în
concordanţă cu conţinuturile asimilate anterior şi cu experienţa dobândită în
aplicarea acestora în exerciţii şi probleme
Activitatea profesorului: Se va insista asupra modului de alocare a memoriei
pentru structurile (statice) cunoscute până în momentul respectiv
Metode didactice: activitate frontală, expunere

Punctul 3
Momentele lecţie: Predarea noilor cunoştinţe
Activitatea profesorului:Profesorul explică elevilor noile noţiuni, exemplificând
cu desene la tablă sau folosind planşe în acest sens. De asemenea, dacă este
posibil, se poate folosi un retroproiector sau soft educaţional;
Pentru alocarea dinamică se utilizează tipul de date referinţă (pointer).
Structurile dinamice, neavând nume, sunt accesibile prin intermediul altor
variabile, care conţin adresele lor, şi în felul acestea “le indică”. Aceste variabile
se numesc pointeri şi formează tipul referinţă. Pointerii sunt variabile statice
obişnuite şi au ca valori adrese, care pot fi adresele de început ale unor structuri
dinamice sau a unei componente a unei asemenea structuri. Deci, accesul la o
variabilă dinamică, indicată de o variabilă pointer se realizează prin adresarea
indirectă a variabilei pointer. Această indirectare se pune în evidenţă prin
ataşarea operatorului unar ‘*’ (operator de indirectare) înainte de numele
variabilei pointer.
În general, un pointer se declară prin: tip *nume; ceea ce înseamnă că
nume este un pointer care pointează spre o zonă de memorie ce conţine o dată
de tipul tip.
Spaţiul necesar variabilelor alocate dinamic se rezervă într-o zonă
specială de memorie numită HEAP. Aşadar, valorile unui tip reper reprezintă
fie adrese din Heap ale unor variabile dinamice de tipul specificat în definiţia
tipului reper respectiv, fie valoarea constantei standard NULL.
Operaţiile cu pointeri:
1. Atribuirea: o variabilă de tip pointer primeşte valoarea unei alte variabile sau
funcţii de acelaşi tip pointer cu ea sau este iniţializată cu constanta NULL.
2. Operaţii de incrementare şi decrementare:
Asupra variabilelor de tip pointer operatorii de incrementare şi
decrementare se execută altfel decât asupra datelor de alte tipuri.
- operatorul de incrementare aplicat asupra unui operand de tip pointer
spre tipul t măreşte adresa conţinută de operand cu numărul de octeţi necesari
pentru a păstra o dată de tipul t;
- operatorul de decrementare se execută în mod analog, cu singura
diferenţă ca în loc să se mărească valoarea pointerului, ea se micşorează cu
numărul corespunzător de octeţi.
Aceste operaţii sunt deosebit de utile când au loc prelucrări de tablouri.
Fie urmâtoarele declaraţii:
int tab[100] ;
int *p;
int i;
Fie atribuirea p=&tab[i]; unde 0<i<100. În acest caz, instrucţiunea p++; măreşte
valoarea lui p cu 2 (tipul int se pastrează pe doi octeţi) şi deci în acest moment
p conţine adresa elementului tab[i+1]. În mod analog, instrucţiunea p--;
micşorează valoarea lui p cu 2 şi deci în urma acestei decrementări p conţine
adresa elementului tab[i-1].
3. Adunarea şi scăderea unui întreg dintr-un pointer
Dacă p este un pointer, sunt corecte expresiile de forma: p+n şi p-n unde
n este de tip întreg.
- Expresia p+n măreşte valoarea lui p cu cu n*t, unde t este numărul
de octeţi necesari pentru a memora o dată de un tip spre care pointează p;
- În mod analog, expresia p-n micşorează valoarea lui p cu n*t.
Dacă x este un tablou de tipul t, atunci x este pointer, deci o expresie de
forma x+n este corectă şi deoarece x este un pointer spre primul său element
x[0], x+n va fi un pointer spre elementul x[n]. Rezultă că valoarea elementului
x[n] se poate reprezentă prin expresia *(x+n) care este o expresie cu pointeri.
Astfel, o expresie cu indici se poate înlocui printr-o expresie cu pointeri.
Acest lucru permite ca la tratarea tablourilor să se folosească expresii cu
pointeri în locul variabilelor cu indici
4. Compararea a doi pointeri
Doi pointeri care pointează spre elementele aceluiaşi tablou pot fi
comparaţi folosind operatorii de relaţie şi de egalitate.
Astfel, dacă p şi q sunt doi pointeri care indică spre elementele t[i]
respectiv t[j] ale tabloului t, expresia p<q are sens şi ea este adevărată dacă
i<j. De asemenea, p!=q are valoarea adevărat dacă i  j.
Observaţii:
a) Pointerii nu pot fi comparaţi decât în condiţia amintită mai sus.
b) Operatorii de egalitate ( = = şi ! = ) permit totuşi compararea unui pointer
cu constanta simbolică NULL. Aceste comparaţii permit să stabilim dacă un
pointer conţine o adresă sau nu.
5. Diferenţa a doi pointeri
Doi pointeri care pointează spre elementele aceluiaşi tablou pot fi scăzuţi.
Rezultatul diferenţei a doi pointeri este definit astfel: fie a un tablou de un tip
oarecare şi p, q doi pointei: p conţine adresa elementului a[i], iar q conţine
adresa elementului a[i+n]. Atunci diferenţa q-p are valoarea n.
EXEMPLE:
1) unsigned lungime(char *x) /* returnează lungimea şirului spre care pointează
x */
{
int i;
for(i=0;*x!=’\0’;i++)
x++;
return i;
}
Observaţii:
- Condiţia *x!=’\0’ poate fi înlocuită cu *x, deoarece *x!=’\0’ este adevarată când
*x este diferit de zero şi invers.
- Ciclul for poate fi compactat şi mai mult: for(i=0;*x++ ;i++) ;

2) void copiază(char *x, char *y) /* copiază şirul spre care indică y în zona spre
care indică x*/
{
while(*x++=*y++);
}
Expresia de atribuire *x++=*y++ realizează atribuirea *x=*y utilizând
valorile neincrementate ale lui x şi y. Dacă valoarea atribuită este diferită de
zero, expresia de atribuire se consideră adevarată, deci ciclul continuă. În
momentul în care se atribuie valoarea 0, adică s-a ajuns la sfarşitul şirului spre
care indică y, expresia de atribuire este falsă şi ciclul se întrerupe.

3) void concatenează(char *x,char *y) /* concatenează şirul spre care pointează


y la sfârşitul şirului spre care pointează x*/
{
/* se avansează cu pointerul x până la sfârşitul şirului */
while(*x) x++;
/* se copiază şirul spre care indică y în zona spre care indică x */
while(*x++=*y++);
}

4) int compară(char *x, char *y) /* returnează o valoare negativă dacă x<y, zero
dacă x=y respectiv o valoare pozitivă dacă x>y */
{
while(*x==*y){ /* ciclul funcţionează cât timp caracterele curente din
cele două şiruri sunt egale*/
if(*x==’\0’) /* dacă s-a ajuns la sfârşitul sirului din x, s-a ajuns şi la cel
din y şi toate caracterele corespunzătoare au fost egale, deci şirurile sunt egale
*/
return 0; /* se trece la perechea următoare de caractere */
x++; y++;
}
/* deoarece ciclul s-a terminat, rezultă că s-au găsit cel puţin două caractere
diferite */
return *x-*y; /* dacă diferenţa caracterelor este negativă atunci x<y, altfel
x>y */
}

Activitatea elevului: ascultă şi notează cele prezentate sau notate pe tablă de


către profesor şi pune întrebări care să poată lămuri aspectele neclare,
participă activ la stabilirea instanţelor de implementare;
Metode şi procedee didactice: metoda conversaţiei, metoda expunerii

Punctul 4
Momentele lecţiei: Fixarea noilor cunoştinţe
Activitatea profesorului: Profesorul pune întrebări elevilor pentru a evalua
înţelegerea noilor cunoştinţe de către elevi, precum şi necesitatea folosirii lor
Activitatea elevului: identifică probleme şi propune soluţii în care se vor folosi
cunoştinţele învăţate, prezentând avantajele unei astfel de implementări;
- metode şi procedee didactice: metoda învăţării prin descoperire, metoda
problematizării

Punctul 5
Momentele lecţiei: Prezentarea temei pentru acasă (care nu se face niciodată
în pauză)
Activitatea profesorului: profesorul solicită realizarea unei aplicaţii care să
folosească numai variabile alocate dinamic (rezolvarea ecuaţiei de gradul I)
Activitatea elevului: notează problema propusă spre rezolvare şi indicaţiile de
implementare ale profesorului şi cere eventuale lămuriri suplimentare;
Metode şi procedee didactice: metoda conversaţiei
3.7 CONCLUZII

Având în vedere cele prezentate în capitolele anterioare, putem trage


anumite concluzii în ceea ce priveşte atitudinea profesorului de informatică în
procesul predării alocării dinamice a memoriei:

1. Profesorul trebuie să fie interesat de subiect


În timpul unei ore, orice stare a profesorului se transmite şi elevului.
Profesorul nu are voie să arate dezinteres sau plictiseală faţă de subiectul pe
care îl predă. Trebuie să-1 considere interesant, chiar dacă subiectul respectiv
este simplu, (pentru un începător nimic nu este prea simplu, pe de altă parte
orice devine extrem de simplu, după ce a fost învăţat). Nu este voie să se arate
semne de rutină din cauză că subiectul respectiv a fost predat la mai multe
clase sau la mai multe generaţii.
Profesorul va trezi interesul elevilor faţă de subiectul predat doar dacă în
primul rând el este (sau cel puţin se arată) interesat şi foloseşte orice mijloc de
a evidenţia faptul că ceea ce se învaţă în lecţia respectivă, este interesant,
valoros şi util în aplicaţii.

2. Profesorul trebuie să stăpânească subiectul


Este de la sine înţeles că orice metodă s-ar alege, orice mijloace s-ar folosi
în predare, profesorul nu va putea explica ceva ce nici el nu înţelege. Dacă un
profesor învaţă mecanic lecţia pe care va trebui s-o predea a doua zi fără s-o
înţeleagă, în primul rând este nesigur şi stresat. În al doilea rând nu poate
răspunde la întrebări. Chiar dacă încearcă, va folosi aceleaşi formulări ca în
momentul anterior, deci elevul cu siguranţă nu va înţelege nici această
explicaţie. Se poate întâmpla ca elevii să întrebe ceva ce are implicaţii în lecţiile
următoare. Nu se poate spune elevilor, "eu încă nu am învăţat lecţia în care se
tratează acest subiect". În funcţie de întrebare şi de nivelul general de
înţelegere, profesorul trebuie să se întoarcă la cunoştinţele predate anterior sau
trebuie să avanseze strictul necesar din cunoştinţe care se vor preda în viitor.
Dacă nu este stăpân pe întreaga materie care urmează a fi predată şi nu o
"simte" în totalitatea să ca pe ceva indivizibil, el va preda "bucăţele" care nu se
vor integra în cunoştinţele elevilor, vor rămâne "insule" de cunoştinţe fără
posibilitatea utilizării lor, deoarece va lipsi posibilitatea realizării conexiunilor.

3. Profesorul trebuie să ştie că cea mai bună metodă de a învăţa este de a


descoperi singur
În predarea informaticii profesorul trebuie să recurgă mai ales la metodele
active (bazate pe activitatea proprie a elevului în însuşirea anumitor concepte,
priceperi, deprinderi). Niciodată nu li se va interzice elevilor să încerce să
realizeze ceva "altfel" decât a planificat profesorul. Atunci când elevii prezintă
păreri proprii, care evident sunt rezultatul gândirii lor independente, profesorul
va trebui să fie foarte atent şi să conducă dialogul astfel încât elevul să simtă
permanent că ideile lui sunt ascultate, analizate şi valorificate. Profesorul
trebuie să sugereze, nu să impună. Chiar şi în situaţiile în care elevul emite o
părere despre care profesorul ştie imediat că este greşită, sau conţine elemente
greşite, acesta trebuie lăsat (cu excepţia unor situaţii rare) să-şi expună ideile,
iar aceste idei trebuie dezbătute până când elevul va descoperi singur că a
greşit. Nu se va "închide gura elevului", afirmând pur şi simplu că ceea ce zice
nu este corect. El are nevoie de argumente, dar nu de unele "comunicate".
Elevul va fi mulţumit dacă a înţeles ce anume a greşit, în caz contrar va fi extrem
de nedumerit.

4. Profesorul trebuie să încerce să descopere la elevi anticipările, dificultăţile,


să se transpună în situaţia elevului
În relaţia profesor-elev este clar că profesorul este cel care ştie şi elevul
cel care învaţă. Dar profesorul trebuie să cunoască fiecare elev, să fie exigent,
dar nu inaccesibil, să ţină cont de faptul că împărţirea elevilor în slabi şi buni
este convenţională. Profesorul trebuie să nu uite că are datoria permanentă să
găsească mijloacele potrivite care să-1 ajute să descopere lacunele fiecăruia
dintre elevii săi şi să dezvolte în mintea şi crezul fiecăruia încrederea că toate
cunoştinţele pe care trebuie să le acumuleze sunt accesibile tuturora, toţi le vor
putea însuşi.
Se poate întâmpla să apară surprize de genul că un elev cu note slabe la
alte discipline să fie bun la informatică sau invers. Elevii nu trebuie clasificaţi
după notele primite la alte discipline, dar nici după nota anterioară obţinută la
informatică. Aceste reguli sunt valabile pentru toţi elevii, atât pentru cei buni cât
şi pentru cei mai slabi. Aceste etichetări date elevilor de "buni" sau "slabi" nu
sunt recomandate. Există alte posibilităţi de a-i diferenţia: mai interesaţi, mai
pasionaţi, mai harnici, mai rapizi, mai originali. Se poate observa că toate
calificativele sunt pozitive. Se va evita să se spună: mai lereşi, mai proşti, sau
altele de genul acestora. Elevii nu vor simţi decât jignirea "aruncată" de
profesor, nici pe departe nu vor fi stimulaţi în învăţare. Mai mult, aceste moduri
de adresare se vor întoarce împotriva profesorului.

5. Profesorul trebuie să transmită nu numai informaţii dar şi priceperea de a


utiliza aceste informaţii
Acest sfat este foarte uşor de respectat din moment ce în informatică în
majoritatea cazurilor se porneşte de la o problemă care trebuie rezolvată. Chiar
şi în cazul utilitarelor se rezolvă probleme. A spune că o problemă poate fi
numai una de matematică sau de fizică este un concept fals. O problemă de
grafică, una de tehnoredactare, una de transmitere, de gestiune etc. poate
necesita o serie de cunoştinţe care se vor dobândi doar prin exersare, în infor-
matică cea mai inutilă activitate este de a preda ceva care nu are utilizare
imediată sau mai bine zis nu este impusă de dorinţa de a rezolva o problemă
(în termeni de informatică chiar o clasă de probleme).
Enunţul problemei precizează ce anume se dă şi ce anume se cere.
Înainte de "a sări pe problemă" şi a începe prezentarea rezolvării, precedată
eventual de predarea cunoştinţelor necesare acestei rezolvări, trebuie să
urmeze analiza problemei Aceasta cuprinde notarea formalizată a principalelor
elemente din problemă. Elevii vor fi dirijaţi să descopere care sunt
instrumentele necesare rezolvării problemei din cele pe care le cunosc deja, şi
care sunt acele puncte unde au nevoie de instrumente noi.

6. Profesorul trebuie să înveţe elevii să intuiască un adevăr sau existenţa unui


instrument informatic
Elevul trebuie dirijat spre descoperire, determinându-1 să formuleze un
algoritm sau să definească un model, o structură de date etc. Corectitudinea
alegerii va trebui s-o poată verifica, va trebui să înveţe să facă analogii, să
descopere diferenţe, să prevadă cazuri extreme. Elevul trebuie învăţat să
abstractizeze, să "dezbrace" enunţul problemei şi să caute, respectiv să
găsească metoda de rezolvare adecvată. Dacă el va atinge performanţa să
realizeze că nu are cunoştinţe necesare de a rezolva problema "elegant" şi să
formuleze presupunerea că trebuie să existe şi altă metodă mai eficientă
(eventual descoperită de alţii), el trebuie condus în gândirea lui astfel încât să
"redescopere" această metodă sau model, în cazul disciplinelor din domeniul
utilitarelor este remarcabil dacă elevul întreabă cum anume rezolvă utilitarul
studiat ceea ce urmează să realizeze aplicaţia respectivă.

7. Profesorul trebuie să înveţe elevii cum se demonstrează corectitudinea


soluţiei alese
Elevii trebuie învăţaţi să reformuleze un enunţ fără să-i schimbe
semantica, să argumenteze cu raţionamente logice paşii algoritmului proiectat,
să explice de ce au ales o metodă sau alta. Trebuie obişnuiţi să verifice
corectitudinea unui algoritm căutând contraexemple pentru care nu ar funcţiona
algoritmul, sau ar funcţiona mai puţin eficient. Trebuie învăţaţi să-şi optimizeze
algoritmii, chiar şi în cazul unei probleme de tehnoredactare.
Problema complexităţii unui algoritm este un concept care se învaţă greu
şi numai în cazul unor clase mai mari; dar şi elevii mai mici pot fi determinaţi să
numere câte operaţii execută un algoritm sau pot fi convinşi că o anumită parte
dintr-un algoritm nu are ce căuta în structura repetitivă (poate fi executată o
singură dată în afara structurii repetitive).

8. Profesorul trebuie să înveţe elevii să fie capabili să desprindă din mai multe
rezolvări un algoritm general
Cum în algoritmizare oricum se caută rezolvări pentru o clasă de
probleme, această cerinţă se îndeplineşte relativ uşor. Sunt şi situaţii în care
din reuniunea mai multor clase de probleme se conturează o clasă nouă. De
exemplu: algoritm de conversie din baza 2 în baza l0, algoritm de conversie din
baza 10 în baza 16, algoritm de conversie din baza 60 în baza 8. Reuniunea
lor va conţine problemele de conversie din orice bază în orice bază pentru care
se va căuta un algoritm cu valabilitate generală.
Atunci când se predă/învaţă metoda backtracking, se vor scoate în
evidenţă paşii având caracter general, care conduc la întocmirea unui algoritm
corect şi care pot constitui un mode! pentru rezolvarea altor probleme.
De asemenea, elevii trebuie învăţaţi să compună enunţuri de probleme
care se rezolvă pe baza modelului învăţat. Elevii din clasă, împreună cu
profesorul se vor juca cu aceste enunţuri, schimbând prima dată doar un
element din ele, apoi îmbogăţindu-le, schimbându-le cerinţele, sau adăugând
cerinţe suplimentare. O importanţă deosebită în acest proces are determinarea
elevilor să observe că anumite cerinţe se pot îndeplini, în paralel, în cadrul
aceleiaşi structuri de control sau subpogram cu o singură parcurgere a structurii
de date. Modularizarea nu înseamnă neapărat câte o procedură pentru fiecare
cerinţă.

9. Profesorul nu trebuie să prezinte elevului un conţinut care poate fi descoperit


de el
Gândirea elevului trebuie condusă astfel încât acesta să descopere singur
cât mai mult posibil, să nu aştepte ca profesorul să spună totul. Se vor pune
întrebări ajutătoare, cu răbdare, se vor da (mici) indicaţii, dar nu se va pune
totul pe tavă pentru că atunci elevii îşi pierd interesul şi se consideră bombardaţi
de cunoştinţe noi, neobservând cât de firesc se înlănţuiesc paşii algoritmului,
sau etapele în tehnoredactarea unui text.

10. Profesorul trebuie să fie un bun actor, un bun diplomat şi un bun prieten al
elevilor
Un profesor bun, de multe ori, se va preface (până la un moment dat) că
o soluţie propusă de elev este bună, lăsându-1 să descopere el greşeala.
Evident, este nevoie de diplomaţie, de siguranţă, altfel elevul nu realizează că
profesorul a ştiut de la bun început că soluţia corectă este diferită de ceea ce a
prezentat el.
Profesorul nu are voie să-şi etaleze supărările, nu are voie să-şi verse
nervii pe elevi, nu are voie să-şi bârfească colegii (profesori), chiar dacă elevii
au avut dreptate. Din nou este nevoie de diplomaţie şi de talent (actoricesc
uneori).
Profesorul trebuie să-şi rezolve problemele cu elevul sau cu clasa pe cât
se poate între patru ochi. Numai în situaţii grave de abateri va apela la
conducerea şcolii sau la diriginte. Legătura cu familia de asemenea este o
problemă de diplomaţie.
Mulţi profesori consideră că atunci sunt prieteni cu elevii dacă le permit o
serie de lucruri interzise de alţii. Dar adevărata prietenie profesor-elev există
doar atunci când profesorul îi învaţă pe elevi tot ce ştie el, uneori "îi învaţă şi
mai mult", perfecţionându-se tot timpul. Profesorul depăşit de unii elevi
pasionaţi, olimpici sau care cunosc un utilitar în detaliu nu trebuie să se
ofenseze, dimpotrivă trebuie să constituie un stimulent. Un profesor de
informatică trebuie să ţină pasul cu ce apare nou în informatică cel puţin la
nivelul cerinţelor învăţămintului. Dar există şi posibilitatea ca elevii să întrebe
ceva ce "nu este în programă". Pe măsura timpului disponibil şi a complexităţii
răspunsului este recomandabil ca profesorul să se documenteze şi să
răspundă acestor întrebări în loc să refuze răspunsul sau să dea un răspuns
confuz.
Elevii în şcoală ar trebui să fie învăţaţi să devină oameni în sensul filosofic al
cuvântului. Evident există activităţi educative care se planifică în scopul
realizării acestui obiectiv. Dar şi de-a lungul orelor de informatică se pot ivi
diferite oportunităţi care pot fi fructificate din punct de vedere educativ cu
succes. Nu este nevoie ca profesorul să povestească elevilor istoria vieţii lui,
sau să comenteze programul de la TV în ora de informatică. Sunt totuşi anumite
momente în care din dorinţa de a fi cât mai credibil este nevoie de câte-un
exemplu din propria viaţă. [4, 5, 6, 7, 8, 9]
Bibliografie

[1.] Dorian Stoilescu, Manual de C/C++ pentru licee, Editura Radial, Galati,
1998, ISBN 9739833703
[2.] Dr. Jamsa, Kris, Klander, Lars, Totul despre C şi C++. Manualul
fundamental de programare în C şi C++, Editura Teora, Bucureşti, 2002;
[3.] Doina Hrinciuc Logofătu, C++. Probleme rezolvate şi algoritmi, Editura
Polirom, 2001;
[4.] Clara Ionescu, Internet: instrument de bază în procesul de predare şi
învăţare în Restructuring of the (re)training of schoolteachers in Computer
Sciences, TEMPUS S_JEP 11168-96, Editura Computer Libris Agora, 1997
[5.] Clara Ionescu, Metodica predării informaticii, Universitatea “Babeş- Bolyai”,
Cluj, 1999 – curs litografiat
[6.] Carmen Petre, Daniela Popa, Ştefania Crăciunoiu, Camelia Ilieşu, Metodica
predării Informaticii şi Tehnologiei Informaţiei, Editura Arves, Craiova, 2002,
ISBN 9738533198
[7.] Cristian Masalagiu, Ioan Asiminoaei. Didactica predării informaticii, Ed.
Polirom, 2004.
[8.] Cristian Masalagiu, Ioan Asiminoaei, Ion Maxim, Metodica predării
informaticii, Ed. MatrixRom, Bucuresti, 2001, ISBN: 9736852180
[9.] Adrian Adascalitei, Instruire asistata de calculator. Didactica informatica,
Editura Polirom, 2007, ISBN: 978-973-46-0687-0
[10.] T. H. Cormen, C. E. Leiserson, R. L. Rivest – Introduction to Algorithms,
M.I.T. Press, 1990
[11.] Adrian Runceanu, Programare orientată pe obiecte, Editura Academica
Brâncuşi, Târgu-Jiu, 2007, ISBN (13) 978-7637-89-5
[12.] Adrian Runceanu, Programare orientată pe obiecte - limbajul C++.
Laborator, Editura Academica Brâncuşi, Târgu-Jiu, 2008, ISBN 978-973-144-
109-2
[13.] Adrian Runceanu, Tehnici de programare - îndrumar de laborator, Editura
Academica Brâncuşi, Târgu-Jiu, 2002, ISBN 973-85805-7-9
[14.] Adrian Runceanu, Programarea şi utilizarea calculatoarelor, Editura
Academica Brâncuşi, Târgu-Jiu, 2003, ISBN 973-8436-44-3
[15.] Adrian Runceanu, Mihaela Runceanu, Notiuni de programare – limbajul
C++, Editura Academica Brâncuşi, Târgu-Jiu, 2012, ISBN 978-973-144-550-2
[16.] R.F. Mager, Goal Analisys, Fernon, 1972
[17.] P. Lisievici, Evaluarea in invatamant. Teorie, practica, instrumente, Editura
Aramis, 2002
[18.] http://www.runceanu.ro/adrian/pa2015 accesat iulie 2015
[19.] http://www.runceanu.ro/adrian/poo2013 accesat octombrie 2014
Despre autori

Mihaela Runceanu (n. 1968) este profesor de informatică, gradul


didactic I, la Colegiul Naţional „Ecaterina Teodoroiu” din Târgu-
Jiu. Este absolventă a facultăţii de Matematică şi Informatică,
Universitatea „Babeş-Bolyai”, Cluj-Napoca, licenţiată în
matematică (1992) şi informatică (1999). A mai publicat:
1) Bacalaureat la informatică. Noţiuni recapitulative. Teze
rezolvate şi probleme propuse (în colectiv), Editura L&S Infomat,
Bucureşti, 2001
2) Culegere de probleme de informatică – variantele Pascal şi C++ (în colaborare cu
Carmen Negrea), Editura Donaris, 2003
3) Atestat la informatică (în colaborare cu Adrian Runceanu), Editura Axioma
Teomsnic, Târgu-Jiu, 2004
4) Informatică, modele de rezolvare – bacalaureat 2008 (în colectiv), Editura Little
Lamb, 2008
5) Baze de date – o abordare Visual Foxpro, (în colaborare cu Adrian Runceanu),
Editura Academica Brâncuşi, Târgu-Jiu, 2009
6) Tehnologii si aplicatii web – îndrumar de laborator, (în colaborare cu Mihaela
Runceanu), Editura Academica Brâncuşi, Târgu-Jiu, 2009
Are o remarcabilă activitate de pregătire a elevilor pentru performanţă, concretizată în
numeroare premii obţinute la fazele naţionale ale olimpiadelor de informatică şi la
concursurile de programare.
Incepand cu anul 2010 este colaborator cu Adobe Foundation si cu iEARN, doua
institutii educationale importante din SUA, pentru care desfasoara activitati ca Lead
Educator si facilitator al cursului Adobe Youth Voices "Create with Purpose".
In august 2011 a participat la Summit-ul Adobe Youth Voices organizat de Adobe
Foundation in California.

Adrian Runceanu (n. 1968) este lector universitar doctor la


Universitatea Constantin Brâncuşi din Târgu-Jiu, Facultatea de
Inginerie, Departamentul de Automatică, Energie şi Mediu. Este
licențiat în specialitatea Informatică (1995), al Facultăţii de
Matematică-Informatică din cadrul Universităţii din Craiova. În
anul 2009 a susținut teza de doctorat cu titul “Algoritmi de
creștere a vitezei de transfer a informației în bazele de date
distribuite”, în domeniul Știința calculatoarelor, la Facultatea de
Automatică, Calculatoare și Electronică din cadrul Universităţii
din Craiova. A mai publicat:
1) Bacalaureat la informatică. Noţiuni recapitulative. Teze rezolvate şi probleme
propuse (în colectiv), Editura L&S Infomat, Bucureşti, 2001
2) Tehnici de programare - îndrumar de laborator, Editura Academica Brâncuşi, Târgu-
Jiu, 2002
3) Metode şi tehnici de programare. Limbajul C++ - îndrumar de laborator, Editura
Academica Brâncuşi, Târgu-Jiu, 2003
4) Programarea şi utilizarea calculatoarelor, Editura Academica Brâncuşi, Târgu-Jiu,,
2003
5) Atestat la informatică, (în colaborare cu Mihaela Runceanu), Editura Axioma
Teomsnic, Târgu-Jiu, 2004
6) Internet şi Intranet. Teorie şi aplicaţii, Editura Academica Brâncuşi, Târgu-Jiu, 2005
7) Programare orientată pe obiecte, Editura Academica Brâncuşi, Târgu-Jiu, 2007
8) Baze de date – Visual Foxpro 6.0 – îndrumar de laborator, (în colaborare cu Marian
Popescu), Editura Academica Brâncuşi, Târgu-Jiu, 2007
9) Programare orientată pe obiecte-limbajul C++. Laborator, Editura Academica
Brâncuşi, Târgu-Jiu, 2008
10) Baze de date – o abordare Visual Foxpro, (în colaborare cu Mihaela Runceanu),
Editura Academica Brâncuşi, Târgu-Jiu, 2009
11) Tehnologii si aplicatii web – îndrumar de laborator, (în colaborare cu Mihaela
Runceanu), Editura Academica Brâncuşi, Târgu-Jiu, 2009
12) Grafică asistată de calculator. Teorie şi aplicaţii, Editura Academica Brâncuşi,
Târgu-Jiu, 2009
13) Inițiere în programarea orientată pe obiecte în limbajul C++, Editura Digitala, 2016
– varianta digitala a cartii Programare orientată pe obiecte, Editura Academica
Brâncuşi, Târgu-Jiu, 2007 http://www.smashwords.com/books/view/616145

Domeniile de cercetare sunt legate de baze de date distribuite, programare web,


programarea calculatoarelor și e-learning.
Tine legatura cu Mihaela-Ana Runceanu

Multumim pentru citirea acestei carti! Urmareste in continuare activitatea acestui autor
prin canalele sociale de mai jos.

Facebook: http://www.facebook.com/adrianrunceanu
LinkedIn: https://ro.linkedin.com/in/mihaela-runceanu-66762416
Site: http://www.runceanu.ro/mihaela/

Tine legatura cu Adrian Runceanu

Multumim pentru citirea acestei carti! Urmareste in continuare activitatea acestui autor
prin canalele sociale de mai jos.

Facebook: http://www.facebook.com/adrianrunceanu
Research Gate: http://www.researchgate.net/profile/Adrian_Runceanu/
LinkedIn: http://ro.linkedin.com/in/adrianrunceanu
Site: http://www.runceanu.ro/adrian/

View publication stats

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