Sunteți pe pagina 1din 69

Contents

1. Tipuri de date simple si structurate. (enumerare, caracteristici exemple in limbaje procedurale)


3
Date simple.............................................................................................................................................3
Date structurate.....................................................................................................................................5
2. Structura de tablou..............................................................................................................................7
3. Liste (stive, cozi, algoritmi de manevră)...........................................................................................7
4. Liste (simplu înlănţuite, dublu înlănţuite, algoritmi de manevră)...............................................12
5. Parcurgerea grafurilor în adâncime şi în lăţime............................................................................22
6. Parcurgerea arborilor binari.............................................................................................................26
7. Algoritmi de căutare. Căutare secvenţială, căutare binară.........................................................27
8. Structuri fundamentale şi derivate în programarea procedurală................................................28
9. Subprograme (definire, tipuri de transfer al parametrilor, apelare, variabile locale şi globale).30
10. Recursivitate...................................................................................................................................32
11. Noţiunile de bază ale programării obiectuale: clasă, metodă.................................................32
12. Proprietăţile claselor şi ale metodelor.........................................................................................33
13. Structuri de control în Visual Basic. Elementele programării vizuale....................................34
14. Noţiunile de control, proprietate, eveniment în programarea vizuală....................................36
15. Buton de comandă (Button) şi butoane de opţiune (RadioButton)........................................36
16. Casetă de text (TextBox), casetă de validare (CheckBox)......................................................36
17. Liste simple (ListBox) şi liste combinate (ComboBox) în Visual Basic..................................38
18. Crearea şi utilizarea hiperlegăturilor HTML...............................................................................38
19. Formulare HTML............................................................................................................................39
20. Tipuri de formatare CSS- creare şi apelare, exemple..............................................................40
21. Exemple de utilizare a funcţiilor Javascript................................................................................41
22. Definiţia clasică a probabilităţii.....................................................................................................41
23. Scheme probabilistice clasice......................................................................................................42
24. Conceptul de distribuţie (repartiție).............................................................................................42
25. Generarea numerelor aleatoare..................................................................................................43
26. Problema celui mai scurt drum în grafuri. Algoritmul lui Dantzig............................................43
27. Problema fluxului maxim în reţele. Algoritmul Ford-Fulkerson...............................................46
28. Rezolvarea sistemelor algebrice liniare – metode directe.......................................................47
29. Rezolvarea sistemelor algebrice liniare – metode iterative.....................................................47
30. Rezolvarea numerică a problemelor algebrice de valori şi vectori proprii............................47
31. Aproximarea funcţiilor prin polinoame. Polinom Lagrange de interpolare............................47
32. Aproximarea funcţiilor prin polinoame. Polinom Newton de interpolare...............................47
33. Generarea de conţinut HTML folosind PHP...............................................................................47
<?php..........................................................................................................................................................47
34. Utilizarea în PHP a datelor din formulare HTML. Metodele PUT şi GET..............................47
35. Utilizarea sistemului PHPMyAdmin.............................................................................................48
36. Interogări simple SQL, apelabile din PHP..................................................................................48
37. Metoda Greedy. Exemple.............................................................................................................49
38. Metoda Backtracking. Exemple...................................................................................................49
39. Metoda Divide et Impera. Exemple.............................................................................................50
40. Operaţii cu structuri dinamice de date (liste, arbori).................................................................51
41. Aspecte fundamentale relative la SGBD: concept, obiective, funcţii, clasificare, arhitecturi51
42. Algebra relaţională.........................................................................................................................55
43. SGBD relaţionale: caracteristici, componente, arhitectură, mecanisme de optimizare......56
1
44. Normalizarea bazelor de date......................................................................................................57
45. Limbajul SQL..................................................................................................................................58
46. Elementele unei baze de date Oracle.........................................................................................59
47. Limbajul PL/SQL. Elementele acestuia......................................................................................60
48. Algoritmi numerici paraleli. Metode de rezolvare a sistemelor de ecuaţii liniare.................61
Algoritmi numerici paraleli. Metode de rezolvare a ecuaţiilor neliniare............................................61
49. Scopul Inteligenţei Artificiale. Definiţii, abordări, aplicaţii.........................................................65
50. Metode de căutare în spaţii de soluţii: căutare neinformată, căutare informată..................66
51. Demonstrarea automată...............................................................................................................67
52. Sisteme inteligente. Sisteme multiagent. Metaeuristici. Exemple..........................................67
53. Gramatici generative pentru o submulţime a limbii române. Implementare în PROLOG.
Utilizarea listelor în PROLOG. Exemple................................................................................................68
54. Definirea unor predicate PROLOG pentru transformarea numerelor din scrierea cu cifre în
scrierea cu litere........................................................................................................................................69
55. Alte aplicaţii ale limbajului PROLOG pentru prelucrarea limbajului natural..........................71

2
1. Tipuri de date simple si structurate. (enumerare, caracteristici exemple in limbaje
procedurale)

Data este forma de reprezentare accesibilă a informației prelucrate. Ea reprezintă suportul


formal al informației, care se concretizează în: cifre, litere, simboluri, coduri și alte însemne. Există o
corespondență determinată între informație, simbol și dată astfel că, foarte adesea, în practică,
termenul de informație este utilizat pentru a desemna date, iar expresia „prelucrarea informațiilor”
înlocuiește expresia „prelucrarea datelor”. Putem considera că datele prelucrate, în măsura în care
afectează în sens pozitiv comportamentul receptorilor (oameni sau mașini), au calitatea de
informații.

Date simple

Un tip de date specifică (precizează) mulţimea de valori pe care variabila respectivă le poate lua
cât şi setul de operaţii pe care programatorul le poate efectua cu acea variabilă. Orice variabila
trebuie sa fie asociata unui tip de date si numai unuia.
o char
variabilă de tip char reţine un singur caracter Exemple: ‘A’, ’a’, ’%’, etc.
Se reprezintă în memoria calculatorului folosind 8 biţi (un octet) şi poate păstra valori cuprinse
între –128 şi 127. Dacă se declară fără semn (adică se utilizează modificatorul unsigned), intervalul
de valori se întinde de la 0 la 255. Programatorii pot atribui valori de tip caracter unei astfel de
variabile în două modalităţi distincte, dar care acţionează identic. Astfel se poate folosi
reprezentarea din ASCII (codul numeric al caracterului respectiv), sau caracterul respectiv între
două apostrofuri.
Exemplu:
char litera_mica=97;
sau char litera_mica=’a’;

o int reţine numere întregi cu semn Exemple: 23, -45, 0, etc.


Se reprezintă în memoria calculatorului folosind 16 biţi (2 octeţi) şi poate păstra valori cuprinse
între – 32768 şi 32767. Dacă se declară fără semn (adică se utilizează modificatorul unsigned),
intervalul de valori se întinde de la 0 la 65535.
Exemplu:
int a=9;
int b=6725;
int c=-31567;

o float reţine numere reale în format cu virgulă mobilă, în simplă precizie Exemple: 7.8965,
-4.123, 7.0, etc.
Se reprezintă în memoria calculatorului folosind 32 biţi (4 octeţi) şi poate păstra valori cuprinse
între 3.4E-38 şi 3.4E+38.
Exemplu:
float x=9.789;
float y=-6725.123;
float z=-3156723;

3
o double reţine numere reale în format cu virgulă mobilă, în dublă precizie Exemple:
123456789.89654321, -123456789.1234567890, 123456789.0, etc. (se utilizează când se
prelucrează numere foarte mari sau foarte mici)
Se reprezintă în memoria calculatorului folosind 64 biţi (8 octeţi) şi poate păstra valori cuprinse
între 1.7E-308 şi 1.7E+308.
Exemplu:
double n_foarte_mare=123456789123456789.123456789123456789;
double n_foarte_mic=-123456789123456789.123456789123456789;

o void este tipul de dată vidă (fără tip specificat), utilizat în general pentru mărirea clarităţii
programelor. Tipul void permite explicitarea faptului că o funcţie nu returnează nimic sau nu
are nici un parametru.
Exemplu:
void salut(void)
{
cout<<“SALUTAM PROGRAMATORII IN LIMBAJUL C++ !!!“<<endl;
}

o boolean
Domeniul tipului de dată boolean are numai două valori: true şi false. Există cinci operații
definite pe acest tip: and, or, not, imp (implicația logică) şi equiv (echivalența logică). Limbajul
C consideră orice şir biți ce conțin numai 0 ca false, respectiv true orice şir de biți între care este
unul nenul. Operanzii de tip boolean se folosesc la formarea expresiilor logice, cu ajutorul
operatorilor logici.

o pointer
Tipul de date pointer are domeniul format din adresele altor entități (reprezentabile în memorie)
dintr‐un program. Variabilele pointer constituie o alternativă de accesare a entităților din memoria
unui program, prin intermediul unui aşa numit mecanism de indirectare. Un pointer care nu referă
nimic are valoarea echivalentă cu 0 (pointer null); în caz contrar, valoarea sa este adresa
entității respective, iar informația de tip al pointerului exprimă şi tipul entității referite de pointer.
Operațiile asupra tipurilor pointer sunt:
• * (indirectarea) *p are ca rezultat obiectul de tip T referit de p dacă p este de tipul pointer la
T.
• & (adresa lui) &p are ca rezultat obiectul de tip pointer la T (T fiind tipul lui p) care referă pe
p, deci cu alte cuvinte, adresa lui p.
• ++, ‐‐ incrementarea şi decrementarea valorilor de tip adresă.
• Operații de comparare
• Operatorii new şi delete (doar în C++) – pentru alocarea şi eliberarea variabilelor
dinamice referite de pointeri.

o şir de caractere (numit şi string)


În limbajul C nu există tipul şir de caractere predefinit (cum este în alte limbaje tipul string),
dar şirurile de caractere pot fi prelucrate, reprezentarea lor fiind convenţională (masive
unidimensionale cu elemente de tipul char). Şirurile de caractere se reprezintă intern printr-o
succesiune de octeţi în care sunt memorate codurile ASCII ale caracterelor şirului. Ultimul octet
conţine caracterul NULL şi marchează sfîrşitul şirului. Pentru memorarea unui şir de n caractere

4
sunt necesare n+1 octeţi. Marcatorul de sfîrşit nu face parte din şir şi este tratat ca atare de funcţiile
care lucrează cu şiruri de caractere.
Valorile şir de caractere sunt compuse din zero sau mai multe caractere precizate între
ghilimele.
Tipul şir de caractere are ca valoare un şir de caractere cu lungimea variabilă (modificabilă
dinamic). Lungimea şirului de caractere este numărul de caractere conținut în el. Operațiile
care se pot efectua cu şiruri de caractere sunt: construirea, inserarea unui şir de caractere în
altul, extragerea unui subşir, ştergerea unui subşir, căutarea unui subşir, concatenarea a
două şiruri de caractere. Acest tip de date s‐a impus din cel puțin două motive:
imposibilitatea accesării globale a unui tablou de caractere precum şi rigiditatea utilizării tablourilor
statice (de dimensiune fixată). Astfel, pentru tipul tablou sunt definite doar operațiile de
atribuire şi test de egalitate; pentru tipul şir de caractere sunt necesare în plus operațiile de
intrare/ieşire şi cele specificate mai sus. Prin aceste operații, lungimea şirului de caractere se
poate modifica, prin urmare o reprezentare fixă (pe număr prestabilit de caractere) nu este
adecvată
Tratarea şirurilor de caractere se poate face folosind declarația de tablou: char [n] (sau char [])
Indicii acestor tablouri încep cu 0, iar reprezentarea se face în convenția C. Pentru a prelucra
şiruri de caractere folosim funcții din biblioteca standard C: strcpy, strcmp, strstr, strchr, strlen
etc.

Date structurate

Tipul tablou (masiv)


Masivul este o structură de date omogenă, cu acces direct la elementele sale. În limbajul C
un masiv se declară folosind o construcţie de forma: tip nume[d1][d2]…[dn]; unde tip este tipul
comun elementelor masivului iar d1, d2, dn sunt expresii constante (care pot fi evaluate la
compilare) care indică numărul de elemente de pe fiecare dimensiune. Se acceptă oricîte
dimensiuni, cu condiţia ca structura în ansamblul ei să nu depăşească 64Ko.
Exemple:
int b[10]; /* vector cu 10 componente intregi*/
float a[10][20]; /* matrice cu 10 linii si 20 coloane */

O structură de tip masiv este memorată, ca şi în Pascal, lexicografic (pe linii). La declararea
masivelor se poate face şi iniţializarea lexicografică a acestora. Numărul valorilor care se
iniţializează trebuie să fie mai mic sau egal cu numărul maxim al elementelor masivului. În cazul în
care se face iniţializarea integrală a masivului, dimensiunile a căror valoare nu intră în generarea
funcţiei rang pot lipsi.
Exemple:
int b[10]={2,3,0,5,6,7,3,6,8,5}; /*vectorul contine valorile 2 3 0 5 6 7 3 6 8 5*/
int b[10]={2,3,0,5,6,7,3,6,8,5,6}; /*se va semnala eroare la compilare, deoarece sunt
mai multe valori pentru initializare*/
int b[10]={2,3,0,5,6,7}; /* vectorul contine valorile 2 3 0 5 6 7 0 0 0 0*/
int b[]={1,2,3,4,5,6,7,8,9,0}; /*se rezerva spatiu pentru 10 elemente, care sint
initializate cu valorile 1,2,3,4,5,6,7,8,9,0*/
float a[5][3]={{1,2,3},{1,2,3},{1,2,3}}; /* matricea contine valorile 1 2 3 1 2 3 1 2 3 0 0 0
0 0 0*/
float a[5][3]={{1,2},{1,2,3},{1}}; /* matricea contine valorile 1 2 0 1 2 3 1 0 0 0 0 0 0 0
0*/
5
Enumerare
Cuvantul cheie enum se foloseste pentru a defini enumeratii
Tipul enumerare permite programatorului să folosească nume sugestive pentru valori
numerice.
• Ca exemplu, pentru denumirea unei luni din an, ianuarie poate fie asociat cu valoarea 1,
februarie asociat cu valoarea 2, etc.
• Tipul enumerare este folosit atunci când nu se vrea utilizarea unor numere întregi
succesive, ci a unor simboluri asociate
Tipul enumerare este un tip întreg distinct ce are constante cu nume. Numele său devine
un aşa numit nume‐enumerare, care este cuvânt rezervat în domeniul de vizibilitate propriu.
Identificatorii dintr‐o listă enumerare sunt declarați constante şi pot apare oriunde pot apare
constante. Dacă nu apar enumeratori cu ‘=’, valorile respectivelor constante încep de la 0 şi cresc
cu 1, de la stânga la dreapta. Un enumerator cu ‘=’ va da identificatorului valoarea indicată, care
rămâne ca valoare de start pentru următorii enumeratori. Valoarea unui enumerator trebuie să fie de
tip int sau de tip ce se poate converti la int. Numele enumeratorilor trebuie să fie distincte de cele
ale variabilelor ordinare sau ale altor enumeratori în acelaşi domeniu de vizibilitate.
De exemplu:
enum culori = {rosu, orange, galben, verde, albastru};
enum fruct = {mar, para, orange, kiwi}; // eroare: orange este redefinit
enum pasare = {strut, dodo, lebada, kiwi}; // eroare kiwi este redefinit
int lebada; // eroare: lebada redefinit
Valorile enumeratorilor nu trebuie să fie distincte. Un enumerator este considerat că se
defineşte după ce s‐a citit numele (şi eventual inițializatorul, dacă există). De exemplu:
enum { a, b, c = 0}; enum {d, e, f = e + 2}; defineşte a, c, d cu valoarea 0, b şi e cu valoarea 1 şi f
cu 3. Fiecare enumerator defineşte un tip întreg diferit de toate celelalte tipuri întregi. Tipul
unui enumerator este enumerarea sa.
Enumerarea este ansamblu de constante întregi asociate câte unui identificator; implicit, sirul
valorilor e crescator cu pasul 1, iar prima valoare e 0;
Exemplu:
int ore_lucru[7];
enum zile_sapt {D, L, Ma, Mc, J, V, S} zi;
for (zi = L; zi <=V; zi++)
ore_lucru[zi] = 8;

Structura

Este o colectie de valori de tipuri diferite grupate conform unei ierarhii.


Datele elementare ale unei structuri pot fi izolate (singulare) sau tablouri;
Fiecare structură reprezintă un tip nou de date, definit de utilizator.
declaratie:
struct [id_tip] {
tip_camp_1 id_camp_1; tip_camp_2 id_camp_2; ... tip_camp_n id_camp_n;
} [lista_identificatori_de_tip_struct];

Daca id_tip lipseste, structura se numeste anonima;


daca lista_identificatori_de_tip_struct lipseste dar are id_tip, se pot defini ulterior variabile de tipul
structurii prin:

6
struct <id_tip> <lista_identificatori_de_tip_struct>
Exemplu:
struct student {
char cnp[13];
char nume[15], prenume[15];
int varsta;
float medie_an[5]; } student1, student2;
struct student student3;
pentru a referi un membru al unei variabile de tip struct de foloseste „.”

2. Structura de tablou
Tabloul este o colecție de date în care fiecare element poate fi identificat pe bază unui index,
colecția asigurând timp de acces constant pentru fiecare element. Prin reprezentarea tabloului t se
înțelege plasarea elementelor în locații succesive de memorie, indexarea uzuală a elementelor
tabloului în majoritatea limbajelor de programare începând cu 0…n unde n este dimensiunea
tabloului (în sensul numărului de componente)
Locațiile de memorie pot fi numerotate, putând accesa direct orice element. Timpul de
accesare al elementului 1, de exemplu, fiind același cu timpul de accesare al elementului n.
Funcție de dimensiunea tablourilor (în sensul numărului de indici folosiți pentru
indexarea unui element) o clasificare a acestora ar cuprinde:
 tablouri unidimensionale: vectori
 tablouri bidimensionale: matrice
 tablouri tridimensionale, multidimensionale: masive.

