Documente Academic
Documente Profesional
Documente Cultură
2
1. Tipuri de date simple si structurate. (enumerare, caracteristici exemple in limbaje
procedurale)
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 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.
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
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
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.
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).
7
typedef struct tnod
{
tip inf; // informatia propriu-zisa
struct tnod *leg; // informatia de legatura
} TNOD;
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)
}
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:
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;
}
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:
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
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
*/
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:
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.
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)
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 */
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
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;
20
void parcurgere2 ( LISTA *ultim)
{
LISTA *p;
p=ultim;
while (p!=NULL)
{
prelucrare(p->inf);
p=p->ant;
}
}
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();
}
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.
25
prefix (r->st); // stânga
prefix (r->dr); // dreapta
}
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
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 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;
do
instructiune;
while (<conditie>)
- spre deosebire de structura repetitiva while instructiune se va executa cel putin o data
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.
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.
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.
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
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.
33
Exit While
End If
End While
34
sampleString = "Number equals 2"
LastLine
Debug.WriteLine(sampleString)
End Sub
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.
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.
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.
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
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)
37
End Sub
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">
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
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.
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:
<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
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:
41
24. Conceptul de distribuţie (repartiție)
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
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;
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'] }
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).
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
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.
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.
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.
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
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.
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.
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
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).
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.
(2)
Sau cu notațiile :
(3)
Rezulta:
60
(4)
(5)
(6)
In pasul l se obține:
(7)
Cu:
(8)
(9)
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
}.
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.
ab ab
Se poate atunci considera punctul , mijlocul intervalului [a,b] şi calcula f şi localiza
2 2
ab
în noul interval având pentru extremităţi şi punctul a sau b după cum f (a ) sau f (b) este de semn
2
ab
contrar lui f . La fiecare iteraţie se înjumătăţeşte lungimea intervalului. La începutul iteraţiei n,
2
ba
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].
In aceasta situație, metoda înjumătățirii intervalului consta in definirea a trei șiruri {a n}, {bn}, {cn},
astfel:
ab
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].
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
bx
altfel
ax
x ( a b) / 2
}
}.
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.
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
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.
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.
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).
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
69