3. Liste (stive, cozi, algoritmi de manevră)


Stiva
O stivă este un tip de dată ale cărui operaţii de inserare şi de ştergere păstrează regula:
ultimul - venit - primul - ieșit
LIFO (Last-In-First-Out)
Astfel, într-o stivă pot fi adăugate sau şterse elemente doar în vârful stivei.

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)
- informaţia de legătură (care este un pointer ce conţine adresa elementului precedent din
stivă – notat cu leg).

Tipul de date necesar implementării dinamice a structurii de tip stivă este:

7
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.
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 întrun 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.
Operaţiile ce se pot efectua asupra stivei
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:
a) Se alocă memorie pentru noul element;
b) Se iniţializează zona de informaţie propriu-zisă (utilă) a acestuia ;
c) 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;
d) Se actualizează variabila vf cu adresa noului element alocat.
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)
}

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 elemental din vârful stivei.
Operaţia se efectuează astfel:
a) Într-un pointer de lucru notat p, se reţine adresa elementului din vârful stivei;
b) În variabila q se extrage elementul din vârful stivei;
c) Adresa elementului următor celui din vârful stivei devine adresa noului vârf al stivei;
d) Se eliberează memoria ocupată de elementul care a fost anterior în vârful stivei.

8
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; //c)
delete p; //(d)
}

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;
}

Coada
O structură de date care respectă regula FIFO se numeşte coadă.
FIFO (First In First Out)
Primul-intrat-primul-iesit
Pentru a respecta această regulă, vom efectua adăugarea în coada listei, iar extragerea din
capătul cozii.
O coadă este un tip de date cu operaţii caracteristice comportării primul venit / primul servit.
Elementul care poate fi servit 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.
Î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 legătură are valoarea
NULL.

9
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 structurii de tip coadă poate arăta în felul următor:

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 Creare_vida (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 efectuează 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:
a) Alocarea unei zone de memorie pentru noul element
b) Se introduce informaţia utilă pentru acest element
c) Informaţia de legatură a elementului creat se completează cu NULL
d) Se reiniţializează informaţia de legatură a elementului indicat de ultim cu adresa
noului element
e) Se modifică valoarea pointerului ultim dându-i ca valoare adresa noului element
introdus

void adaug(tip x, TNOD *ultim)


{
TNOD *p; // pointer de lucru
if (prim==NULL)

10
{
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ă:
a) Se reţine într-o variabilă (*q) informaţia utilă din primul element al cozii
b) Se reţine într-un pointer de lucru adresa acestui element (să numim pointerul de lucru
p)
c) Se actualizează valoarea pointerului prim cu adresa următorului element din coadă
d) Se eliberează zona de memorie ce fusese alocată iniţial primului element din coadă
(acum indicat de pointerul p)
void extrag(TNOD *prim, tip *q)
{
TNOD *p; // pointer de lucru
*q=prim->inf; // (a)
p=prim; // (b)
11
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;
}

4. Liste (simplu înlănţuite, dublu înlănţuite, algoritmi de manevră)

Lista simplu înlănțuită reprezintă o structură de date constituita dintr-o serie de noduri legate intre
ele. Fiecare din noduri conține doua valori: datele și o referință către nodul următor.

 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.
 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.

12
 Accesul imediat la fiecare nod din mulţime nu este necesar pentru că fiecare nod conduce la
un altul.

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 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)
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
*/

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 liste
A. Adăugarea unui element la începutul listei se poate reprezenta grafic astfel:

13
Etapele adăugarii unui element la începutul listei:
a) alocarea zonei de memorie necesare noului element (Se foloseşte un pointer de lucru
p)
b) completarea informaţiei utile pentru noul element (notată cu nou)
c) 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)
d) Actualizarea variabilei referinţă prim cu adresa elementului creat, care în acest
moment devine primul element al listei
void adaug_la_inceput( tip x, LISTA *prim ) // x este informatia ce se adauga
{
LISTA *p; // pointerul de lucru
p=new LISTA; // (a)
p->inf=x; // (b)
p->leg=prim; // (c)
prim=p; // (d)
}
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:


a) Alocarea zonei de memorie necesară pentru noul element
b) Completarea informaţiei de legătură a elementului creat cu NULL, deoarece el va
deveni ultim element
c) Completarea informaţiei utile
d) 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)
e) Se actualizează pointerul ultim cu adresa nodului adăugat listei

void adauga_la_sfarsit( tip x, LISTA *ultim ) // adaugă valoarea x la sfarşitul listei


{

14
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 adaug_la_sfarsit.
Sunt necesari doi pointeri de lucru:
1. q – indică nodul după care este facută inserarea
2. 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:
a) alocarea zonei de memorie necesară noului element (folosirea pointerului p)
b) iniţializarea informaţiei utile ( cu valoarea notată nou )
c) iniţializarea informaţiei de legătură cu adresa următorului nod (cu adresa
reţinută în acest moment în variabila q->leg)
d) actualizarea informaţiei de legatură din nodul după care s-a inserat noul
element cu adresa zonei de memorie alocată pentru acesta (p)

void adaug_dupa_o_valoare( 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.

15
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)

void adaug_inainte_de_o_valoare( 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)
}
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 notat 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.
Afişarea elementelor listei pentru exemplificarea procedurii de parcurgere a listei:
void parcurgere ( LISTA *prim )
{
LISTA *p;
p=prim;
while (p!=NULL)
{
cout<inf;
p=p->leg;
}
}

16
Listele dublu înlănțuite sunt structuri de date dinamice omogene. Ele au aceleași
caracteristici de bază ca și listele simplu înlănțuite. Diferența față de acestea constă în faptul că,
pentru fiecare nod, se reține și adresa elementului anterior, ceea ce permite traversarea listei în
ambele direcții.
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.

Fiecare element al unei liste dublu înlănţuite are două câmpuri de legătură:
– ant – adresa nodului anterior din listă
– 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ă
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.

17
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:
1.iniţializarea listei
2.adăugarea unui element: – la începutul listei – la sfârşitul listei – în interiorul listei
3.căutarea unei valori
4.parcurgerea listei
5.ş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 presupune modificarea variabilei de tip
referinţă ce indică primul element al listei şi este efectuată respectând următorii paşi:
a) alocarea zonei de memorie necesare noului element (Se foloseşte un pointer
de lucru p);
b) completarea informaţiei utile pentru noul element;
c) 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);
d) completarea câmpului ant cu valoarea NULL, deoarece nodul adăugat va fi
primul nod al listei şi nu va avea predecesor;
e) Actualizarea variabilei referinţă prim cu adresa elementului creat, care în acest
moment devine primul element al listei;

void adaugi( tip x, LISTA *prim) // x - 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->ant=p; // (e)
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:
18
a) Alocarea zonei de memorie necesară pentru noul element;
b) Completarea câmpului urm al elementului creat cu NULL, deoarece el va
deveni ultimul element al listei;
c) Completarea câmpului ant al elementului creat cu adresa ultimului nod al listei
(care va deveni penultimul);
d) Completarea informaţiei utile;
e) 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);
f) Se actualizează pointerul ultim cu adresa nodului adăugat listei;

void adaugs(tip x, LISTA *ultim) // 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:
a) alocarea zonei de memorie necesare noului element (folosirea pointerului p);
b) iniţializarea informaţiei utile;
c) iniţializarea câmpului urm al noului nod cu adresa nodului ce urmează în listă
după nodul indicat de q;
d) iniţializarea câmpului ant al noului nod cu valoarea q (nodul ce va precede noul
nod);

19
e) actualizarea câmpului urm din nodul după care s-a inserat noul element cu
adresa zonei de memorie alocată pentru acesta (p);
f) actualizarea câmpului ant al lui q->urm cu adresa nodului creat;

void adaug_dupa( 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)
q->urm->ant=p; // (f)
}

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 adaug_inainte(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. a) parcurgerea de la primul catre ultimul nod
void parcurgere1 ( LISTA *prim)
{
LISTA *p;
p=prim;
while (p!=NULL)
{
prelucrare(p->inf); // o operaţie asupra informaţiei din listă
p=p->urm;
}
}
b) parcurgerea de la ultimul nod către primul:

20
void parcurgere2 ( LISTA *ultim)
{
LISTA *p;
p=ultim;
while (p!=NULL)
{
prelucrare(p->inf);
p=p->ant;
}
}

D. Ş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 element al 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;
}
}

5. Parcurgerea grafurilor în adâncime şi în lăţime


Se numeşte graf neorientat o pereche ordonatã de mulţimi (X,U), X fiind o mulţime finitã şi nevidã
de elemente numite noduri sau vârfuri, iar U o mulţime de perechi neordonate din X, numite muchii.
Parcurgerea grafului reprezintă operaţia prin care sunt examinate în mod sistematic nodurile
sale, pornind de la un nod dat, i, astfel încât fiecare nod accesibil din nodul i pe muchiile (arcele)
21
adiacente să fie atins o singură dată. Vecinii unui nod sunt reprezentaţi de toate nodurile
adiacente lui şi accesibile din el.
Vizitarea sau traversarea unui graf este operaţia prin care se parcurge graful trecându-se de la
un nod i (nodul curent) la nodurile vecine lui, într-o anumită ordine, în vederea prelucrării
informaţiilor asociate nodurilor. Pentru parcurgerea grafurilor, există următoarele două metode:
1. Metoda de parcurgere „în lăţime" – Breadth First (BF). Se vizitează mai întâi un nod
iniţial i, apoi vecinii acestuia, apoi vecinii nevizitaţi ai acestora, şi aşa mai departe – până când se
parcurg toate nodurile grafului.
2. Metoda de parcurgere „în adâncime" – Depth First (DF). Se vizitează mai întâi un nod
iniţial i, după care se parcurge primul dintre vecinii săi nevizitaţi, de exemplu j, după care se trece
la primul vecin nevizitat al lul j, şi aşa mai departe – până când se parcurge în adâncime ramura
respectivă. Când s-a ajuns la capătul ei, se revine la nodul din care s-a plecat ultima dată, şi se
parcurge următorul său vecin nevizitat.
Exemplu Pentru graful neorientat G22 = (X22,U22) – figura 23 – definit astfel:
mulţimea nodurilor este X22={1,2,3,4,5,6,7,8,9}.
mulţimea muchiilor este U22={[1,2], [1,3], [1,4], [2,5], [3,5], [3,6], [3,7], [4,7], [5,8], [6,8],
[6,9]}.
Graful G22 poate fi parcurs astfel, pornind din nodul 1:
1. În cazul metodei de parcurgere BF – „în lăţime", vor fi parcurse pe rând nodurile: 1, 2, 3, 4,
5, 6, 7, 8, 9
2. În cazul metodei de parcurgere DF – „în adâncime", vor fi parcurse pe rând nodurile: 1, 2,
5, 3, 6, 8, 9, 7, 4

Parcurgerea în lăţime – Breadth First


Pentru această metodă de parcurgere a unui graf cu n noduri, se folosesc următoarele
structuri de date şi date elementare:
1. Variabilele de memorie: n pentru numărul de noduri ale grafului, k pentru nodul care se
prelucrează, i şi j pentru parcurgerea matricei de adiacenţă şi a vectorilor.
2. Matricea de adiacenţă a grafului a.
3. Vectorul de vizitare vizitat. El conţine n elemente în care se înregistrează nodurile vizitate.
Elementele vectorului vizitat[i] sunt definite astfel:

4. Coada de aşteptare c a nodurilor parcurse. Coada de aşteptare c


gestionează nodurile prelucrate. Pentru coada de aşteptare c, se foloseşte
implementarea statică cu un vector c cu n elemente. Pentru gestionarea cozii de
aşteptare, se folosesc două variabile de memorie prim şi ultim care joacă
rolul de indicatori pentru a memora adresa primului element din listă (capul
cozii) şi, respectiv, adresa ultimului element din listă (coada cozii). În această
coadă de aşteptare vor fi înregistrate nodurile vizitate, în ordinea în care au fost
vizitate. Iniţial, coada de aşteptare c conţine un singur element care corespunde nodului cu care
începe parcurgerea grafului, iar valoarea indicatorilor prim şi ultim este 1. Pe măsură ce se
parcurge graful, se completează următoarele elemente ale vectorului c. Atunci când se prelucrează
un nod k de la capul cozii de aşteptare, prin coada cozii de aşteptare se introduc toate nodurile i
vecine cu nodul k care nu au fost vizitate încă.
22
Algoritmul pentru parcurgerea grafului este următorul:
PAS1. Se citesc din fişier, valoarea pentru variabila n şi matricea de adiacenţă a grafului.
PAS2. Se iniţializează cu 0 elementele vectorului de vizitare vizitat, deoarece iniţial nici unul
dintre noduri nu a fost vizitat.
PAS3. Se introduce de la tastatură valoarea variabilei de memorie k, corespunzătoare primului
nod cu care începe parcurgerea grafului.
PAS4. Se iniţializează coada de aşteptare c (indicatorii şi conţinutul primului element introdus
în coada de aşteptare), astfel: prim=1, ultim=1 şi c[prim]=k, deoarece, în coada de
aşteptare c este înregistrat doar nodul k cu care începe parcurgerea.
PAS5. Se actualizează vectorul vizitat – atribuind elementului k al vectorului valoarea 1,
deoarece a fost vizitat (vizitat[k]=1).
PAS6. Cât timp coada nu este vidă (prim <= ultim) execută
PAS7. Se extrage următorul element din coada de aşteptare, corespunzător nodului
căruia i se vor vizita vecinii (k=c[prim];).
PAS8. Pentru toate nodurile i vecine ale vârfului k, nevizitate încă, execută
PAS9. Se incrementează valoarea indicatorului ultim, pentru a înregistra
următorul nod care va trebui vizitat, prin adăugare la coada cozii de
aşteptare (ultim=ultim+1;).
PAS10. Se adaugă, la sfârşitul cozii de aşteptare c, nodul i vecin nodului k,
care nu a fost încă vizitat (c[ultim] =i;).
PAS11. Prin adăugarea nodului j la coada de aşteptare c, se consideră că
acest nod a fost vizitat – şi se actualizează elementul din vectorul de
vizitare care corespunde acestui nod (vizitat[i]=1;). Se trece la Pasul 6.
PAS12. Se pregăteşte indicatorul prim pentru a se extrage următorul nod, din coada de
aşteptare, ai cărui vecini vor fi vizitaţi (prim=prim+1;). Se trece la Pasul 7.
PAS13. Se afişează lista nodurilor vizitate, în ordinea în care au fost vizitate, prin extragerea
lor din vectorul c, pornind de la elementul 1 şi până la elementul n.

int n,a[10][10],vizitat[20],c[20],prim,ultim,k;
fstream f("graf21.txt",ios::in);
void citeste() {//funcţia prin care se citeşte matricea de adiacenţă din fişier}
void init (int k)
{
prim=ultim=1;
c[ultim]=k;
vizitat[k]=1;
}
int este_vida()
{
return ultim<prim;
}
void adauga(int i)
{
ultim++;
c[ultim]=i;
vizitat[i]=1;
}
void elimina() {prim++;}
void prelucrare()

23
{
int i;
k=c[prim];
for (i=1;i<=n;i++)
if (a[k][i]==1 && vizitat[i]==0) adauga(i);
elimina();
}
void afisare()
{
for (int i=1;i<=n;i++) cout<<c[i]<<" ";
}
void main()
{
citeste(); cout<<"nod de pornire: "; cin>>k; init(k);
while (!este vida()) prelucrare();
cout<<"Nodurile vizitate prin metoda BF sunt: "< <endl ;
afisare();
}

Parcurgerea în adâncime – Depth First


Pentru această metodă de parcurgere a unui graf cu n noduri se folosesc următoarele structuri
de date şi date elementare:
1. Variabilele de memorie. n pentru numărul de noduri ale grafului, k pentru nodul care se
prelucrează, i şi j pentru parcurgerea matricei de adiacenţă şi a vectorilor.
2. Matricea de adiacenţă a grafului a.
3. Vectorul de vizitare vizitat. El conţine n elemente în care se înregistrează nodurile vizitate.
Elementele vectorului vizitat[i] sunt definite ca şi în metoda precedentă de parcurgere.
4. Stiva st a nodurilor parcurse. Stiva st gestionează nodurile vecine parcurse în adâncime.
Pentru gestionarea stivei se foloseşte variabila de memorie vf pentru a identifica ultimul nod intrat în
stivă. Pentru stiva st se foloseşte implementarea statică cu un vector st cu n elemente. În această
stivă vor fi înregistrate în ordine nodurile vizitate în adâncime, pe o direcţie. Iniţial stiva st conţine un
singur element care corespunde nodului cu care începe parcurgerea grafului, iar valoarea variabilei
vf este 1. Pe măsură ce se parcurge graful se completează următoarele elemente ale vectorului st.
Atunci când se prelucrează un nod k, pe la vârful stivei se introduc în stivă toate nodurile i vecine cu
nodul k care nu au fost vizitate încă.
Algoritmul pentru parcurgerea grafului este următorul:
PAS1. Se citesc din fişier valoarea pentru n şi matricea de adiacenţă a grafului.
PAS2. Se iniţializează cu 0 elementele vectorului de vizitare vizitat, deoarece nici unul dintre
noduri nu a fost vizitat.
PAS3. Se introduce de la tastatură valoarea variabilei de memorie k, corespunzătoare primului
nod cu care începe parcurgerea grafului şi se afişează eticheta lui.
PAS4. Se iniţializează stiva st (vârful şi conţinutul vârfului stivei), astfel: vf←1; st[vf] ←k;
deoarece iniţial în stiva st este înregistrat doar nodul k cu care începe parcurgerea.
PAS5. Se actualizează vectorul vizitat atribuind elementului k al vectorului valoarea 1
deoarece a fost vizitat (vizitat[k] ←1).
PAS6. Cât timp stiva nu este vidă (vf<>0) execută
PAS7. Se extrage din vârful stivei, elementul corespunzător nodului căruia i se vor vizita
vecinii (k←st[vf];).
PAS8. Se iniţíalizează nodul i cu care începe căutarea (i←1;).

24
PAS9. Cât timp nu s-a găsit un nod i vecin nodului k, nevizitat încă (i<=n şi (a[i][k]=0 sau
(a[i][k]=1 şi vizitat[i]=1))) execută
PAS10. Se trece la următorul nod în vederea verificării (i←i+1;) şi se revine la
Pasul 9.
PAS11. Dacă nu s-a mai găsit un nod i vecin nodului k nevizitat încă, atunci se elimină
nodul k din stivă prin coborârea vârfului stivei (vf←vf-1), altfel se afişează nodul
găsit i, se adaugă în vârful stivei (vf←vf+1; st[vf] ←i;) şi se actualizează
elementul din vectorul de vizitare care corespunde acestui nod deoarece prin
adăugarea nodului i la stiva st se consideră că acest nod a fost vizitat
(vizitat[i]←1;) şi se trece la Pasul 6.

6. Parcurgerea arborilor binari


Traversarea unui arbore înseamnã vizitarea tuturor nodurilor din arbore si poate fi privitã ca o
liniarizare a arborelui, prin stabilirea unei secvente liniare de noduri. In functie de ordinea în care se
iau în considerare rãdãcina, subarborele stânga si subarborele dreapta putem vizita un arbore binar
în:
- Ordine prefixatã (preordine sau RSD) : rãdãcinã, stânga, dreapta
- Ordine infixatã (inordine sau SRD) : stânga, rãdãcinã, dreapta
- Ordine postfixatã (postordine sau SDR): stânga, dreapta, rãdãcinã
typedef struct nod
{
declaratii ;
struct nod *st;
struct nod *dr;
} NOD;

void prefix (tnod * r)


{
if ( r == NULL) return;
printf ("%d ",r->val); // radacina

25
prefix (r->st); // stânga
prefix (r->dr); // dreapta
}

void infix (tnod * r)


{
if ( r == NULL) return; // nimic daca (sub)arbore vid
infix (r->st); // afisare subarbore stânga
printf ("%d ",r->val); // afisare valoare din radacina
infix (r->dr); // afisare subarbore dreapta
}

(postfix poate fi scrisă diferit de primele 2 moduri, unde prelucrare() poate fi


orice fucţie care se aplică nodului – în exemplele de mai sus se afişează valoare
anodului)
void postord (NOD *p)
{
if(p != 0)
{
postord (p -> st);
postord (p -> dr);
prelucrare(p);
}
}

• Preordine : 10, 6, 4, 2, 1, 3, 5, 8, 7, 9, 13, 12, 11, 15, 14, 16


• Inordine : 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16

• Postordine: 1, 3, 2, 5, 4, 7, 9, 8, 6, 11, 12, 14, 16, 15, 13, 10

• Pe niveluri: 10, 6, 13, 4, 8, 12, 15, 2, 5, 7, 9, 11, 14, 16, 1, 3

7. Algoritmi de căutare. Căutare secvenţială, căutare binară.

26
Căutarea secvenţială este unul dintre cei mai simpli algoritmi studiaţi. El urmăreşte să verifice
apartenenţa unui element la un şir de elemente de aceeaşi natură, în speţă a unui număr la un şir
de numere. Pentru aceasta se parcurge şirul de la un capăt la celălalt şi se compară numărul de
căutat cu fiecare număr din şir.
procedure cautare_secventiala(array, x)
for i = 1 to n
if (array[i] == x) print i
Complexitatea căutării secvenţiale: O(n) deoarece trebuie inspectate toate elementele vectorului.
Dacă nu există informaţii suplimentare privind datele de intrare, complexitatea nu poate fi micşorată.
vect = [7 3 9 7 7 5 7 5 9]; x=5 => se repetă de 9 ori. Afișează 6,8.

Căutarea binară oferă performanţe mai bune decât algoritmul de căutare secvenţială. El
funcţionează prin compararea numărului de căutat cu elementul aflat la mijlocul şirului (element
care se mai numeşte şi pivot). Avem următoarele cazuri:
1. În cazul în care cele două elemente coincid căutarea s-a încheiat cu succes.
2. Dacă numărul de căutat este mai mare decât pivotul, se continuă căutarea în aceeaşi
manieră în partea dreaptă (subşirul delimitat de pivot şi capătul şirului initial).
3. Dacă numărul de căutat este mai mic decât pivotul se continuă căutarea în aceeaşi
manieră în partea stângă (subşirul delimitat de pivot şi începutul şirului initial).
Algoritmul prezentat se încadrează în clasa algoritmilor elaboraţi conform tehnicii de
programare Divide et Impera. Unul din dezavantajele acestui algoritm este că şirul în care se face
căutarea trebuie să fie iniţial sortat.

procedure cautare_binara(array, x)
low = 1
high = N //nr de elemente a şirului
gasit=0
while (low <= high)
mid = low + (high - low) / 2
if (array[mid] < x)
low = mid + 1
else
if (array[mid] > x)
high = mid – 1
else
print mid // poziţia pe care a fost găsită valoarea
gasit=1
return
if (gasit=0)
print “valoarea nu a fost găsită”
return

Complexitatea căutării binare: O(log(n)) deoarece la fiecare pas se înjumătăţeşte lungimea


vectorului de inspectat.
Vector = [3 5 5 7 7 7 7 9 9]; x=5. Se repetă de 2 ori, se fac 6 comparații. Afișează 2.

27
8. Structuri fundamentale şi derivate în programarea procedurală
orice algoritm poate fi realizat prin combinarea a trei structuri fundamentale:
 structura secvenţială;
 structura alternativă (de decizie, de selecţie);
 structura repetitivă (ciclică).

Structura secvenţială este o înşiruire de secvenţe de prelucrare (instrucţiuni), plasate una după
alta, în ordinea în care se doreşte execuţia acestora.
Implementarea structurii secvenţiale se realizează cu ajutorul instrucţiunilor:

 Instrucţiunea vidă
Sintaxa: ;
Instrucţiunea vidă nu are nici un efect. Se utilizează în construcţii în care se cere prezenţa
unei instrucţiuni, dar nu se execută nimic (de obicei, în instrucţiunile repetitive).

 Instrucţiunea expresie
Sintaxa: expresie;
sau: apel_funcţie;

 Instrucţiunea compusă (instrucţiunea bloc)


Sintaxa: {
declaratii;
instr1;
instr2;
....
}
Într-un bloc se pot declara şi variabile care pot fi accesate doar în corpul blocului.
Instrucţiunea bloc este utilizată în locurile în care este necesară prezenţa unei singure
instrucţiuni, însă procesul de calcul este mai complex, deci trebuie descris în mai multe
secvenţe.

Structura de decizie se implementează folosind instrucţiunile:


 Instrucţiunea if:
Sintaxa:
if (expresie)
instrucţiune1;
[ else
instrucţiune2; ]
 Instrucţiunea switch
În unele cazuri este necesară o decizie multiplă specială. Instrucţiunea switch permite acest lucru
Sintaxa:
switch (expresie)
{
case valoare_1: instructiune_1;
[break;]
case valoare _2: instructiune_2;
[break;]
28
..................................
case valoare _n-1: instructiune_n-1;
[break;]
[ default: instructiune_n; ]
}

Structurile repetitive se impart în 2 categorii: cu test iniţial şi cu test final.


1. structura ciclică cu test initial se implementează folosind instrucţiunile while şi for.

 Instrucţiunea while implementează structura ciclică cu număr necunoscut de paşi


Sintaxa:
while (<conditie>)
instructiune;

 Instrucţiunea for
În majoritatea limbajelor de programare de nivel înalt, instrucţiunea for implementează
structura ciclică cu număr cunoscut de paşi

for (<initializare_contor>;<conditie>;<incrementare_contor>)
instructiune;

2. structura ciclică cu test final se implementează folosind :

do
instructiune;
while (<conditie>)

- spre deosebire de structura repetitiva while instructiune se va executa cel putin o data

FACILITATI DE INTRERUPERE A UNEI SECVENTE


Pentru o mai mare flexibilitate (tratarea exceptiilor care pot apare in procesul de prelucrare), in
limbajul C se utilizeaza instructiunile break si continue. Ambele instructiuni sunt utilizate in
instructiunile ciclice. In plus, instructiunea break poate fi folosita in instructiunea switch.
Instructiunea break
Este utilizata in cadrul instructiunilor ciclice, instructiunea break "forteaza" iesirea din acestea.
Fara a se mai testa valoarea expresiei (conditia) care determina repetarea corpului instructiunii
ciclice, se continua executia cu instructiunea care urmeaza instructiunii ciclice. Astfel, se intrerupe
repetarea corpului instructiunii ciclice, indiferent de valoarea conditiei de test.
Utilizarea in cadrul instructiunii switch: In situatia in care s-a ajuns la o valoare a unei expresiei
constante egala cu cea a expresiei aritmetice, se executa instructiunea corespunzatoare acelei
ramuri. Daca se intalneste instructiunea break, parcurgerea este intrerupta (nu se mai compara
valoarea expresiei aritmetice cu urmatoarele constante), deci se va trece la executia primei
instructiuni de dupa switch. Daca nu este intalnit break, parcurgerea continua. Instructiunea break
cauzeaza deci, iesirea imediata din switch.
Instructiunea continue

29
Intalnirea instructiunii continue determina ignorarea instructiunilor care o urmeaza in corpul
instructiunii ciclice si reluarea executiei cu testarea valorii expresiei care determina repetarea sau
nu a corpului ciclului.

9. Subprograme (definire, tipuri de transfer al parametrilor, apelare, variabile locale şi


globale).

Prin subprogram (funcţie) vom înţelege un ansamblu alcătuit din tipuri de date, variabile şi
instrucţiuni scrise în vederea unei anumite prelucrări (calcule, citiri, scrieri) şi care poate fi utilizat
(rulat) doar dacă este apelat de un program sau de alt subprogram.
Parametrii care se găsesc în apelul funcţiei se numesc parametri formali. Atunci când scriem
o funcţie nu cunoaştem valoarea propriu-zisă a parametrilor. Funcţia trebuie să întoarcă rezultatul
corect, oricare ar fi valoarea lor. Din acest punct de vedere ei se numesc formali.
Parametrii care se utilizează la apel se numesc parametri efectivi. La apel, valorile sunt
cunoscute. De aceea se numesc efectivi.
Apelarea:
La întâlnirea instrucţiunii return, după atribuirea valorii, execuţia funcţiei se încheie şi se revine
la funcţia care a apelat-o. În absenţa instrucţiunii return, execuţia funcţiei se încheie după execuţia
ultimei instrucţiuni. În acest caz nu se întoarce nici o valoare.
O funcţie poate fi apelată de sine stătător (prin nume şi lista parametrilor efectivi), dar poate fi
inclusă şi în cadrul expresiilor, caz în care, la evaluarea expresiei este apelată funcţia. Această
formă de apel nu este valabilă în cazul funcţiilor de tip void .
Variabilele globale. Se declară în afara corpului oricărei funcţii. Atribute:
1. Clasa de memorare – segmentul de date.
2. Durata de viaţă a variabilelor globale este statică. Ele au spaţiu rezervat în tot timpul
execuţiei programului.
3. Vizibilitatea – În cazul în care declaraţiile acestora sunt înaintea tuturor funcţiilor, acestea
sunt vizibile la nivelul întregului program(fişier). Dacă anumite funcţii se află plasate înaintea
declaraţiilor acestor variabile, atunci ele sunt vizibile doar pentru funcţiile care sunt plasate
după aceste declaraţii.
Variabilele locale. Se declară în corpul funcțiilor. Atribute:
1. Clasa de memorare a variabilelor locale este, implicit, segmentul de stivă. Există posibilitatea
ca acestea să fie alocate în registrele microprocesorului. Variabilele locale nu sunt iniţializate
implicit cu 0. Dacă nu sunt iniţializate explicit de programator, ele reţin o valoare oarecare,
numită valoare reziduală.
2. Vizibilitatea variabilelor locale este la nivelul blocului la care au fost declarate. În cazul în
care, într-un anumit bloc sunt vizibile mai multe variabile, toate cu acelaşi nume, dar au
domenii de vizibilitate diferite, se accesează variabila cu vizibilitatea cea mai mică. Dacă
declarăm o variabilă locală în ciclul for ea este vizibilă doar în blocul for.
3. Durata de viaţă a variabilelor locale este atâta timp cât durează execuţia blocului respectiv.

Transmiterea parametrilor se poate realiza prin intermediul a două mecanisme:


 prin valoare
 prin referinţă.

30
Transmiterea prin valoare este utilizată atunci când dorim ca subprogramul să lucreze cu
acea valoare, dar, în prelucrare, nu ne interesează ca parametrul actual (din blocul apelant) să
reţină valoarea modificată în subprogram.
Transmiterea prin referinţă este utilizată atunci când dorim ca la revenirea din subprogram
variabila transmisă să reţină valoarea stabilită în timpul execuţiei programului. În acest caz,
parametrii actuali trebuie să fie referinţe la variabile. La transmitere, subprogramul reţine în stivă
adresa variabilei. La compilare, orice referinţa la o variabilă este tradusă în subprogram ca adresare
indirectă. Acesta este motivul pentru care în subprogram putem adresa variabila normal (nu
indirect), cu toate că, pentru o variabilă transmisă, se reţine adresa ei.
void interschimba(int &a, int &b)

10. Recursivitate

Un obiect sau un fenomen se definește în mod recursiv daca în definiția sa există o referire la
el însuși. Utilitatea practică a recursivității rezultă din posibilitatea de a defini un set infinit de obiecte
printr-o singura relație sau printr-un set finit de relații.
Recursivitatea e strâns legată de iterație. Iterația este execuția repetată a unei porțiuni de
program, până la îndeplinirea unei condiții (while, do-while , for din C).
Recursivitatea presupune execuția repetată a unui modul, însă în cursul execuției lui (și nu la
sfârșit, ca in cazul iterației), se verifică o condiție a cărei nesatisfacere, implică reluarea execuției
modulului de la început, fără ca execuția curentă sa se fi terminat. În momentul satisfacerii condiției
se revine in ordine inversa din lanțul de apeluri, reluându-se si încheindu-se apelurile suspendate.
Apelul recursiv al unei funcții trebuie sa fie condiționat de o decizie care sa împiedice apelul in
cascada ( la infinit ); aceasta ar duce la o eroare de program - depășirea stivei.

11. Noţiunile de bază ale programării obiectuale: clasă, metodă.


Programarea Orientata pe Obiecte, POO, se fundamenteaza pe conceptul de obiect, care
este definit printr-o multime de date, numite proprietati, si o multime de procedure sau functii de
prelucrare ale acestor date, numite metode.
La baza POO stau conceptele de clasa si de obiect.
Clasa, intr-un anumit limbaj de programare, reprezinta definirea unui tip de obiecte abstracte
sau concrete, adica descrierea proprietatilor, a datelor si a metodelor, a prelucrarilor, posibile asupra
datelor. Clasa este, de fapt, o notiune abstracta, care defineste un anumit tip de obiecte, sau, altfel
spus, o clasa reprezinta multimea posibila a mai multor obiecte de acelasi tip.
Obiect, reprezinta o multime de date care descrie un anumit obiect concret sau abstract,
numite si proprietati, impreuna cu procedurile, functiile, de prelucrare a cestora, numite metode.
Crearea unui obiect presupune specificarea clasei din care face parte, astfel identificandu-
se proprietatile obiectului si modul in care acestea pot fi folosite si prelucrate

Clasa de obiecte: defineste structura (arhitectura, planul) obiectelor ce pot fi create din
acea clasa.
Obiectele sunt instante ale unor clase.

Metoda este un membru al unei clase care implementează o acţiune. Metoda poate admite
parametri şi returna valori. Tipul returnat de către o metodă poate fi unul predefinit (int, bool etc.)
sau de tip obiect (class). În cazul în care metoda nu returnează nimic, tipul este void.

31
Metodele pot fi supradefinite (supraîncărcate), adică se pot defini mai multe metode, care să
poarte acelaşi nume, dar să difere prin numărul şi tipul de parametri. Valoarea returnată de către o
metodă nu poate să fie luată în considerare în cazul supradefinirii.

■ Metode constructor
 Sunt metode speciale apelate atunci cand se creaza un obiect
 Metodele de tip constructor au exact acelasi nume cu cel al clasei de obiecte si nu au
tip de returnare (nici macar void)
 Orice clasa are cel putin un constructor
 Daca nu declaram nici un constructor, compilatorul va genera un constructor default
(numit null constructor)
 Daca declaram cel putin un constructor, compilatorul nu va mai genera null
constructor
 Constructorii sunt folositi pentru initializarea datelor de obiect
 Pentru o clasa ce nu are nici un constructor public, nu se pot crea obiecte din afara
clasei

■ Metode getter
 Sunt metode de tipul public int getNota()
 Unde nota este un atribut de tip intreg
 In mod normal atributele sunt private, iar pentru a avea acces in mod controlat la
atributele unui obiect se folosesc metode getter
 In mod normal pentru toate atributele private care dorim sa poate fi citite din afara
obiectului, cream metode getter

■ Metode setter
 Sunt metode de tipul public void setNota(int nota)
 Unde nota este un atribut de tip intreg
 In mod normal atributele sunt private, iar pentru a modifica in mod controlat atributele
unui obiect se folosesc metode setter
 In mod normal pentru toate atributele private care dorim sa poate fi cscrise din afara
obiectului, cream metode setter

■ Metode generale
 Sunt toate celelalte tipuri de metode
 Orice metoda primeste unele argumente si returneaza un rezultat

■ Metodele sunt in mod normal metode de instanta (apartin unor obiecte)


■ Daca apare cuvantul cheie “static” in declaratia metodei, atunci metoda este de clasa
(poate fi apelata fara a avea creat un obiect de acea clasa)

12. Proprietăţile claselor şi ale metodelor

Proprietățile unei clase sunt:


 Încapsularea este proprietatea obiectelor de a-si ascunde o parte din date si metode. Din
exteriorul obiectului sunt accesibile numai datele si metodele publice. Un program poate
utiliza datele unui obiect declarate privat, numai cu ajutorul unor metode definite public.
32
Separarea datelor in secțiuni de date publice sau private determina protejarea datelor față de
utilizarea lor eronata in programe.
 Moștenirea este proprietatea unei clase de a conține toate atributele si metodele superclasei
sale. In consecință trecerea de la clasa la subclasa se face prin adăugarea de atribute si/sau
de metode. In general, in programarea orientata obiect, moștenirea poate fi simpla sau
multipla. In cazul moștenirii simple fiecare cl6asa are o superclasa. In cazul moștenirii
multiple o clasa poate avea mai multe superclase.
 Polimorfismul înseamnă că putem defini o funcţie de mai multe ori, astfel încât să accepte
diferite combinaţii de parametri şi să realizeze aceeaşi sarcină folosind parametri diferiţi dar
specificaţi (funcţia va avea acelaşi nume dar va diferi numărul şi tipul parametrilor la fiecare
declarare)..

13. Structuri de control în Visual Basic. Elementele programării vizuale.

 Instrucţiunea IF este o structură condițională și are sintaxa:


If condition Then If hour = 14 Or hour = 15 Then
[ statements ] Return True
[ Else [ elsestatements ] ] Else
End If Return False
End If

 La instrucțiunea SWITCH din C/C++, dacă la finalul instrucţiunilor dintr-o ramură case nu
există break, se trece la următorul case. În C# se semnalează eroare. Există şi aici
posibilitatea de a face verificări multiple (în sensul de a trece la verificarea următoarei condiţii
din case) doar dacă case-ul nu conţine instrucţiuni.

Select [ Case ] testexpression Select Case number


[ Case expressionlist Case 1 To 5
[ statements ] ] Debug.WriteLine("Between 1 and 5, inclusive")
[ Case Else Case 6, 7, 8
[ elsestatements ] ] Debug.WriteLine("Between 6 and 8, inclusive")
End Select Case 9 To 10
Debug.WriteLine("Equal to 9 or 10")
Case Else
Debug.WriteLine("Not between 1 and 10,
inclusive")
End Select

 Instrucţiunea WHILE este o instrucțiune repetitivă și are sintaxa:


While condition While index < 100000
[ statements ] index += 1
[ Continue While ] If index >= 5 And index <= 8 Then
[ statements ] Continue While
[ Exit While ] End If
[ statements ] Debug.Write(index.ToString & " ")
If index = 10 Then
End While

33
Exit While
End If
End While

 Instrucţiunea DO-WHILE este o instrucțiune repetitivă și are sintaxa:


Do { While | Until } condition Do While index <= 100
[ statements ] If index > 10 Then
[ Continue Do ] Exit Do
[ statements ] End If
[ Exit Do ]
[ statements ] Debug.Write(index.ToString & " ")
index += 1
Loop
Loop
--sau--
Do
Do
[ statements ]
Debug.Write(index.ToString & " ")
[ Continue Do ]
index += 1
[ statements ] Loop Until index > 10
[ Exit Do ]
[ statements ]
Loop { While | Until } condition

 Instrucțiunea FOR este o instrucțiune repetitivă și are sintaxa:


For counter [ As datatype ] = start To end [ Step step ]
[ statements ] For number As Double = 2 To 0 Step
[ Continue For ] -0.25
[ statements ] Debug.Write(number.ToString & " ")
[ Exit For ] Next
[ statements ]
Next [ counter ]

 Instrucțiunea FOREACH enumeră elementele dintr-o colecţie, executând o instrucţiune


pentru fiecare element. Elementul care se extrage este de tip read-only, neputând fi transmis
ca parametru şi nici aplicat un operator care să-i schimbe valoarea.
For Each element [ As datatype ] In group For Each item As String In lst
[ statements ] Debug.Write(item & " ")
[ Continue For ] Next
[ statements ]
[ Exit For ]
[ statements ]
Next [ element ]
 Instrucţiunea GOTO poate fi folosită, pentru efectuarea unor salturi la anumite linii
GoTo line Sub gotoStatementDemo()
Dim number As Integer = 1
Dim sampleString As String
If number = 1 Then GoTo Line1 Else GoTo Line2
Line1:
sampleString = "Number equals 1"
GoTo LastLine
Line2:

34
sampleString = "Number equals 2"
LastLine
Debug.WriteLine(sampleString)
End Sub

14. Noţiunile de control, proprietate, eveniment în programarea vizuală

Un control este unitatea de bază a unei interfeţe Windows. Acesta poate fi „găzduit” de un
container ce poate fi un formular sau un alt control. Un control este o instanţă a unei clase derivate
din System.Windows.Forms şi este responsabil cu desenarea unei părţi din container. Visual
Studio .NET vine cu o serie de controale standard, disponibile în Toolbox.
Proprietatea este un membru al clasei care ne permite să accesăm sau să modificăm
caracteristicile unui obiect sau ale clasei.
Un eveniment este un mesaj trimis de un obiect atunci când are loc o anumită acţiune.
Această acțiune poate fi: interacţiunea cu utilizatorul (mouse click) sau interacţiunea cu alte
entităţi de program, apăsarea unui buton, o selecţie de meniu, trecerea unui anumit interval de timp,
pe scurt, orice ce se întâmplă în sistem şi trebuie să primească un răspuns din partea programului.
Evenimentele sunt proprietăţi ale clasei care le publică. Cuvântul-cheie event controlează cum sunt
accesate aceste proprietăţi.

15. Buton de comandă (Button) şi butoane de opţiune (RadioButton)

Butonul de comanda determina când utilizatorul dorește sa facă ceva cum ar fi sa iasă din
aplicație sau sa înceapă sa printeze. Aproape in toate cazurile se vor adăuga următoarele sarcini
pentru adăugarea unui buton de comanda intr-o aplicație:
 Locația si mărimea butonului de comanda pe form;
 Schimbarea numelui butonului de comanda si proprietăți Caption;
 Adăugare codului de procedura la butonul de comanda pentru evenimentul click.
Deși butonul de comanda are zeci de proprietăți, cele mai folosite proprietăți in majoritatea cazurilor
sunt puţine. În plus, chiar daca butonul de comanda suporta nenumărate controale, utilizatorul va
scrie cod numai pentru evenimentul click in cele mai multe cazuri.
Butonul de comanda se afla pe cele mai multe forme, astfel încât atunci când utilizatorul face click
pe buton, acesta va putea declanșa un eveniment care poate să înceapă.
Butoanele de opțiune sunt similare cu caseta de validare, dar butoanele de opțiune sunt
afișate rotunjite, față de o caseta pătrată așa cum sunt casetele de validare. Așa cum sunt si
casetele de validare, butonul de opțiune este folosit pentru a selecta si deselecta opțiuni dar acesta
permite utilizatorului sa alega din mai multe opțiuni diferite.
Cele mai importante proprietăți a butonului de opțiuni sunt:
 Appearance -> valoarea implicita este Normal. Atunci când este setat la valoarea Button,
acesta va fi afișat ca un buton;
 BackgroundImage -> folosit pentru a seta o imagine de fundal pentru un buton de opțiuni;
 CheckAlign -> folosit pentru setarea alinierii butoanelor de opțiuni;
 Checked -> valoarea inițiala este false, iar daca este setata la true, butonul de opțiuni va fi
afișat ca si selectat;

35
 FlatStyle -> valoarea implicita este Standard. Se poate selecta dintr-o lista predefinita stilul
butonului de opțiuni.
Pentru gruparea radioButton se foloseşte containerul GroupBox.

16. Casetă de text (TextBox), casetă de validare (CheckBox)

Caseta de text este folosita pentru a accepta datele scrise de utilizator, sau pentru afișarea textului.
Cele mai importante proprietăți ale casetei de text sunt:
 Enable -> setat implicit la valoarea true, iar pentru dezactivare este setat la false;
 MultiLine -> atunci când aceasta proprietate este setata la true permite casetei de text sa
adauge text pe mai multe linii;
 PasswordChar -> folosit pentru a seta caractere pentru parola. Textul afișat in caseta de text
va fi afișat in funcție de cum îl setează utilizatorul. Daca acesta introduce ‚*’, atunci textul
introdus va fi afișat sub forma de ‚*’;
 ReadOnly -> face a căsuță de text sa poată fi doar citita. Nu este permis adăugarea altui text
sau modificarea textului afișat;
 Visibile -> valoarea implicita este true. Pentru a ascunde caseta de dialog, aceasta
proprietate este setata la false;
 TextAlign -> permite alinierea textului din trei posibile opțiuni. Textul inițial este aliniat la
stânga, dar acesta poate fi aliniat la dreapta sau pe centru;
 Scrollbars -> permite adăugarea unui scrollbar pe o caseta de text. Este foarte folositor
atunci când caseta de text este setata pe linii multiple. Scrollbarul are următoarele opțiuni:
None (pentru a nu fi adăugata un scrollbar), Horizontal (scrollbarul va fi amplasat orizontal),
Vertical (scrollbarul va fi amplasat pe verticala), Both (scrollbarul va fi amplasat atât pe
verticala cat si pe orizontala).
Caseta de validare
Prin bifare, valoarea casetei de validare este setata la true. Acest control poate fi gri atunci când
caseta de validare nu este disponibila, iar aceasta stare este gestionata prin cod.
Atunci când o căsuța de validare este amplasata pe o forma, utilizatorul nu trebuie decât sa ii
seteze numele si proprietate Caption cu un sir de caractere descriptive.
Cel mai important eveniment al unei casete de validare este evenimentul click, care se declanșează
atunci când utilizatorul sau codul scris schimba starea de control.

Public Class Form1


Private Sub Button1_Click(sender As System.Object, e As System.EventArgs)
Handles Button1.Click
TextBox1.Text = "Ai achizitionat: "
If RadioButton1.Checked = True Then
TextBox1.Text += RadioButton1.Text + ","
End If
If RadioButton2.Checked = True Then
TextBox1.Text += RadioButton2.Text + ","
End If
If RadioButton3.Checked = True Then
TextBox1.Text += RadioButton3.Text + ","
End If
If RadioButton4.Checked = True Then

36
TextBox1.Text += RadioButton4.Text + ","
End If
If CheckBox1.Checked = True Then
TextBox1.Text += CheckBox1.Text + ","
End If
If CheckBox2.Checked = True Then
TextBox1.Text += CheckBox2.Text + ","
End If
If CheckBox3.Checked = True Then
TextBox1.Text += CheckBox3.Text + ","
End If
End Sub
End Class

17. Liste simple (ListBox) şi liste combinate (ComboBox) în Visual Basic

O lista simpla afișează o lista de elemente din care un utilizator poate selecta una sau mai multe
valori din lista. Cele mai utilizate proprietăți sunt:
 MultiColumn -> inițial este setat la false. Atunci când este setat la true, in lista vor apărea mai
multe coloane;
 HorizontalScrollbar -> afișarea pe orizontala a unui scrollbar in lista. Este utila atunci când
lista are coloane multiple;
 ScollAlwaysVisible -> inițial este setat la false. Atunci când este setat la true vor fi afișate
mereu un scrollbar pe verticala si unul pe orizontala;
 SelectionMode -> inițial este setat la one. Atunci când este setat la None nu poate fi selectat
nici un element, iar când este setat la MultiSimple pot fi selectate multiple elemente si
MultiExtended permite selectarea mai multor elemente cu ajutorul tastelor Shift, Ctrl, si
săgețile de pe tastatura;
 Sorted -> valoarea inițiala este false. Când este setat la true elementele din lista vor fi afișate
in ordine alfabetica.

Listele combinate sunt numite astfel deoarece combina caracteristicile care se găsesc in casetele
de text, cat si casetele de lista. Listele combinate sunt de asemenea menționate ca căsuțe drop-
down sau liste drop-down.
Listele combinate sunt au trei stiluri:
Dropdown ComboBox (stilul 0)
Simple ComboBox (stilul 1)
Dropdown List (stilul 2)

Private Sub Button1_Click(sender As System.Object, e As System.EventArgs)


Handles Button1.Click
Dim text As String = "Am selectat si am adaugat elementele: "
ListBox1.Items.Clear()
For Each c As Object In CheckedListBox1.CheckedItems
ListBox1.Items.Add(c)
text += c.ToString()
text += " "
Next

37
End Sub

18. Crearea şi utilizarea hiperlegăturilor HTML

Legăturile (link-urile) reprezintă partea cea mai importantă a unei pagini Web. Ele transformă un text
obișnuit în hipertext sau hiperlegătură, care permite trecerea rapidă de la o informație aflată pe un
anumit server la altă informație memorată pe un alt server aflat oriunde în lume.
Legăturile sunt zone active într-o pagină Web, adică zone de pe ecran sensibile la apăsarea
butonului stâng al mouse-ului.
O legãtură (link) este definită cu ajutorul etichetelor (tag-urilor) <a>…</a>, (de la "anchor"=ancoră)
textul, imaginea sau paragraful plasat între aceste etichete formând link-ul, și are atributele:
• href - adresa fișierului destinație;
• target - în ce fereastră se va deschide fișierul destinație:
o _blank pagina va fi încărcată într-o nouă fereastră;
o _parent pagina va fi încărcată în fereastra părinte;
o _top pagina va fi încărcată în fereastra top a cadrului;
o _self pagina va fi încărcată în aceeași fereastră.
• title - mică descriere asociată legăturii afișată în momentul în care mouse-ul se află deasupra
legăturii. Legătura poate fi:
• o pagină aflată în același director, realizată cu ajutorul atributului href, astfel: <a
href="nume_fisier_2.html">;
• o pagină de pe același disc local – se folosește adresa relativă la acel fișier : <a
href="exemple/list/listex_11.html"> ;
• o legătură către un site particular: <a href="http://www.ub.ro">;
• o imagine;
• o adresă de e-mail: <a href='mailto:test@test.ro?subject="subiect prestabilit"'>Trimite e-mail</a>;
• către un fișier oarecare: <a href="fisier.zip">

19. Formulare HTML

Un formular este un ansamblu de zone active alcătuit din butoane, casete de selecție, câmpuri de
editare etc. Formularele ajută la realizarea paginilor Web care permit utilizatorilor să introducă
informații și să le transmită serverului. Formularele pot fi de la simple la foarte complicate. Un
formular este definit într-un bloc delimitat de etichetele corespondente <form> și </form>.
<form method="post" action="mailto:youremail@email.com">
Name: <input type="text" size="10" maxlength="40" name="name"> <br />
Password: <input type="password" size="10" maxlength="10" name="password"><br />
<input type="submit" value="Send">
<input type="radio" name="culoare" value="inchis">Inchis
<input type="checkbox" name="pantofi" value="negru">Negru simplu
<select multiple name="tipuriMuzica" size="4">
<option value="pop" selected>Pop</option>
<input type="hidden" name="MAX_FILE_SIZE" value="100" /> <input name="file"
type="file"/> </form>
Elemente ale formularului
<form> Defines an HTML form for user input

38
<input> Defines an input control
<textarea> Defines a multiline input control (text area)
<label> Defines a label for an <input> element
<fieldset> Groups related elements in a form
<legend> Defines a caption for a <fieldset> element
<select> Defines a drop-down list
<optgroup> Defines a group of related options in a drop-down list
<option> Defines an option in a drop-down list
<button> Defines a clickable button

20. Tipuri de formatare CSS- creare şi apelare, exemple.

CSS (cascading style sheet = foi de stil în cascadă) permite separarea conținutului HTML de stilul
de afișare în pagină. Se utilizează codul HTML pentru aranjarea conținutului în pagina, însă toată
prezentarea (fonturi, culori, fundaluri, borduri, etc.) se realizează din fișierul CSS. În acest moment,
se pot folosi CSS-uri în două moduri, și anume interne paginii (inline sau dedicate) sau externe.

a) Stiluri inline - folosite prin intermediul atributului style=”sir de caractere” aplicat


elementelor html ce se “stilează“.
Exp : <p style=”text-align:center; color:green”> Am aplicat un stil cu verde pentru p, centrat.
Lista atributelor ce se stilează este separată prin punct şi virgulă, iar separarea atribut- valoare se
face prin intermediul “:”.
Specificarea unui stil inline e utilă când dorim formatarea individuală a unui element.

b) Stiluri dedicate - specificarea stilurilor în antet.


În acest caz, codul CSS va fi plasat în interiorul fiecărei pagini html în care vom folosi stilurile
respective, și codul CSS va fi scris între tagurile <head>…</head>. Acest lucru se face după cum
se poate vedea în exemplul de mai jos:
<head>
<title>titlu pagina</ti<style type="text/css">Aici se definesc stilurile CSS</style>
</title>
<style>
P { font:12 Arial; font-style:italic; text-align:left;
}
</style>
</head>

Folosind această metodă (stilurile interne), fiecare fișier HTML va conține codul CSS folosit la
stilizare. Asta înseamnă că atunci când se dorește realizarea unei schimbări de stil, (mărimea
fontului, culoare, etc.) va trebui să se opereze modificarea în toate paginile ce conțin acel stil.
Metoda descrisă până acum este bună atunci când avem de stilizat două, trei pagini, însă când

39
avem de a face cu siteuri de zeci sau sute de pagini este destul de neplăcut să modificăm toate
paginile.

c) Stilurile externe

În acest caz, se creează un fișier CSS extern (cu orice editor de text simplu: Notepad,
Wordpad) sau cu editoare avansate. De reținut că fișierul CSS va conține doar cod CSS și trebuie
salvat cu extensia *.css. Inserarea acestui fișier .css în pagina (X)HTML se face foarte simplu, prin
plasarea unui link în secțiunea <head>…</head> a fiecărei pagini în care dorim să folosim stilul
respectiv. Iată un exemplu de inserare a unui fișier extern .css într-o pagină HTML:

<link rel="stylesheet" type="text/css" href="Calea catre fisierul.css" />

21. Exemple de utilizare a funcţiilor Javascript

Javascript este un limbaj de programare simplu, de tip script, pentru definirea


comportamentului elementelor dintr-o pagina Web. Nu este acelaşi lucru cu mult mai complexul
limbaj de programare Java.
Javascript poate specifica, în mod obişnuit în doar câteva rânduri , răspunsurile la acţiuni sau
evenimente cum ar fi: deschiderea unei pagini, deplasarea mouse-ului într-un anumit punct sau
ştergerea unui anumit câmp dintr-un formular.

<HTML>
<HEAD>
<SCRIPT LANGUAGE="JavaScript">
function Salutare(){
var name = document.forms[0].elements[0].value; alert("Salut "+name);}
</SCRIPT>
</HEAD>
<BODY><br><br>
<p align=center>
<FORM NAME="form">
<b> Numele: <INPUT TYPE="text" NAME="nume">
<INPUT TYPE="button" VALUE="Scrie numele si apasa!" onClick="Salutare()">
</FORM>
</BODY>
</HTML>
Folosirea ferestrelor predefinite de dialog Alert, Prompt si Confirm

22. Definiţia clasică a probabilităţii

Probabilitatea unui eveniment reprezintă expresia numerică a posibilităţii de


realizare. Astfel noţiunea de experiment este legată de noţiunea de frecvenţă a unui
eveniment. In cadrul unui experiment pot avea loc mai multe evenimente. Numărul
total al acestora este definit ca “numărul cazurilor egal posibile”. Dintre acestea

40
conform unui criteriu de cercetare se pot realiza un anumit număr care este definit ca
“numărul cazurilor favorabile”.
Probabilitatea unui eveniment se calculează ca raport al celor două numere:

23. Scheme probabilistice clasice

 Schema bilei nerevenite


Se consideră o urnă în care avem bile albe de două culori diferite albe și negre: a-bile albe și b-bile
negre. Se extrag n-bile fără revenire. Există două modalități prin care se poate realiza astfel de
extragere: Se extrag toate cele n bile simultan; se extrag bilele una câte una fără a le reintroduce.
Se cere să se determine probabilitatea ca din cele n bile extrase, k să fie albe și n-k negre.
Probabilitatea cerută să fie:

 Schema bilei revenite.


Fie o urnă în care se află bile de două culori diferite: a-bile albe și b-bile negre. Se extrag n-bile cu
revenire. Se cere probabilitatea ca din cele n-bile extrase. K-bile să fie albe și n-k-bile sa fie negre.
Probabilitatea cerută este:

p – probabilitatea de a extrage o bilă albă.


q – probabilitatea de a extrage o bilă neagră
p+q=1

 Schema lui Poisson


Presupunem că avem n urne: U1, U2,…Un. În prima urnă avem a1-bile albe, b1-bile negre. În a doua
urnă avem a2-bile albe, b2-bile negre ș.a.m.d. În urna n avem a n-bile albe și bn-bile negre. Din
fiecare urnă se extrage câte o singură bilă. Se cere probabilitatea ca din cele n-bile extrase k-bile să
fie albe, n-k să fie negre. Probabilitatea cerută este dată de coeficientul lui x k din expresia:

pi – probabilitatea de a extrage o bilă albă din urna i


qi – probabilitatea de a extrage o bilă neagră din urna i
pi+qi=1

41
24. Conceptul de distribuţie (repartiție)

In teoria probabilităților si statistica, distribuția de probabilitate (repartiția) descrie probabilitatea


valorilor unei variabile (sau a mai multor variabile). In cazul variabilelor discrete, distribuția identifica
valorile si probabilitatea fiecărei valori. Pentru variabilele continue, distribuția identifica valorile
posibile si probabilitatea intervalelor de valori.

25. Generarea numerelor aleatoare

Se considera numar aleator orice număr care este obținut astfel încât valoarea sa nu poate fi
prevăzută anticipat.
O variabilă a cărei valoare este un număr determinat de evenimentul rezultat în urma unei
experienţe este numită variabilă aleatoare.
Generarea, cu ajutorul calculatorului a numerelor aleatoare, au la baza reguli prestabilite
(algoritmi de generare), afectând intr-o numita măsura caracterul aleator al acestui proces. Astfel
numerele obținute sunt considerate pseudoaleatoare.
Principalele clase de metode de generare a numerelor aleatoare sunt:
 Metoda manuala - presupune utilizarea zarurilor, ruleta, urne cu bile, etc. Metodele manuale
se folosesc rar în simularea numerică datorită vitezei reduse.;
 Metode fizice - se bazează pe analogii dintre unele procese fizice intrinsec întâmplătoare
(procese radioactive, procese electronice generatoare de zgomot alb etc.).;
 Metode de memorizare - presupune utilizarea unor tabele cu numere aleatoare. Prezintă
avantajul unei viteze ridicate , in schimbul consumului de memorie al calculatorului este
ridicat; Metodele de memorizare a numerelor aleatoare (tabelele) folosesc de regulă
memoria internă sau externă a calculatoarelor. Oferă avantajul reproductibilităţii.
Prin combinarea metodelor fizice cu memorizarea pe discuri sau benzi se obţin rezultate
bune din punct de vedere al preciziei, dar timpul de rulare al programului creşte datorită
duratei relativ mare de acces la fiecare înregistrare din memoria externă.
Se pot folosi şi alte tabele ca de exemplu: cartea de telefoane, tabelele de logaritmi etc. dar
numai după efectuarea unor teste de uniformitate
 Metode analitice - presupun utilizarea anumitor algoritmi de calcul. Se impune ca acești
algoritmi sa asigure un consum minim de timp si memorie pe parcursul rulării pe calculator.
Procedee analitice, folosesc relaţii de recurenţă. Un şir de numere se numeşte şir
de numere pseudoaleatoare dacă există o anumită formulă de recurenţă şi un număr natural
fix k astfel încât

26. Problema celui mai scurt drum în grafuri. Algoritmul lui Dantzig.

Algoritmul Dantzig: determină drumurile minime cu sursă unică în grafuri cu costuri nenegative.

42
43
44
27. Problema fluxului maxim în reţele. Algoritmul Ford-Fulkerson.

{s,A,M1,x,t} min{18,5,3,18}=3
{s,A,M2,x,t} min{18-3,4-0,4-0}=4
{s,B,M2,y,t} min{7-0,5-0,4-0,12-0}=4
{s,B,M2,z,t} min{7-4,5-4,3-0,20-0}=1
{s,B,M3,y,t} min{7-5,5-0,7-0,12-4}=2
{s,C,M2,z,t} min{25-0;10-0,3-1,20-1}=2
{s,C,M3,y,t} min{25-2,5-0,7-2,12-6}=5
{s,C,z,t} min{25-7,7-0,20-3}=7
{s,c,M4,z,t} min{25-14,8-0,10-0,20-10}=8
{s,A,M1,B,M3,z,t} min{18-7,5-3,5-2,3-0,20-18}=2
Tăietura desparte nodurile etichetate de cele neetichetate. Pentru capacitatea tăieturii nu se iau în
calcul drumurile nesaturate. 5+4+4+3+5+8+7=36

45
28. Rezolvarea sistemelor algebrice liniare – metode directe

29. Rezolvarea sistemelor algebrice liniare – metode iterative

30. Rezolvarea numerică a problemelor algebrice de valori şi vectori proprii

31. Aproximarea funcţiilor prin polinoame. Polinom Lagrange de interpolare

32. Aproximarea funcţiilor prin polinoame. Polinom Newton de interpolare

33. Generarea de conţinut HTML folosind PHP


Pagina care conţine codul PHP trebuie să fie salvată cu extensia php.
Un bloc de cod php este marcat de simbolurile <?php şi ?>.
Codul php nu este citit de browser, acesta neştiind să-l interpreteze. Codul este transmis la un
server, acesta execută codul şi transmite browserului codul html generat.
Generarea de conținut se poate realiza prin printarea codului HTML cu ajutorul funcției echo
’cod html’. Conținutul va fi sub forma unui string.
<?php
echo("<html><head><title>Salutare!</title></head>");
echo("<body bgcolor='fuschia'>");
?>

34. Utilizarea în PHP a datelor din formulare HTML. Metodele PUT şi GET

Formularele sunt utilizate pentru a trimite informații de la client la server. GET si POST sunt
cele doua metode utilizate de către browser pentru a trimite informații la server. Înainte ca browserul
sa trimită informațiile la server acesta le codifica cu ajutorul unui sistem de codare numit
URL(Uniform Resource Locator). Din fiecare căsuță de text se preia numele si valoarea, atribuindu-i

46
numelui valoarea introdusa de utilizator. Căsuțele de texte sunt separate prin caracterul „&”.Spatiile
sunt scoase fiind înlocuite cu caracterul +. După ce informațiile sunt codate sunt trimise la server.
GET – in urma trimiterii formularului completat la server , informațiile introduse de către utilizator
sunt afișate in link;
 aceasta este restricționată la 1024 de caractere;
 nu este recomandata sa fie utilizata daca in formular este introdusa o parola sau informații
ce nu doriți sa fie văzute de alți vizitatori ai sitului;
 aceasta nu poate fi utilizata pentru a trimite imagini sau documente Word la server
 in PHP informațiile trimise la server cu metoda get pot fi accesate utilizând vectorul asociativ
$_GET
POST – transfera informațiile cu ajutorul protocolului HTTP. Ca si in cazul metodei GET codate si
puse intr-un antet numit QUERY_STRING;
 nu are restricții la numărul de caractere pe care îl trimite;
 poate trimite atât caractere cat si date binare;
 date trimise trec prin antetul HTTP, făcând astfel informațiile transmise sa fie securizate
 in PHP informațiile pot fi accesate utilizând vectorul asociativ $_POST;

35. Utilizarea sistemului PHPMyAdmin

phpMyAdmin este un instrument software liber, scris în PHP, destinat să se ocupe de


administrarea MySQL. phpMyAdmin suportă o gamă largă de operaţiuni cu MySQL. Operaţiunile
cel mai frecvent utilizate sunt suportate de către interfaţa de utilizator (gestionarea bazelor de date,
tabele, câmpuri, relații, indici, utilizatori, permisiuni, etc.), în timp ce încă mai au capacitatea de a
executa direct orice declaraţie SQL.
PHPMyAdmin elimina nevoia de a folosi consola făcând crearea bazelor de date si a tabelelor
foarte simple. In Phpmyadmin poți face orice puteai face cu ajutorul consolei pentru mysql dar fară
a mai fi nevoie sa scrii cod SQL:
 Creezi , copiezi, redenumești si alterezi tabele;
 Poți efectua lucrări de întreținere a bazelor de date
 Șterge, adaugă si editezi câmpurile
 Executa orice declarație si interogare SQL
 Gestionezi tastele de pe câmpuri
 Exporți date in diverse formaturi
 Cauți la nivel global intr-o baza de date

36. Interogări simple SQL, apelabile din PHP

O interogare SQL poate fi apelata in PHP prin intermediul funcției mysql_query(‚cod SQL’).
Daca funcția returnează rezultate atunci (nu este de tip DM ) atunci rezultatele se pot prelua ca
un vector cu ajutorul funcției mysql_fetch_array(mysql_query(‚cod SQL’)).
//modul de scriere orientat obiect
$con = new mysqli($host,$username,$password,$database); // conectarea la baza de date
$codSQL="SELECT * FROM drepturi";
$rezultat = $con->query($codSQL); // apelarea codului SQL
$randuri=$rezultat ->num_rows; //numarul de rânduri returnate

47
while($row = $ rezultat ->fetch_assoc()) {$idNivel1=$row['idNivel1'] }

37. Metoda Greedy. Exemple

Această metodă se foloseşte în problemele în care, dată fiind o mulţime A cu n elemente, se


cere să se determine o submulţime B a sa, care să îndeplinească anumite condiţii (eventual un
anumit criteriu de optim).
Metoda Greedy este următoarea:
- se iniţializează mulţimea B la mulţimea vidă;
- se alege un anumit element din A;
- se verifică dacă elementul ales poate fi adăugat mulţimii B;
- procedeul continuă aşa, repetitiv, până ce au fost determinate toate elementele din B.
Exemplu: Într-o sală, într-o zi, trebuie planificate n spectacole. Pentru fiecare spectacol se
cunoaşte ora de începere (start[i]) şi durata spectacolului (durata[i]). Se cere să se
planifice un număr maxim de spectacole astfel încât să nu se suprapună.
Să considerăm A = mulţimea iniţială de spectacole şi B = mulţimea spectacolelor ce
vor fi alese.
Pentru a rezolva problema prin tehnica Greedy, prelucrarea care se va face asupra
mulţimii A este o ordonare crescătoare după ora de finalizare.
Apoi se iau spectacolele în ordine, astfel încât fiecare spectacol să înceapă după ce
s-a terminat cel anterior lui.
Exemplu: Numărul total de spectacole n=6, cu cei doi vectori:
start=(2,4,1,3,6,8) şi durata=(2,2,2,2,1,3). Se vor obţine orele de terminare a
spectacolelor: (4,6,3,5,7,11).
În urma sortării după criteriul orelor de terminare a spectacolelor, se va obţine
ordinea: 3,1,4,2,5,6.
Se ia spectacolul 3 (iniţial şi nu după ordonare!), care se termină la ora 3. Urmează
spectacolul 1, care începe, însă, la ora 2, deci se sare peste el. Următorul este spectacolul
4, care începe la ora 3 şi se termină la ora 5. Urmează spectacolul 2, care nu se ia. În
schimb, se ia spectacolul 5, care începe la ora 6, şi se termină la ora 7 , se verifică apoi
spectacolul 6. Acesta începe la 8, deci se adaugă. Ora de terminare a tututor spectacolelor
va fi, aşadar, 11.

38. Metoda Backtracking. Exemple

Există multe probleme a căror soluţie se poate reprezenta sub forma unui vector x=(x 1, ...,
xn)S, în care S=S1xS2x...xSn, unde S1,...,Sn sunt mulţimi finite, cu ⎪Si⎪=si elemente.
Metoda “Back-tracking” evită generarea tuturor soluţiilor posibile. Elementele vectorului x
primesc, pe rând, valori. Astfel, lui xk i se atribuie o valoare numai dacă au fost deja atribuite valori
lui x1, ..., xk-1. Mai mult, odată o valoare pentru xk stabilită, nu se trece direct la atribuirea de valori lui
xk+1, ci se verifică nişte condiţii de continuare referitoare la x1, ..., xk. Aceste condiţii stabilesc
situaţiile în care are sens să trecem la determinarea lui x k+1. Neîndeplinirea lor exprimă faptul că,
oricum am alege xk+1, ..., xn, nu vom putea ajunge la o soluţie rezultat, adică la o soluţie pentru care

48
condiţiile interne să fie satisfăcute. Dacă condiţiile de continuare nu sunt îndeplinite, se va alege alt
xk din Sk, iar dacă Sk s-a epuizat ne întoarcem la Sk-1.
Printre exemplele celebre de probleme în a căror rezolvare se poate folosi această
metodă de programare, amintim: problema celor opt regine; colorarea vârfurilor unui graf (a
unei hărţi); generarea permutărilor; problema circuitului hamiltonian (a comisului voiajor).

De pildă, să considerăm problema aşezării a n dame pe o tablă de şah cu nxn pătrate. În


acest caz, fireşte vom avea exact o damă pe fiecare coloană. Deci dama k va sta pe coloana k şi pe
una din cele n linii, pe linia notată x[k]. Aşadar, o soluţie a acestei probleme poate fi reprezentată
doar prin vectorul liniilor pe care sunt aşezate cele n dame, coloanele subînţelegându-se.
Pentru fiecare astfel de problemă sunt date anumite relaţii între componentele x 1, ..., xn ale
vectorului x, numite condiţii interne. S se numeşte spaţiul soluţiilor posibile.
Soluţiile posibile, care satisfac condiţiile interne se numesc soluţii rezultat.
În cazul problemei damelor, se cere ca damele să nu se atace. Acest lucru constituie condiţiile
interne. Aşezându-le câte una pe fiecare coloană, ele nu se vor ataca vertical. Pentru a nu se ataca
orizontal, trebuie ca să nu existe două dame pe aceeaşi linie (deci două dame i şi j cu x[i]=x[j]). De
asemenea, trebuie ca damele să nu se atace diagonal.
Astfel de probleme pot fi soluţionate folosind metoda “backtracking” (în caz că nu se
cunoaşte o metodă mai bună).

39. Metoda Divide et Impera. Exemple

Divide-et-impera este o tehnică (recursivă) ce constă în următoarele:


- dacă problema este rezolvabilă direct, atunci ea se rezolvă
- altfel se descompune în două sau mai multe probleme mai simple, de aceeaşi natură cu
problema iniţială (numite subprobleme), care se rezolvă prin aceeaşi metodă; soluţia
problemei iniţiale se obţine prin combinarea soluţiilor subproblemelor.
De exemplu, fie A=(a1,a2,...,an) şi trebuie efectuată o prelucrare oarecare asupra elementelor sale.
Mai mult, presupunem că pentru orice p, q naturale, cu 1≤p<q≤n, există m{p,...,q-1} astfel încât
prelucrarea secvenţei {ap,...,ak} se poate face prelucrând secvenţele{ap,...,am} şi {am+1,...,aq}. Se
apelează procedura descrisă mai jos, astfel:
DivideEtImpera(1,n,), în  obţinându-se rezultatul final.
Am notat prin  lungimea maximă a unei secvenţe {ap,...,aq} pentru care prelucrarea se poate face
direct (prin procedura Prelucreaza).
Procedura Combina realizează combinarea rezultatelor a două secvenţe vecine. m este obţinut prin
apelul procedurii Divide.
Iată deci varianta recursivă a metodei Divide-et-impera:

49
40. Operaţii cu structuri dinamice de date (liste, arbori)

Structurile dinamice de date sunt date structurate ale căror componente se aloca pe
măsură ce se creează, adică in mod dinamic. Pentru a crea o structura dinamica de date se impune
folosirea unui câmp care sa retina adresa de memorie la care se afla următorul element din
structura, deci un câmp care este un pointer. Astfel se realizează o înlănțuire după adrese.
In funcție de tipul înlănțuirii realizate intre componente, exista următoarele tipuri de organizări:
- structuri liniare: liste simplu înlănțuite si liste dublu înlănțuite, cu cazuri particulare: lista circulara,
stiva, coada.
- structuri arborescente ierarhice
- structuri rețea
Asupra unei liste liniare putem efectua următoarele operații:
- creare lista;
- parcurgere lista, pentru prelucrarea informației utile (afișare, calcule, sortare, căutare, etc.
- operații care se pot efectua in general si asupra vectorilor)
- inserarea unui nod in lista
- ștergerea unui nod din lista
Asupra unei structuri arborescente putem efectua următoarele operații:
- creare arborelui;
- parcurgere arborelui, pentru prelucrarea informației utile (afișare, calcule, sortare, căutare,
etc.)
- inserarea unui nod in arbore
- ștergerea unui nod din arbore

41. Aspecte fundamentale relative la SGBD: concept, obiective, funcţii, clasificare,


arhitecturi

Conceptul de SGBD
 Definirea unui SGBD -> SGBD este un ansamblu complex de programe care asigura
interfață intre o baza de date si utilizatorii acesteia. SGBD este componenta software a unui
sistem de baza de date care interacționează cu toate celelalte componente ale acestuia,
asigurând legătura si independenta intre elementele sistemului.
 Rolul unui SGBD -> rolul unui SGBD intr-un context de sistem de baza de date este de a:

50
 Defini si descrie datele in baza de date respectând niște restricții de integritate impuse
de modelul de date utilizat;
 Realizarea accesului la date pentru diferite operații – operatorii modelului de date;
 Întreține BD cu ajutorul unor instrumente specializate;
 Asigura protecția bazei de date sub cele doua aspecte: securitatea si integritatea
datelor;
Obiectivele unui SGBD
Obiectivul general al unui SGBD este de a furniza suportul software complect pentru
dezvoltarea de aplicații informatice cu baze de date. In acest sens, pentru ca un produs software sa
fie SGBD, el trebuie sa asigure un set minim de obiective:
 Asigurarea independenţei datelor faţă de programe. Se spune că o aplicaţie informatică
depinde de date, dacă modificarea structurii de memorare a datelor sau a strategiei de acces
la date afectează şi aplicaţia.
 Redundanţă minimă şi controlată a datelor. Spre deosebire de sistemele clasice (cu fişiere)
de prelucrare automată a datelor, stocarea informaţiilor în BD se face astfel încât datele să
nu fie multiplicate. Cu toate acestea, uneori, pentru a realiza performanţe sporite, în ceea ce
priveşte timpul de răspuns se acceptă o anumită redundanţă a datelor. Aceasta va fi însă
controlată pentru a se asigura coerenţa (corectitudinea datelor) BD. Exemplul de redundanţă
controlată acceptată este cea apărută la proiectare BD relaţionale prin tehnica de
normalizare.
 Facilităţi de utilizare a datelor. Această facilitate presupune ca SGBD să aibă nişte
componente specializate pentru diferite operaţii de utilizare:
 folosirea datelor de către mai mulţi utilizatori în diferite scopuri (aplicaţii). Acest lucru
reduce spaţiul de memorare necesar şi efortul de încărcare / validare a datelor;
 accesul cât mai simplu al utilizatorilor la date, fără ca ei să fie nevoiţi să cunoască
structura întregii BD, acest lucru rămânând în sarcina administratorului BD (ex.:
asistenţi tip Wizard);
 existenţa unor limbaje performante de regăsirea a datelor care permit exprimarea
interactivă a unor cereri de regăsire a datelor şi indicarea unor reguli pentru obţinerea
informaţiilor solicitate (ex.: limbajul relaţional SQL);
 oferirea posibilităţii unui acces multicriterial la date. SGBD stochează datele în
entităţile BD şi permite mai multe căi de acces. Pentru diferite moduri de adresare
SGBD creează dinamic, la momentul execuţiei, o serie de fişiere anexe (de index etc.)
care lasă neschimbate entităţile BD.
 Protecţia datelor. În sistemele de BD, protecţia datelor se asigură sub două aspecte:
securitatea şi integritatea.
 Securitatea (confidenţialitatea) datelor semnifică faptul că accesul la date se face
numai printr-o autorizare corespunzătoare şi doar controlat (sarcina administratorului
BD). În acest sens, SGBD permite: autorizarea şi controlul accesului la date, utilizarea
viziunilor, realizarea unor proceduri speciale, criptarea datelor.
 Integritatea datelor se referă la corectitudinea (coerenţa) datelor şi este asigurată prin
protejarea acestora împotriva unor incidente intenţionate sau neintenţionate.
 Partajabilitatea datelor -> Partajabilitatea datelor se referă nu numai la aspectul asigurării
accesului mai multor utilizatori la aceleaşi date, ci şi la posibilitatea dezvoltării unor aplicaţii
fără a se modifica structura bazei de date. Problema partajabilităţii se pune la un nivel
superior pentru SGBD-urile care permit lucrul în reţea.
 Legăturile între date. Legăturile între date corespund asocierilor care se pot realiza între
obiectele unei aplicaţii informatice. Orice SGBD trebuie să permită definirea şi descrierea
structurii de date, precum şi a legăturilor dintre acestea, conform unui model de date. Fiecare
51
tip de model de date permite anumite legături între date. Un SGBD, care implementează un
anumit model de date, va trebui să asigure şi realizarea legăturilor dintre datele
corespunzătoare în conformitate cu schema conceptuală.
 Performanţele globale. Performanţele globale ale aplicaţiei sunt influenţate de SGBD. Acesta
trebuie să gestioneze un volum mare de date de o complexitate ridicată, într-un anumit timp
de acces util pentru diferiţi utilizatori. Pentru toate aceste lucruri SGBD foloseşte diferite
metode de acces, tehnici de optimizare, tipuri de date.

Functiile unui SGBD


Realizarea obiectivelor prezentate anterior este asigurată de SGBD printr-o serie de componente ce
permit efectuarea unor operaţii specifice. În funcţie de natura lor şi de scopul urmărit, operaţiile pot
fi grupate pe activităţi. Activităţile acceptă şi ele o grupare pe funcţii astfel încât, una sau mai multe
activităţi, relativ omogene, vor realiza o anumită funcţie.
 Descrierea datelor -> SGBD, prin această funcţie, permite definirea structurii bazei de date
cu ajutorul limbajului de definire a datelor - LDD. Definirea datelor poate fi realizată la nivel
conceptual, logic şi fizic. Se descriu atributele (câmpurile) din cadrul structurii bazei de date,
legăturile dintre entităţile bazei de date sau dintre atributele aceleiaşi entităţi, se definesc
eventualele criterii de validare a datelor, metodele de acces la date, aspectele referitoare la
asigurarea integrităţii datelor.
 Manipularea datelor -> Funcţia de manipulare a datelor este cea mai complexă şi realizează
actualizarea şi regăsirea datelor din baza de date, cu ajutorul limbajului de manipulare a
datelor (LMD). Sunt realizate următoarele activităţi referitoare la date: încărcarea,
actualizarea, prelucrarea, regăsirea.
 Încărcarea datelor în baza de date se realizează prin operaţii automatizate (restricţiile
de integritate) sau programate ce asigură criteriile de validare a datelor.
 Actualizarea bazei de date constă în operaţiile de: adăugare, modificare, ştergere de
înregistrări. La operaţiile de adăugare şi de modificare se păstrează aceleaşi criterii de
validare care s-au folosit şi la activitatea de încărcare a datelor. Actualizarea se
realizează numai autorizat, prin asigurarea unei protecţii corespunzătoare a datelor.
 Prelucrarea datelor se realizează prin operaţiile de: selecţie, ordonare, inter-clasare
(compunere), ventilare (descompunere) efectuate asupra entităţilor bazei de date.
Acestea sunt, de obicei, operaţii pregătitoare activităţii de regăsire a datelor. Multe
dintre operaţiile de prelucrare sunt realizate cu ajutorul operatorilor din modelul de
date implementat de SGBD.
 Regăsirea (interogarea) datelor constă în operaţiile de: vizualizare (afişare pe ecran,
imprimare pe hârtie), răsfoire, editarea unor situaţii de ieşire. Situaţiile de ieşire pot fi
intermediare sau finale şi se pot obţine pe diferiţi suporţi tehnici de informaţie (ecran,
hârtie, mediu magnetic, mediu optic). Ele pot avea cele mai diferite forme (punctuale,
liste, rapoarte, grafice, imagini, sunet, video) şi se pot obţine după cele mai diferite
criterii de regăsire.
 Utilizarea datelor -> Funcţia de utilizare a datelor asigură mulţimea interfeţelor necesare
pentru comunicarea tuturor utilizatorilor cu baza de date. Pentru a realiza această funcţie
SGBD trebuie să asigure facilităţi pentru mai multe categorii de utilizatori ai BD:
neinformaticieni, specialişti, administratori.
 Funcţia de administrare -> Funcţia de administrare a datelor este de competenţa
administratorului bazei de date. Administratorul, care are o bogată experienţă de analiză,
proiectare şi programare, organizează şi administrează baza de date în toate etapele de
realizare a acesteia.
Clasificarea SGBD
52
Diversele SGBD, care au fost şi care sunt în exploatare pe diferite calculatoare şi sub diferite
sisteme de operare, impun o clasificare a lor după diferite criterii.
 După sistemele de calcul pe care se implementează
 SGBD pentru calculatoare mari se folosesc pentru baze de date foarte complexe şi
foarte mari (exemple: Oracle, DB2, IMS).
 SGBD pentru minicalculatoare se folosesc pentru baze de date complexe şi mari şi
au cunoscut o dezvoltare puternică în anii ‘80 (exemplu: Oracle).
 SGBD pentru microcalculatoare se folosesc pentru baze de date de complexitate şi de
mărime mici şi medii. Au o mare răspândire în momentul actual (exemple: Oracle,
DB2 etc.).
 După limbajul de programare utilizat
 SGBD cu limbaj gazdă este cel care are un limbaj de manipulare a datelor bazat pe
unul de nivel înalt (universal). Avantajul acestei soluţii este acela că se pot dezvolta
proceduri complexe de program, se pot realiza interfeţe om-maşină foarte bune, se
valorifică experienţa de programare din limbajele de nivel înalt (toate rezultă din
avantajele programării procedurale). Dezavantajul major este acela că formularea
cererilor de regăsire se face mai greu, de multe ori într-un mod inaccesibil utilizatorilor
finali. (exemplu PL-SQL din Oracle).
 SGBD cu limbaj propriu (autonom) este cel care are un limbaj de manipulare a datelor
specific. Acest limbaj de programare propriu este procedural şi are marele avantaj că
permite implementarea tuturor facilităţilor oferite de SGBD. În el se pot programa
proceduri complexe şi interfeţe puternice ca într-un limbaj universal, dar în plus se
realizează un acces uşor şi optimizat la baza de date. Dezavantajul este că un astfel
de limbaj nu poate fi utilizat decât de specialiştii în informatică (exemplu limbajul din
Visual FoxPro).
 După modelul logic de date implementat
 SGBD ierarhice sunt cele care implementează modelul de date arborescent (ierarhic)
şi au fost primele care s-au utilizat pentru gestionarea bazelor de date. Ele au o serie
de avantaje pentru domenii precise din lumea reală înconjurătoare, de exemplu
tehnologia construcţiei de maşini, dar au limite pentru alte domenii (exemplu: IMS).
 SGBD reţea sunt cele care implementează modelul de date reţea şi care au eliminat
multe din limitele celor ierarhice. Ele au o largă aplicabilitate pentru numeroase
probleme din lumea reală, dar sunt dificil de utilizat datorită complexităţii ridicate
(exemplu: IDMS).
 SGBD relaţionale sunt cele care implementează modelul de date relaţional şi au
aplicabilitate în majoritatea domeniilor din lumea reală. Ele pot fi folosite de o gamă
largă de utilizatori datorită facilităţilor oferite (generatoare, limbaj neprocedural etc.)
(exemple: Oracle, Visual FoxPro, Paradox, Access, Informix, Progress etc.).
 SGBD orientate obiect sunt cele care implementează modelul de date orientat obiect.
Ele se pretează bine la problemele foarte mari, de complexitate ridicată, precum şi
pentru tipurile noi de aplicaţii (proiectarea asistată, multimedia, sisteme deschise)
(exemple: O2, Orion, Jasmin etc.).
 După localizarea bazei de date
 SGBD centralizate sunt cele care gestionează datele amplasate într-o singură bază
de date centrală. La acestea au acces toţi utilizatorii autorizaţi pentru a efectua diferite
operaţii de manipulare a datelor. Toate calculatoarele care nu sunt legate în reţea şi
lucrează cu baze de date au instalat un SGBD centralizat. Tot un SGBD centralizat,
dar cu facilităţi de lucru în reţea, trebuie instalat şi în reţelele de calculatoare care au

53
plasată baza de date pe un singur calculator (de obicei pe server).(exemplu: Visual
FoxPro, Access)
 SGBD distribuite sunt cele care gestionează datele amplasate pe mai multe
calculatoare dintr-o reţea tratându-le ca un tot unitar. Complexitatea acestor SGBD
este ridicată, având componente speciale pentru realizarea conexiunilor şi tratarea
distribuită a datelor (exemplu: Oracle, DB2, Informix).
Arhitecturi de SGBD
De la apariţia lor şi până în prezent, SGBD au cunoscut o mare varietate. Există preocupări de
standardizare a arhitecturii SGBD care caută să definească un cadru general al lor. Dintre acestea,
sunt două arhitecturi de referinţă a unui SGBD propuse de grupul de lucru CODASYL şi respectiv
ANSI/SPARC. In ultimul timp, arhitectura de SGBD a evoluat spre o configuraţie cu trei categorii de
componente (nucleul, interfaţa, instrumentele), situaţie întâlnită la ultimele versiuni de sisteme
comerciale.
 Nucleul (motorul) conţine limbajul de descriere a datelor (LDD), limbajul de manipulare a
datelor (LMD), componente obligatorii în kit-ul minim de SGBD. Componenta este destinată
analiştilor, programatorilor şi administratorilor BD.
 Interfeţele sunt formate din: generatoarele de diferite tipuri (de meniuri, de videoformate, de
rapoarte etc.), elementele de CASE (Computer Aided Software Engeenering), interfeţe cu
limbaje de programare universale, interfeţe cu alte sisteme etc. Componenta este destinată
tuturor categoriilor de utilizatori: finali, intensivi, specialişti.
 Instrumentele sunt formate din: editoarele, navigatoarele (browsers), utilitarele (shells) de
diferite tipuri. Componenta este destinată, în principal, administratorului bazei de date, dar şi
altor categorii de utilizatori.

42. Algebra relaţională

• Reuniunea. Pentru două relaţii R şi S se poate nota: RUS, UNION(R,S), ADD(R,S).


Reuniunea relaţiilor R şi S este mulţimea tuplurilor care se găsesc în cel puţin una din
relaţiile R sau S. Această operaţie se poate aplica numai în cazul în care R şi S au
aceeaşi schemă. Dacă atributele au nume se cere ca, în plus, cele două liste de
nume să coincidă şi rezultatul va avea aceeaşi listă de nume pentru atribute.
• Diferenţa. Pentru două relaţii R şi S se poate nota: R-S, MINUS(R,S), REMOVE(R,S).
Diferenţa relaţiilor R şi S este mulţimea tuplurilor din R care nu sunt în S. Este
necesar să fie îndeplinite aceleaşi condiţii ca pentru reuniune.
• Produsul cartezian. Pentru două relaţii R şi S se poate nota: R×S, PRODUCT(R,S),
TIMES(R,S). Produsul cartezian al relaţiilor R şi S este mulţimea tuplurilor cu r+s
componente, în care primele r componente reprezintă un tuplu în R iar ultimele s
componente reprezintă un tuplu în S. Dacă atributele au nume, lista numelor
atributelor din rezultat este reuniunea disjunctă a celor două liste (folosind calificări
sau redenumiri pentru atributele cu aceleaşi nume în cele două relaţii).
• Proiecţia. Fie relaţia R de grad r. Proiecţia relaţiei R după atributele c1, c2,…, ck (k<=r) se
notează πc1, c2,…, ck(R), PROJECT(R; c1, c2,…, ck) şi este mulţimea tuplurilor de aritate
k în care se păstrează doar valorile corespunzătoare atributelor menţionate explicit în
proiecţie. Dacă relaţia R are asociate nume pentru atribute, acestea se pot păstra în
relaţia rezultată. Se observă că acesastă operaţie corespunde unor „tăieturi verticale”
în R.
• Selecţia. Fie F o formulă logică formată din operanzi care sunt constante sau nume de
componente în tupluri şi operatori aritmetici şi/sau logici. Selecţia relaţiei R în raport
cu formula F se notează σF(R), SELECT(R; F) şi reprezintă mulţimea tuplurilor din R
54
pentru care formula F devine adevărată. Relaţia rezultat are pentru atribute aceleaşi
nume ca şi relaţia R. Toate constantele care apar în F sunt incluse între apostrofuri.
• Joncţiunea. Este numită şi uniune sau join. O θ-uniune a relaţiilor R şi S după
coloanele i şi j, unde θ este un operator de comparaţie este notată UNION(R,S; iθj),
JOIN(R,S; iθj) sau R Xiθj S este constituită din mulţimea tuplurilor produsului cartezian
dintre R şi S, pentru care a i-a componentă a lui R se află în relaţia θ cu a j-a
componentă a lui S. Dacă R şi S au nume pentru atribute, în loc de i şi j se pot folosi
numele atributelor corespunzătoare. Joncţiunea este o operaţie derivată deoarece se
poate exprima cu ajutorul operaţiilor de bază prin formula: R Xiθj S= σiθ(r+j) (R×S).
• Intersecţia. Intersecţia relaţiilor R şi S, notată R∩S, INTERSECT(R,S), AND(R,S), este
constituită din mulţimea tuplurilor care se găsesc în ambele relaţii. Se aplică în
condiţiile specificate la reuniune. Intersecţia se poate exprima prin operaţiile de bază
cu formula: R∩S=R-(R-S).
• Diviziunea. Fie relaţiile R de aritate r şi S de aritate s, cu r >s şi S≠Φ. Diviziunea sau
câtul lui R prin S, notat R÷S, este mulţimea tuplurilor a de aritate r-s astfel încât,
pentru orice tuplu b al lui S, tuplul ab este în R. Dacă atributele celor două relaţii au
nume, atunci lista atributelor lui S trebuie să fie o submulţime a listei atributelor lui R
iar rezultatul are ca listă de atribute diferenţa celor două liste. Câtul se poate exprima
prin operaţiile de bază cu formula: R÷S= π1, 2,…, r-s(R)- π1, 2,…, r-s(π1, 2,…, r-s(R)×S)-R).

43. SGBD relaţionale: caracteristici, componente, arhitectură, mecanisme de


optimizare

SGBD caracteristici :
1. O bună reprezentare a realităţii înconjurătoare
Baza de date trebuie să ofere întotdeauna o imagine fidelă a realităţii prin informaţii fiabile şi
actualizate.
2. O independenţă a datelor faţă de prelucrări
Datele constituie imaginea fidelă a lumii reale, programele de aplicaţii trebuind să fie
concepute în raport cu această structură a datelor.
3. O non-redundanţă a informaţiei
Informaţia conţinută în baza de date trebuie să fie unică din punct de vedere semantic şi
fizic.
4. Securitatea şi confidenţialitatea datelor
Securitatea datelor trebuie asigurată prin proceduri fizice, iar confidenţialitatea prin proceduri
care să împiedice accesul utilizatorilor neautorizaţi.
5. Performanţe în exploatare
Orice cerere de prelucrare trebuie să fie satisfăcută într-un timp convenabil utilizatorului,
ceea ce presupune folosirea unor tehnici de optimizare pentru reducerea timpului de
prelucrare.

 Stocarea , regăsirea si reactualizarea datelor – funcție fundamentala


 Asigura tranzacțiile – acțiunile utilizatorului sau a unui program care accesează sau
modifica baza de date
 Servicii de control concurente – prezintă un mecanism care garantează ca baza de date
este corect reactualizata atunci când mai mulți utilizatori efectuează simultan tranzacții
asupra bazei de date
 Servici de securitate– doar utilizatorii autorizați au acces la bazele de date

55
 Suport pentru comunicarea intre date
 Trebuie să asigure că modificările datelor respectă anumite reguli
 Asigură suport pentru administrarea efectiva a bazelor de date

Prezintă cinci componente principale:


 Hardware – reprezintă suportul fizic pentru SGBD
 Software – reprezintă programele ce formează SGBD , programe de aplicație , sistemul
de operare local si atunci când e cazul software de rețea
 Date – includ datele care sunt stocate in tabele
 Proceduri – reguli care guvernează, proiectează si utilizează bazele de date
 Persoane – Patru tipuri de persoane implicate:
1. Administratori
2. Proiectanți
3. Programatori de aplicație
4. Utilizatori finali

Arhitectura unui SGBD cuprinde următoarele componente:


- baza de date propriu-zisă în care se memorează colecţia de date;
- sistemul de gestiune al bazei de date, care este un ansamblu de programe (soft) care
realizează gestiunea şi prelucrarea complexă a datelor;
- un set de proceduri manuale şi automate, precum şi reglementările administrative,destinate bunei
funcţionări a întregului sistem;
- un dicţionar al bazei de date (metabaza de date), ce conţine informaţii despre date,structura
acestora, elemente de descriere a semanticii, statistici, documentaţie etc. - mijloacele hard utilizate
(comune, specializate etc.);
- personalul implicat: (categorii de utilizatori: finali - (neinformaticieni); de specialit ate
(administrator), analişti - programatori, gestionari, operatori)

44. Normalizarea bazelor de date

Datele stocate în baza de date pot fi afectate de două mari probleme: redundanţa şi
inconsistenţa. Rezolvarea acestora presupune realizarea unei structuri în care datele să fie
accesibile unde este nevoie prin relaţii şi nu prin duplicare. Astfel, relaţiile dintre tabele fac posibilă
eliminarea redundanţei datelor şi păstrarea integrităţii referenţiale a datelor.
Eliminarea redundanţei se face prin realizarea unor legături între anumite date şi locurile unde
acestea sunt folosite, evitând astfel duplicarea lor, în fiecare loc în care acestea sunt folosite.
Integritatea datelor este protejată tocmai prin utilizarea datelor fără redundanţe, astfel încât
actualizarea lor să se facă într-un singur loc, fără posibilitatea de a greşi.
Pentru ca datele să poată fi relaţionate şi utilizate corect este necesară normalizarea bazei de
date. Acest lucru presupune trecerea tabelelor în următoarele formele de normalizare :
1. Prima formă de normalizare (FN1)
Într-o bază de date relaţională, entităţi diferite trebuie stocate în tabele diferite. Este
recomandabil ca pentru fiecare entitate (de lucru) să se creeze un tabel separat.
Un alt mod de prezentare a acestei forme de normalizare spune că valoarea unui atribut al
entităţi (modelat în baza de date printr-o coloană) nu poate lua valori multiple (ceea ce ar însemna
utilizarea mai multor coloane de acelaşi fel).
2. A doua formă de normalizare (FN2)

56
O tabelă este în a doua formă de normalizare dacă şi numai dacă se găseşte în prima formă
de normalizare şi, în plus, orice înregistrare dintr-o tabelă poate fi identificată în mod unic printr-o
cheie primară şi fiecare atribut (valoare dintr-o coloană) depinde în mod direct de întreaga cheie
primară.
Pentru a asigura dependenţa faţă de întreaga cheie primară, este necesar ca în tabelele care
au cheie compusă, fiecare atribut să depindă de toate coloanele care compun cheia primară.
Dacă un tabel are cheie unică el intră automat în a doua formă de normalizare.
3. A treia formă de normalizare (3NF)
O tabelă este în a treia formă de normalizare dacă şi numai dacă se găseşte în a doua formă
de normalizare şi, în plus, câmpurile care nu sunt chei primare sunt independente unul de altul, în
sensul că nici un câmp să nu să fie obţinut prin aplicarea unei funcţii asupra valorii altor câmpuri
(câmpurile care nu sunt chei primare sunt independente între ele şi depind numai de cheia primară).
Încălcarea acestei forme poate fi detectată analizând care câmpuri trebuie actualizate atunci
când se actualizează un alt câmp.
În afară de aceste trei forme de normalizare, în literatura de specialitate mai sunt descrise şi
altele. În general însă, acestea trei sunt acoperitoare şi se acceptă că o bază de date este
normalizată dacă se găseşte în a treia formă de normalizare.

1. Se proiectează relaţia iniţială, aflată în FN1, pe alte relaţii, pentru a elimina dependenţele
funcţionale care nu sunt complete. Se obţine o mulţime de relaţii în FN2.
2. Se proiectează relaţiile obţinute în pasul 1 pe alte relaţii, pentru a elimina dependenţele
funcţionale tranzitive. Se obţine o mulţime de relaţii în FN3.
3. Se proiectează relaţiile obţinute în pasul 2 pe alte relaţii, pentru a elimina dependenţele
în care partea din stânga nu este o supracheie. Se obţine o mulţime de relaţii în FNBC.
4. Se proiectează relaţiile obţinute în pasul 3 pe alte relaţii, pentru a elimina toate
dependenţele multivaloare care nu sunt şi dependenţe funcţionale. Se obţine o mulţime
de relaţii în FN4.
5. Se proiectează relaţiile obţinute în pasul 4 pe alte relaţii, pentru a elimina orice
dependenţă de uniune care nu este implicată de o cheie. Se obţine o mulţime de relaţii în
FN5.

45. Limbajul SQL

SQL este un limbaj neprocedural sau declarativ, deoarece utilizatorul lui descrie numai informaţiile
pe care vrea să le obţină în urma interogării, fără a fi nevoie să stabilească modalităţile de a ajunge
la rezultatele dorite.
 Toate cererile SQL folosesc optimizarea cererilor - o parte a RDBMS - pentru a determina
rapid gasirea datelor specificate
 La un moment dat, SQL proceseaza o singura inregistrare. Cea mai comuna forma a unui set
de inregistrari este un tabel.
 SQL pune la dispozitie comenzi pentru o varietate de task-uri incluzand:
o date interogate
o inserarea, extragerea si stergerea rindurilor intr-un tabel.
o crearea, modificarea si stergerea obiectelor de tip baza de date
o controlul accesului la baza de date si la obiectele de tip baza de date.
o garantarea consistentei bazei de date

SQL a devenit un limbaj standard industrial pentru bazele de date relationale . Institutul National
American de Standarde (ANSI) a adoptat SQL ca limbaj standard pentru RDBMS in anul 1986.

57
Organizatia Internationala de Standarde (ISO) a adoptat deasemenea SQL ca limbaj standard
pentru RDBMS. Toate RDBMS-urile suporta unele forme de SQL si toti vinzatorii de RDBMS se
aliniaza la standardele ANSI.

Setul de comenzi SQL


este comanda cea mai utilizata ; este folosita pentru obtinerea informatiilor din bazele de
SELECT
date

INSERT
aceste trei comenzi sunt utilizate pentru a introduce noi rinduri, pentru a actualiza rindurile
UPDATE existente si stergerea rindurilor nedorite din tabelele bazelor de date respective. (Ele sunt
cunoscute in ansamblu ca DML sau comenzi ale limbajului de manevra a datelor)
DELETE

CREATE
aceste trei comenzi sunt utilizate dinamic pentru a crea, utiliza si sterge orice structura de
ALTER date, de exemplu, tabele, expuneri, indecsi. (Ele sunt cunoscute sub numele colectiv DDL
sau comenzi ale limbajelor de definire a datelor).
DROP

aceste doua comenzi sunt utilizate pentru a acorda sau a revoca drepturile de acces
GRANT
pentru bazele de date si structurile din Oracle.
REVOKE

46. Elementele unei baze de date Oracle

Procesul este o prelucrare (job) a sistemului care presupune un program unic, ce rulează, la un
moment dat, cu propria lui zonă de lucru.
Zona de lucru este o parte din memoria internă (buffer) alocată de sistemul Oracle pentru diferite
operaţii temporare: execuţia tranzacţiilor, conectarea utilizatorilor – sesiunea de lucru etc.
Indexul este o structură fizică de date asociată unei tabele sau unui cluster. Indexarea are rolul de
a obţine date ordonate după diferite criterii (chei). Cheia de indexare este formată din una sau mai
multe coloane dintr-o tabelă. Oracle foloseşte patru metode de indexare: arbori B simpli, arbori B
compuşi, cheie inversă, bitmap.
Viziunea (view) este o tabelă virtuală construită din una sau mai multe tabele de bază, fără a ocupa
spaţiul fizic. Ea este, de fapt, o cerere de regăsire SELECT stocată în dicţionarul de date şi
contribuie la creşterea protecţiei datelor.
Clusterul este o grupare fizică a informaţiilor din una sau mai multe tabele şi are rolul de a creşte
eficienţa regăsirii datelor.
Contextul o zonă de memorie extensibilă dinamic, alocată şi gestionată de Oracle pentru a putea
executa o comandă.
Cursorul este un pointer (identificator) spre zona de context necesar manipulării acesteia. Oracle
foloseşte două tipuri de cursor: implicit şi explicit. Cursorul implicit este creat şi gestionat automat
de sistem şi utilizat pentru o serie de comenzi pentru definirea sau manipularea datelor (CREATE,
ALTER, INSERT, DELETE etc.). Cursorul explicit este creat şi gestionat de programator, în special
pentru cererile de regăsire (SELECT).
58
Tranzacţia este un ansamblu omogen de operaţii (în special actualizări) într-o sesiune utilizator. Ea
are rolul de a asigura coerenţa datelor şi funcţionează binar: se validează în totalitate sau deloc.
Tranzacţia poate fi descompusă în subtranzacţii prin stabilirea unor puncte de salvare
(SAVEPOINT).
Pseudo-coloane şi pseudo-funcţii sunt variabile de sistem utilizate pentru a avea acces la
parametrii interni ai sistemului. Ele se pot utiliza pentru tabelele utilizator sau pentru cele standard
(exemple: LEVEL, ROWID, NEXVAL şi respectiv USER, UID, SYSDATE).

47. Limbajul PL/SQL. Elementele acestuia.

PL/SQL (Procedural Language) este un limbaj procedural, propriu sistemului Oracle, care lucrează
stil compilator şi care dă posibilitatea să se dezvolte structuri procedurale de program, suportând în
acelaşi timp o parte dintre comenzile SQL. El a fost dezvoltat pe o structură iniţială de program
Pascal, ulterior fiindu-i adăugate numeroase extensii.
Câteva dintre elementele de limbaj din PL/SQL sunt prezentate, în sinteză, în continuare.
Instrucţiunea PL/SQL are drept terminator caracterul punct şi virgulă (;).
Expresiile în PL/SQL sunt formate din operatori şi operanzi. Tipul unei expresii este dat de tipul
operatorilor utilizaţi.
Operatorii sunt de următoarele tipuri: aritmetici (+,-, *, /, **), logici (AND, OR, NOT), de comparaţie
(=, !=, <, >, <=, >=), alţi operatori speciali (LIKE; IN; BETWEEN etc.).
Operanzii pot fi variabile, constante, atribute (%TYPE, %FOUND etc.), funcţii.
Unitatea de bază pentru structurarea unui program în limbajul PL/SQL este blocul.
Structura unui bloc este:
DECLARE DECLARE
Instrucţiuni declarative (neexecutabile) v_cod agenti.codagent%type;
BEGIN v_nume agenti.numeagent%type;
Instrucţiuni executabile (proprii sau din SQL) CURSOR c1 IS SELECT
EXCEPTION codagent,numeagent FROM agenti;
Rutine pentru tratarea erorilor (excepţiilor) BEGIN
END; OPEN c1;
FOR i IN 1..5 LOOP
FETCH c1 INTO v_cod,v_nume;
INSERT INTO mesaje
VALUES(v_cod,v_nume);
END LOOP;
CLOSE c1;
END;

Comentariul se indică ca un text scris între /* şi */ (analog ca în SQL) sau după două caractere
liniuţă de unire (- -).
Instrucţiunile dintr-un bloc pot fi precedate de <<etichetă>>, care se poate folosi apoi pentru
referire.
Limbajul PL/SQL acceptă şi subprograme care pot fi de următoarele tipuri: proceduri
(PROCEDURE), funcţii (FUNCTION), pachete (PACKAGE), declanşatori (TRIGGER).
Comenzi din SQL suportate în blocuri PL/SQL
INSERT, UPDATE, DELETE, SELECT, COMMIT, ROLLBACK, SAVEPOINT, LOCK, TABLE, SET
TRANSACTION.
Instrucţiuni proprii limbajului PL/SQL
:= este instrucţiunea de atribuire.
59
BEGIN desemnează începutul părţii executabile a unui bloc.
CLOSE închide un cursor explicit.
DECLARE marchează începutul unui bloc şi a părţii neexecutabile a acestuia.
Pentru a declara variabile şi constante se folosesc clauzele: NUMBER, CHAR, VARCHAR, DATE,
BOOLEAN, atributele (%nume).
Pentru a declara un cursor se foloseşte clauza: CURSOR.
Pentru a declara o excepţie (tratarea erorilor) se foloseşte clauza: EXCEPTION.
END încheie o serie de instrucţiuni PL/SQL: bloc – END, structură repetitivă – END LOOP, structură
alternativă – END IF.
EXCEPTION marchează începutul părţii de tratare a erorilor dintr-un bloc.
EXIT forţează ieşirea necondiţionată dintr-o structură nesecvenţială de program.
FETCH accesează următoarea linie din mulţimea selectată de un cursor explicit.
GOTO salt necondiţionat la o etichetă dintr-un bloc.
IF…END IF structura alternativă simplă de program.
LOOP… END LOOP structura repetitivă de program tip WHILE sau FOR
NULL este instrucţiunea care nu are nici un efect şi se foloseşte pentru structurarea şi lizibilitatea
blocului.
OPEN deschide un cursor explicit.
RAISE opreşte execuţia unui bloc şi transferă controlul unei secţiuni de tratarea excepţiilor.
SELECT…INTO instrucţiune de regăsire, care întoarce o linie dintr-o tabelă şi o plasează într-o
variabilă de memorie indicată prin clauza INTO.

48. Algoritmi numerici paraleli. Metode de rezolvare a sistemelor de ecuaţii liniare.


Algoritmi numerici paraleli. Metode de rezolvare a ecuaţiilor neliniare.

Metoda eliminării Gauss


In prima etapa numim triangularizare (substituție înainte) se elimina succesiv in n-1 pași
necunoscutele xi, i =1, 2 , ..., n-1 din ecuațiile sistemului ceea ce are rezultat eliminarea elementelor
situate sub diagonala principala a matricei A si transformarea acestora intr-o matrice superior
triangulara.
In pasul 1 se obține:

(2)

Sau cu notațiile :

(3)

Rezulta:

60
(4)

In pasul i-1 eliminările sistemului de ecuație devine:

(5)

Sau in forma restrânsă:

(6)

In pasul l se obține:

(7)

Cu:

(8)

In final după consumarea pasului n-1, sistemul este complet triangularizat:

(9)

Sau utilizând o scriere simbolică:


[0\S] ∙ [X] = [B’] (10)

Metoda lui Gauss este un algoritm folosit pentru rezolvarea sistemelor de ecuaţii liniare ce poate fi
uşor programabilă pe calculator. Întrucât această metodă se bazează pe reducerea succesivă a
61
necunoscutelor, sistemul transformându-se, pas cu pas, în alte sisteme echivalente, ale căror
ecuaţii au un număr de necunoscute care se micşorează, ea se mai numeşte şi metoda eliminării
parţiale.
Pentru prelucrarea treptata a sistemului, se utilizează transformări elementare, care conduc la
sisteme echivalente:
 Reașezarea ecuațiilor in alta ordine;
 Reașezarea necunoscutelor in alta ordine;
 Înmulțirea unei ecuații cu un număr nenul;
 Adunarea ecuațiilor membru cu membru.
Aplicând in mod convenabil astfel de transformări, se ajunge la una din situațiile:
 Sistemul final are forma triunghiulara, soluția fiind unica (compatibil determinat)
 Sistemul final are forma trapezoidala, cu mai multe soluții )compatibil nedeterminat)
 Sistemul final conține o contradicție, fără soluții(incompatibil)
Practic, aplicarea metodei lui Gauss, consta in parcurgerea următorilor pași:
 Scriem matricea extinsa a sistemului (adică matricea sistemului, căreia ii anexam coloana
termenilor liberi);
 Aplicam transformări elementare (ca si cum am lucra cu ecuațiile) asupra acestei matrice,
pana când aceasta ia forma triunghiulara sau trapezoidala;
 Consideram sistemul liniar căruia ii corespunde aceasta matrice extinsa (el este echivalent
cu cel dat!);
 Daca in acest sistem apare o contradicție, atunci sistemul este incompatibil;
 Daca nu apare nici o contradicție, atunci sistemul este compatibil sau compatibil
nedeterminat, după cum el are forma triunghiulara sau trapezoidala;
 Soluția sistemului (când aceasta exista!) se afla ușor, parcurgând drumul înapoi, de la ultima
ecuație (cu cele mai puține necunoscute), către prima (cu cele mai multe necunoscute).

Algoritmul 3.2.1.1.
Intrări: n = dimensiunea sistemului
A = matricea sistemului
b = vectorul termenilor liberi
Ieşiri: A = matricea sistemului triunghiular
b = termenii liberi ai sistemului triunghiular
x = vectorul necunoscutelor
{
pentru k  1 : n  1
pentru i  k  1 : n
{
t  aik / a kk
ai, k : n  ai, k : n  t  a k , k :n
bi  bi  t  bk
}
pentru i  n : 1
{
suma  suma + ai, i 1:n  xi 1:n
xi  (bi - suma) / aii
}

62
}.

Metode numerice paralele de rezolvare a ecuațiilor neliniare


Pentru rezolvarea ecuațiilor neliniare pe R exista diferite metode seriale.
2.1.1. Metoda paralela a înjumătățirii intervalului (metoda bisecției) Principiul dihotomiei

Fie ecuația neliniara f(x)=0, unde f:[a,b]→R este o funcție continua. Daca f(a)f(b) < 0, atunci ecuația
data are cel puțin o soluție reala in intervalul (a,b). Se cere determinarea aproximativa, cu o eroare
data, a soluției reale ale ecuației date.
ab ab
Se poate atunci considera punctul , mijlocul intervalului [a,b] şi calcula f   şi localiza 
2  2 
ab
în noul interval având pentru extremităţi şi punctul a sau b după cum f (a ) sau f (b) este de semn
2
ab
contrar lui f   . La fiecare iteraţie se înjumătăţeşte lungimea intervalului. La începutul iteraţiei n,
 2 
ba
lungimea intervalului era .
2n

Din punct de vedere al unei ecuații cu mai multe procesoare, putem considera următoarele cazuri:
A. Cazul I – ecuația data are o singura soluție reala in intervalul [a,b].

Situația unei rădăcini reale in intervalul [a,b]

In aceasta situație, metoda înjumătățirii intervalului consta in definirea a trei șiruri {a n}, {bn}, {cn},
astfel:
ab
Inițializare: a0 = a, b0 = b, c0=(a+b)/2 . Fiind construiți termenii an-1, bn-1, cn-1 definim, pentru
2
n≥1:
 an = cn-1 si bn = bn-1 daca f(an-1)f(cn-1) > 0
 an = an-1 si bn = cn-1 daca f(an-1)f(cn-1) > 0
Daca f(cn-1) = atunci am = an-1, bm = bn-1, cm = cn-1, m ≥ n. Determinarea elementelor celor
trei siruri poate fi facuta simultan pe un sistem paralel, fiecare sir fiind calculat de catre un procesor.
Un al patrulea poate fi folosit la calcularea valorilor functiei in diferite puncte si la obtinerea
rezultatului.

63
B. Cazul II – ecuația data are mai multe rădăcini reale in intervalul [a,b].

Situația in care exista mai multe rădăcini reale in [a,b]

In aceasta situație, problema se descompune in mai multe subprograme, după cum intervalul inițial
[a,b] se descompune in subintervale care izolează cate o singura rădăcină reala. Lucrând cu mai
multe procesoare, fiecare poate determina soluția aproximativa corespunzătoare subproblemei
repartizata.

Algoritmul 2.2.8.1.
Intrări: a, b = capetele intervalului
f = funcţia
 = precizia
Ieşiri: x = rădăcina localizată
{
x  ( a  b) / 2
cât timp
| f ( x ) |   şi b  a  
{
dacă
f (a) f ( x)  0
atunci
bx
altfel
ax
x  ( a  b) / 2
}
}.

49. Scopul Inteligenţei Artificiale. Definiţii, abordări, aplicaţii.

Definitie1: Inteligenta Artificiala se ocupa de studiul si crearea sistemelor de calcul si a programelor


care prezintă o forma de inteligenta: sisteme care învață noi concepte, care pot raționa si deduce
concepte utile intr-un domeniu al lumii înconjurătoare, sisteme care pot înțelege limbajul natural sau
percepe si înțelege o imagine, intr-un cuvânt sisteme care necesita capacități inteligente specifice
omului.
64
Definiție 2: Inteligenta artificiala este studiul facultăților mentale pe baza modelelor computaționale.
Inteligenţa Artificială este o ramură a Stiinţelor Calculatoarelor care studiază crearea de
calculatoare sau maşini la fel de inteligente ca oamenii. Aceasta se realizează prin studierea
modului de lucru al creierului uman, adică observarea modului de învăţare (achiziţia de informaţii şi
reguli de utilizare a acestora), decizie (utilizarea de reguli pentru a ajunge la concluzii aproximative
sau definitive) şi acţiune (autocorecţie) a omului în timp ce încearcă să resolve o problemă.
Majoritatea textelor şi cercetătorilor din domeniu definesc această ramură a ştiinţei ca “studierea şi
proiectarea agenţilor inteligenţi”, unde un sistem inteligent este un sistem care percepe
împrejurimile sale şi acţionează astfel încât să-şi maximizeze şansele de reuşită.

Abordări:
1. Implementarea (simularea) inteligenţei umane în sisteme artificiale, “inteligenţă artificială
tare” (strong AI), însemnând că sistemul înţelege, gândeşte, învaţă şi acţionează la fel ca un om.
Până în acest moment încă nu a fost creat un model de inteligenţă tare sau sistem care să simuleze
întradevăr modul de gândire uman, problemă care este dealtfel foarte greu de rezolvat
2. Crearea de sisteme expert, “inteligenţă artificială slabă” (weak AI), adică sisteme care pot
prelua anumite activităţi umane şi pot acţiona ca şi cum ar fi inteligente. Astfel de sisteme sunt
folosite în operaţiunile din producţie, în educaţie, pieţe financiare, clădiri inteligente, transport, chiar
şi în aparatele electrocasnice.
La ora actuală cea mai puternică dezvoltare este undeva între cele două obiective, şi anume
crearea de sisteme care utilizează gândirea umană ca un ghid, neavând rolul de a o modela
perfect.

Aplicații
 In vizualizarea cu calculatorul: recunoaștere;
 In robotica: vehicule cu diferite grade de autonomie;
 In procesarea limbajului natural: sisteme compatibile de traduceri simple;
 In sisteme expert
 In diagnosticarea medicala, in domenii foarte înguste;
 In înțelegerea vorbirii: sisteme capabile de recunoașterea a câteva mii de cuvinte emise
continuu;
 In planificarea si programare: sisteme capabile de rutarea vehiculelor, de dirijarea operațiilor
in procesele industriale;
 In jocuri: sisteme care pot juca șah la nivel de campionat mondial.

50. Metode de căutare în spaţii de soluţii: căutare neinformată, căutare informată

Căutarea neinformata:
 Raționamentul consta in explorarea alternativelor
 Căutarea in lățime (nodurile noi sunt inserate la sfârșitul frontierei)
 Căutarea bidirecționala
 Căutarea in adâncime (nodurile noi sunt inserate la începutul frontierei)
 Căutarea limitata in adâncime
 Căutarea iterativa in adâncime

65
Căutarea in lățime este completa si optima daca un pas are costul 1. Aceasta poate rula la infinit
daca problema nu are soluții si spațiul de căutare este infinit sau stările pot fi vizitate de mai multe
ori.
Căutarea informata:
 Factorii de ramificare mari sunt o problema serioasa
 Trebuie găsite o modalitate de a reduce numărul de noduri vizitate
 Metodele de căutare euristice încearcă alegerea „inteligenta” a nodurilor care trebuie
expandate

51. Demonstrarea automată

Sistemele de deducţie automatã îşi datoreazã apariţia şi existenţa la doi factori principali: progresele
realizate în construcţia echipamentelor de calcul pe de-o parte şi sistematizarea capacitatilor umane
de a sintetiza concluzii din premise pe de alta. Cum în legatura cu prima componentã care a
determinat dezvoltarea sistemelor de deducţie automatã (evoluţia calculatoarelor) existã nenumãrate
descrieri, vom discuta în continuare pe scurt cea de-a doua componentã: dezvoltarea sistemelor de
deducţie matematicã (automatã). În momentul de faţa, deducţia automatã a devenit o disciplinã
fundamentalã nu numai în cadrul inteligenţei artificiale (AI), dar şi în cadrul stiinţei calculatoarelor în
general.
Se ştie cã programarea nu numai cã se bazeazã pe logicã (cum s-a anticipat de Mc Carthy în anii
`60) dar poate fi identificatã cu logica. Acest lucru este evident în programarea logicã, unde ecuaţia lui
R. Kowalski (1979) îşi gãseşte cea mai potrivitã verificare:
CALCUL (ALGORITM) = DEDUCŢIE + CONTROL.

52. Sisteme inteligente. Sisteme multiagent. Metaeuristici. Exemple.

Caracteristicile sistemelor multiagent


 fiecare agent are informaţii incomplete despre problemă şi mediu
 fiecare agent are o capacitate limitată de calcul, insuficientă pentru a rezolva singur
problema
 resursele sunt descentralizate
 calculele se efectuează asincron

Utilitatea sistemelor multiagent


 modelarea sistemelor de natură distribuită
 capacitatea limitată a unui singur agent de a rezolva probleme reale
 robusteţe - căderea unor agenţi nu conduce la căderea sistemului
 toleranţă în caz de eroare
 scalabilitate - se pot adăuga noi agenţi pentru creşterea randamentului
 deţin în mod implicit potenţialul unui comportament inteligent, pe baza interacţiunilor dintre
componente

Tipuri de sisteme multiagent


Keith Decker consideră importante patru dimensiuni ale inteligenţei artificiale distribuite:
 granularitatea agenţilor: poate fi mare sau fină

66
 eterogenitatea cunoştinţelor agenţilor: cunoştinţele din sistem pot fi redundante, atunci când
mai mulţi agenţi deţin aceleaşi informaţii, sau specializate, dacă agenţii deţin cunoştinţe
distincte
 metodele de control distribuit: agenţii pot coopera sau pot fi în competiţie; organizarea lor
poate fi ierarhică sau orice formă de control centralizat poate fi evitată, agenţii intrând în
componenţa unor echipe; de asemenea, rolul jucat de agenţi (adică funcţia îndeplinită,
mulţimea atribuţiilor) poate fi constant, static, sau aceştia îşi pot schimba rolurile în funcţie de
necesităţi
 posibilităţile de comunicare: comunicarea se poate face prin intermediul mesajelor transmise
direct de la un agent la altul sau prin intermediul unei memorii comune (sisteme blackboard);
de asemenea, comunicaţiile pot fi clasificate după nivelul de abstracţiune al conţinutului: de
nivel înalt sau scăzut.

Metaheuristicile sunt strategii la nivel înalt de explorare a spaţiului soluţiilor, folosindu-se de


diverse metode. În ansamblu, proprietăţile fundamentale ale metaheuristicilor sunt următoarele:
• sunt strategii care „ghidează” procesul de căutare
• scopul lor este de a explora eficient spaţiul soluţiilor pentru a găsi soluţii(sub-) optimale
• tehnicile folosite acoperă o gamă largă de algoritmi, pornind de la o simplă căutare locală şi
ajungând până la algoritmi complecşi de învăţare
• algoritmii metaheuristici sunt aproximativi şi de obicei nedeterministici
• pot include mecanisme de evitare a optimelor locale
• nu sunt specifice numai anumitor probleme
• pot apela la cunoştinţe specifice domeniului prin intermediul unor heuristici locale care sunt
controlate de un nivel superior .

53. Gramatici generative pentru o submulţime a limbii române. Implementare în


PROLOG. Utilizarea listelor în PROLOG. Exemple
predicates
determinator(string)
substantiv(string)
adjectiv(string)
verb(string)
propozitie(string)
grupnominal(string)
grupverbal(string)
grupdeadjective(string)
conjunctie(string)
clauses
determinator(un).
determinator(o).
determinator(oricare).
substantiv(femeie).
substantiv(barbat).
substantiv(caine).
substantiv(pisica).
adjectiv(destept).
adjectiv(frumoasa).

67
conjunctie(si).
conjunctie(sau).
conjunctie(",").
verb(iubeste).
verb(uraste).
propozitie(P) if grupnominal(GN),
grupverbal(GV),
concat(GN, " ",GNS),
concat(GNS, GV, P).
grupnominal(X) if substantiv(X).
grupnominal(X) if determinator(Y),
substantiv(Z),
concat(Y, " ", YS),
concat(YS, Z, X).
grupverbal(X) if verb(X).
grupverbal(X) if verb(V), grupnominal(GN),
concat(V, " ", Z),
concat(Z, GN, X).
grupdeadjective(X) if adjectiv(X).
grupdeadjective(X) if adjectiv(A),
conjunctie(C),
grupdeadjective(GDA),
concat(A, " ", AS),
concat(AS, C, ASC),
concat(ASC, " ", ASCS),
concat(ASCS, GDA, X).

Utilizarea listelor în PROLOG. Exemple

domains
lista = string*
predicates
fa_lista(string, lista)
clauses
fa_lista("", []) if !. %cut - valoare true intoatdeuana
fa_lista(S, L) if fronttoken(S, T, R),
fa_lista(R, L1),
L = [T | L1].

54. Definirea unor predicate PROLOG pentru transformarea numerelor din scrierea
cu cifre în scrierea cu litere.

domains
lista=integer*
predicates
trad(symbol,lista,string)
clauses
trad(unitati,[0],"").
trad(unitati,[1],"unu").
68
trad(unitati,[2],"doi").
trad(unitati,[3],"trei").
trad(unitati,[4],"patru").
trad(unitati,[5],"cinci").
trad(unitati,[6],"sase").
trad(unitati,[7],"sapte").
trad(unitati,[8],"opt").
trad(unitati,[9],"noua").
trad(zeci,[1,0],"zece").
trad(zeci,[1,1],"unsprezece").
trad(zeci,[1,4],"paisprezece").
trad(zeci,[1,6],"saisprezece").
trad(zeci,[1,X],S) if
X<>0, X<>1, X<>6, X<>4,
trad(unitati,[X],S1),
concat(S1,"sprezece",S).
trad(zeci,[0,X],S) if trad(unitati,[X],S).
trad(zeci,[2,0],"douazeci").
trad(zeci,[6,0],"saizeci").
trad(zeci,[6,X],S) if X<>0,trad(unitati,[X],S1),
concat("saizecisi",S1,S).
trad(zeci,[X,0],S) if X<>0,X<>1,X<>2,X<>6,trad(unitati,[X],S1),
concat(S1,"zeci",S).
trad(zeci,[X,Y],S) if X<>0,X<>1,X<>6,Y<>0,trad(unitati,[X],S2),
trad(unitati,[Y],S1), concat(S2,"zecisi",S3),
concat(S3,S1,S).
trad(sute,[0|Rest],S) if trad(zeci,Rest,S).
trad(sute,[1|Rest],S) if trad(zeci,Rest,S1), concat("osuta",S1,S).
trad(sute,[X|Rest],S) if X<>0, X<>1, trad(unitati,[X],S2), trad(zeci,Rest,S1),
concat(S2,"sute",S3), concat(S3,S1,S).
trad(mii,[0|Rest],S) if trad(sute,Rest,S).
trad(mii,[1|Rest],S) if trad(sute,Rest,S1), concat("omie",S1,S).
trad(mii,[2|Rest],S) if trad(sute,Rest,S1), concat("douamii",S1,S).
trad(mii,[X|Rest],S) if X<>0, X<>1, X<>2, trad(unitati,[X],S1),
concat(S1,"mii",S2),
trad(sute,Rest,S3), concat(S2,S3,S).
trad(zecidemii,[0|Rest],S) if trad(mii,Rest,S).
trad(zecidemii,[1,X|Rest],S) if trad(zeci,[1,X],S1),
concat(S1,"mii",S2), trad(sute,Rest,S3),
concat(S2,S3,S).
trad(zecidemii,[X,Y|Rest],S) if X<>0, X<>1, X<>2, trad(zeci,[X,Y],S1),
concat(S1,"demii",S2), trad(sute,Rest,S3),
concat(S2,S3,S).

55. Alte aplicaţii ale limbajului PROLOG pentru prelucrarea limbajului natural

Diacritice, despartire in silabe, Din cuvinte in numere etc.

69

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