Sunteți pe pagina 1din 61

Structuri de date 1

Laborator 1

1. C.m.m.d.c.

a) Algoritmul lui Euclid

Acest algoritm foloseşte tehnica scăderilor repetate. Se presupune că numerele


citite a şi b au proprietatea că sunt strict pozitive.

int cmmdcEuclid(int a, int b)


{ while (a!=b)
{ if (a>b) a=a-b;
else b=b-a;
}
return a;
}

b) Algoritmul lui Stein

Acest algoritm este mult mai eficient decât algoritmul lui Euclid. El urmăreşte
următoarele proprietăţi:
- dacă a şi b sunt ambele pare, atunci cmmdc(a,b)=2*cmmdc(a/2, b/2)
- dacă a este par şi b este impar, atunci cmmdc(a,b)=cmmdc(a/2, b)
- dacă a şi b sunt impare, atunci cmmdc(a,b)=cmmdc(|a-b|/2,b)
int cmmdcStein(int a, int b)

{
int g=1,t;
while ((a%2==0)&&(b%2==0))
{ a=a/2;
b=b/2;
g=2*g;
}
while(a>0)
{ while ((a%2==0)||(b%2==0))
{ if (a%2==0) a=a/2;
else b=b/2;
}
t=abs(a-b)/2;
if (a<b) b=t;
else a=t;
}
return g*b;
}
Structuri de date 2
2. Calculul lui xn

Deşi calculul lui xn poate părea o problemă banală, există totuşi un algoritm
care realizează aceasta cu un număr de paşi mai mic decât n. Mai jos sunt prezentaţi
trei algoritmi care calculează xn.
Primul algoritm este algoritmul clasic care calculează x n în n paşi.

double power(double x, int n)


{ double y=1;
while (n>0 )
{ y*=x;
n--;
}
return y ;
}

Există un algoritm care calculează pe xn în maximum log2(n)+1 paşi şi care


foloseşte următoarele observaţii:
- dacă n este par, atunci xn=(x2)n/2
- dacă n este impar, atunci xn=x*xn-1

double powerIterativ(double x, int n)


{ double y=1;
while (n>0)
{ if (n%2==1)
y=y*x;
n=n/2;
x=x*x;
}
return y;
}

double powerRecursiv(double x, int k)


{ if (k==0) return 1;
if( k%2==1)
return x*powerRecursiv(x,k-1)
return powerRecursiv(x*x,k/2)
}

3. Metode numerice

De foarte multe ori se doreşte găsirea zeroului unei funcţii continue f pe un


interval dat [a,b]  R în condiţiile în care se ştie cu exactitate (folosind elemente de
analiză matematică) faptul că are o singură rădăcină pe acest interval şi că
f(a)*f(b)<0. În aceste condiţii metodele de aproximare sunt deosebit de utile deoarece
găsesc cu aproximaţie valoarea rădăcinii pe intervalul [a,b].
Structuri de date 3
Vom prezenta trei metode iterative de calcul aproximativ a rădăcinii folosind
următoarea idee: cum f(a)*f(b)<0 din Teorema lui Darboux, rezultă că există cel
puţin o rădăcină a lui f pe intervalul [a,b] şi că f(a)şi f(b) au semne contrare.
Presupunem (fără a restrânge generalitatea că f(a)<0, f(b)>0. Fie m, cu a<m<b, o
valoare din intervalul [a,b]. Dacă f(m)<0 atunci rădăcina lui f va fi în intervalul [a,m],
dacă f(m)>0 atunci rădăcina va fi în intervalul [m,b] iar dacă f(m)=0 atunci m este
chiar rădăcina căutată. În situaţia în care nu am găsit exact rădăcina putem relua
procesul de căutare, însă de data aceasta pe un interval [a,m] (sau [m,b]) mai restrâns
decât cel iniţial. Procesul se va termina când valoarea absolută a lui f(m) nu va depăşi
o constantă de aproximaţie eps, specificată încă de la începutul algoritmului.
Cele trei metode diferă numai prin alegerea lui m şi anume:

a) Metoda înjumătăţirii intervalului


Această metodă îl alege pe m la jumătatea intervalului [a,b] în aşa fel încât la
fiecare reluare a iteraţiei domeniul de căutare se înjumătăţeşte.

double rout1(double a, double b, double eps)


{ double m;
if (f(a)*f(b)>0)
printf(“Nu exista solutii in acest interval”);
else
{m=(a+b)/2;
while (abs(f(m))>eps)
{ if (f(m)*f(a)>0)
a=m;
else
b=m;
m=(a+b)/2;
}
}
return m;
}

b) Metoda coardei
Această metodă alege pe m la intersecţia dintre abscisă şi segmentul dat de
punctele ((a,f(a)), (b,f(b))).

double root2(double a, double m, double eps)


{ double m;
if (f(a)*(b)>0 )
printf(”Nu exista solutii pe acest interval”);
else
{ m=abs(a - (b - a)*f(a)/(f(b) - f(a)));
while (abs(f(m))>eps)
{ if (f(m)*f(a)>0)
a=m;
else
b=m;
Structuri de date 4
m=abs(a - (b - a)*f(a)/(f(b) - f(a)));
}
}
return m;
}

c) Metoda tangentei
Această metodă alege pe m în punctul în care tangenta la funcţie în punctul f(a)
sau f(b) intersectează abscisa.

double root2(double a, double m, double eps)


{ double m=a;
if (f(a)*(b)>0 )
printf(”Nu exista solutii pe acest interval”);
else
{ m=m-f(m)/fderiv(m);
while (abs(f(m))>eps)
{ if (f(m)*f(a)>0)
a=m;
else
b=m;
m= m-f(m)/fderiv(m);}
}
return m;
}
Structuri de date 1

Laborator 2

1. Recurenţe liniare
a) Recurenţe liniare de ordinul I
Să se rezolve următoarea recurenţe:
T(1)=8 şi T(n)=3T(n-1)-15, n>1
Forma generală a acestui tip de recurenţă este următoarea:
T(n)=aT(n-1)+b, cu T(1) dat.
În continuare vom ataşa acestei recurenţe următoarea ecuaţie caracteristică şi vom
căuta constanta reală s astfel încât:
T(n)+s=a(T(n-1)+s), n N
T(n) = aT(n -1) + s(a -1) b
  S(a −1) = b  s= , a 1
b = T(n) - aT(n -1)  a −1

Atunci vom avea că:


T(n)+s=ak(T(n-k)+s), k 1, n
Pentru k=n+1 vom avea:
b  b 
T(n)+s=an-1(T(1)+s)= + a n T (0) +   O( a n )
a −1  a − 1 

Pentru ecuaţia noastră vom avea:


a=3, b=-15
-15
s=
2
15 n-1  16 -15  15 n-1 1 15
T(n)- =3   + =3 * +  O(a n )
2  2  2 2 2

b) Recurenţe liniare de ordinul II


Forma generală a acestui tip de recurenţă este :
T(n)=aT(n-1)+bT(n+2), cu T(0) şi T(1) daţi.
Vom ataşa acestei recurenţe ecuaţia caracteristică:
y2=ay+b
Structuri de date 2
şi vom căuta soluţiile reale y1 şi y2.
În funcţie de valorile obţinute pentru y1 şi y2, distingem următoarele două cazuri :
Caz 1: y1  y2
Formula termenului general este:
T(n)=A(y1)n + B(y2)n  O(max(y1n,y2n))
A şi B se identifică din sistemul:
 A + B = T (0)

 Ay1 + By 2 = T (1)

Caz 2: y1 = y2
Formula termenului general este:
T(n)=(A+nB)y1n  O(y1n)
A şi B se identifică din sistemul:
 A = T (0)

 Ay1 + By1 = T (1)

Cea mai cunoscută recurenţă liniară de ordinul II este şirul lui Fibonacci.
T(n)=T(n-1)+T(n+2), cu T(0)=0 şi T(1)=1.
Ecuaţia caracteristică ataşată este:
y2=y+1
 1− 5
 y1 =
 2
de unde obţinem soluţiile 
y = 1+ 5
 2 2

Formula termenului general va fi:


n n n n
1− 5  1+ 5  1− 5  1+ 5 
T(n)=A   + B
 
  O(max( 

  
 2  ,  2  ))
 2   2     

 5
 A=− n n
A + B = 0  5 − 5 1− 5  5 1+ 5 
   T(n)=   +  
 Ay1 + By 2 = 1  5 5  2  5  2 
 B = 5
Structuri de date 3
2. Să se demonstreze că următoarele funcţii sunt corect definite, adică se
termină într-un număr finit de paşi
x
 2 , x - par

a) F ( x) = F ( F ( x + 3)), x = 4k + 1
 F ( F ( x + 1)), x = 4k + 3

Pp. x=4k  F(x) = 2k


Pp. x=4k+1  F(x) = F (F (4k + 4)) = F (2k + 2) = k +1
Pp. x=4k+2  F(x) = 2k +1
PP. x=4k+3  F(x) = F (F (4k +1+ 3)) = F (2k + 2) = k +1
  x −1 
2 F   + 1, daca x impar
  2 
  x 
b) F(x)= 2F F  , daca x par, x  0
   2 
0, daca x = 0



 2k + 1 −1 
Pp. x=2k+1  F ( x) = 2F   + 1 = 2 F (k ) + 1 - impar () x  N
 2 

Observăm că x se înjumătăţeşte până ajunge în final pe valoarea 0,


() x N  în final F(x)=0+1=1 şi se termină într-un număr finit de paşi.

  2k  
Pp. x=2k  F ( x) = 2F  F    = 2 F ( F (k ))
 - par () x  N
  2 

Din nou x se înjumătăţeşte până ajunge la 0, () x N  în final F(x)=0.


Exemple de recurente liniare de ordin 1.
Ex.2: T(1)=3 şi T(n)=2T(n-1)+6
Pas 1. Forma generală: T(n)=aT(n-1)+b ➔ a=2, b=6
T(n)+s= a(T(n-1)+s)
T(n)= a(T(n-1)+s)-s
T(n)= aT(n-1)+as-s
T(n)= aT(n-1)+ s(a-1)
b=s(a-1) ➔ s= b/(a-1) ➔ s=6/1 ➔ s=6

Pas 2. T(n)+s= ak(T(n-k)+s)


Presupunem k = n-1
T(n)+s= an-1(T(n-(n-1))+s)
T(n)+s = 2𝑛−1 (T(n-n+1)+s)
T(n)+s= 2𝑛−1 (T(n-n+1)+s)
T(n)+ 6 = 2𝑛−1 *(3+6) ➔ T(n) = 2𝑛−1 *9-6 ϵ O(𝑎𝑛 )
Ex.3: T(1)=5 si T(n)=4T(n-1)+ 7
Pas 1. T(n) = a T(n-1)+b
a=4, b=7
s=7/3
T(n)+s= a(T(n-1)+s)
T(n)= a(T(n-1)+s)-s
T(n) = aT(n-1) + as-s ➔ T(n)= aT(n-1)+ s(a-1)
Pas 2. T(n)+s = 𝑎𝑘 (T(n-k)+s)
Presupunem k=n-1
T(n)+s= 𝑎 𝑛−1 (T(1)+s)
7 7 7
T(n) = 4𝑛−1 T(1)+ 4𝑛−1 * - ➔ T(n)= 4𝑛−1 ∗ 5+ (4𝑛−1 − 1) ϵ O(𝑎𝑛 )
3 3 3

Ex. 4: T(1)= 4 si T(n)= 2T(n-1)+1


Pas 1. Forma general:T(n)= aT(n-1)+b
a=2 si b=1
T(n)+s = a(T(n-1)+s)
T(n)= aT(n-1)+ as- s
b= as-s ➔ s= b/(a-1) ➔ s=1
Pas 2. T(n) + s= 𝑎𝑘 (T(n-k) + s)
Presupunem k =n-1
T(n)+s= 𝑎 𝑛−1 (T(n-n+1)+s)
T(n) + s = 𝑎𝑛−1 (T(1)+s) ➔ T(n)= 𝑎𝑛−1 *T(1) +𝑎𝑛−1 *s – s
T(n) = 2𝑛−1 ∗ 4 + 2𝑛−1 − 1 ϵ O(𝑎𝑛 )
Structuri de date 1

Laborator 3

1. Liste statice

Una dintre cele mai simple şi mai răspândite obiecte de dată sunt listele
ordonte.
Există un set de operaţii care pot fi efectuate pe liste şi anume:
- determinarea lungimii n a unei liste;
- parcurgerea listei de la stânga la dreapta şi de la dreapta la stânga;
- determinarea elementului de pe poziţia k din listă ( 1  k  n )
- modificarea valorii elementului de pe poziţia k din listă ( 1  k  n )
- inserarea unui nou elemnt pe poziţia i (1  i  n ), cauzând o translatare a
elementelor de pe pozţia i, i+1, …, n pe poziţiile i+1, i+2, …, n+1;
- ştergerea elementului de pe poziţia i ( 1  i  n ), cauzând o translatare a
elementelor de pe pozţia i+1, …, n pe poziţiile i, i+1, …, n-1;
- interclasarea elementelor a două liste sortate şi construirea unei noi liste.
În cele ce urmează vom construi o clasă ce va implementa operaţiile pe o listă
statică. Vom folosi trei fişiere, unul pentru definirea clasei, unul pentru
implementarea metodelor din clasă şi un al treilea pentru exemplificarea lucrului cu
metodele din clasa SList.

SList.h

class SList{
int count;
int data[20];
public:
SList(); //constructor
int SListLength(); //returneaza lungimea listei
int SListGetElement(int index); //returneaza elementul de pe pozitia index
void SListIterate(); //afiseaza elementele listei statice
void SListModify(int index, int value); //modif. elem. de pe poz. index cu value
void SListInsert(int index, int value); //insereaza elem. value pe poz. index
void SListDelete(int index); //sterge elementul de pe pozitia index
void SListMerge(SList obSList1, SList obSList2); //interclas. doua liste ord.
}; //sfarsitul clasei SList

SList.cpp

#include<stdio.h>
#include<conio.h>
#include "SList.h"

inline SList::SList()
{ count=0;
}
Structuri de date 2

inline int SList::SListLength()


{ return count;
}

inline int SList::SListGetElement(int index)


{ return data[index-1];
}

void SList::SListIterate()
{
for(int i=0; i<count;i++)
printf("%d ",data[i]);
}

inline void SList::SListModify(int index, int value)


{ data[index-1]=value;
}

void SList::SListInsert(int index, int value)


{ int i;
for(i=count-1;i>=index;i--)
data[i+1]=data[i];
count++;
data[index]=value;
}

void SList::SListDelete(int index)


{ int i;
for(i=index-1;i<count;i++)
data[i]=data[i+1];
count--;
}

void SList::SListMerge(SList obSList1, SList obSList2)


{ int i=0, k=0, j=0;
while((i<obSList1.count)&&(j<obSList2.count))
{ if(obSList1.data[i]<obSList2.data[j])
{ data[k]=obSList1.data[i];
i++;
k++;
}
else
{ data[k]=obSList2.data[j];
j++;
k++;
}
}
if(i==obSList1.count)
{
while(j<obSList2.count)
{ data[k]=obSList2.data[j];
j++;
k++;
}
}
else
{
Structuri de date 3
while(i<obSList1.count)
{ data[k]=obSList1.data[i];
i++;
k++;
}
}
count=k; }

ExSlist.cpp

#include<stdio.h>
#include<conio.h>
#include "SList.cpp"

void main()
{
int poz, val;
SList ob1, ob2, ob3;
int a;
printf("Introduceti elementele primei liste. Terminati cu 0");
scanf("%d", &a);
while(a!=0)
{
poz=ob1.SListLength();
ob1.SListInsert(poz,a);
scanf("%d", &a);
}
printf("Elementele primei liste sunt:\n");
ob1.SListIterate();
printf("\n Introduceti pozitia de pe care doriti sa aflati
elementul ");
scanf("%d",&poz);
printf("%d",ob1.SListGetElement(poz));
printf("\n Introduceti pozitia pe care doriti sa modificati
elementul \n");
scanf("%d", &poz);
printf("\n Introduceti noua valoare\n");
scanf("%d",&val);
ob1.SListModify(poz,val);
printf("\n Elementele listei sunt:\n");
ob1.SListIterate();
printf("\n Introduceti pozitia de pe care doriti sa stergeti un
element \n");
scanf("%d", &poz);
ob1.SListDelete(poz);
printf("\n Elementele listei sunt:\n");
ob1.SListIterate();
printf("\nIntroduceti elementele ordonate pentru cea de-a doua
lista. Terminati cu 0\n");
scanf("%d", &a);
while(a!=0)
{
poz=ob2.SListLength();
ob2.SListInsert(poz,a);
scanf("%d", &a);
}
printf("\nElementele celei de-a doua liste sunt:\n");
Structuri de date 4
ob2.SListIterate();
printf("\nIntroduceti elementele ordonate pentru cea de-a treia
lista. Terminati cu 0\n");
scanf("%d", &a);
while(a!=0)
{
poz=ob3.SListLength();
ob3.SListInsert(poz,a);
scanf("%d", &a);
}
printf("\nElementele celei de-a doua liste sunt:\n");
ob3.SListIterate();
ob1.SListMerge(ob2,ob3);
printf("\nElementele interclasate sunt:\n");
ob1.SListIterate();
getch();
}

2. Permutări

Permutările sunt structuri algebrice larg folosite în algoritmi. Posibilitatea


implementării unei structuri de date care să gestioneze permutările devine astfel o
necesitate. Cea mai simplă structură de date care gestionează o permutare de n
elemente este vectorul de n întregi.
Principalele operaţii cu permutări sunt următoarele:
- iniţializarea cu permutarea identică
- afişarea permutării
- compunerea permutărilor
- generarea permutării succesoare
Pentru a calcula permutarea succesoare trebuie parcurşi următorii paşi:
- se determină cel mai lung subşir de la sfârşitul permutării, fie acesta
pk, pk+1, ...pn. cu pk-1<pk>pk+1>...>pn
- se determină în secvenţa pk, pk+1, ...pn elementul pjastfel încât pj-1>pk-1>pj
- se interschimbă pk-1 cu pj
- se sortează crescător elementele de pe poziţiile k, k+1, ..., n.
Vom defini o clasă perm care va implementa operaţiile pe permutări.

Perm.h
class perm{
int count;
int data[10];
public:
perm();
void create(int n);
void init();
void permPrint();
perm compose(perm p1, perm p2);
perm permNext(perm p);
};
Structuri de date 5
perm.cpp

#include "perm.h"
#include<stdio.h>

inline perm::perm()
{ count=0;
}

void perm::create(int n)
{ count=n;
for(int i=1;i<=count;i++)
{ printf("\ndata[%d]=",i);
scanf("%d",&data[i]);
}
}

void perm::init()
{ for(int i=1;i<=count;i++)
data[i]=i;
}

void perm::permPrint()
{for(int i=1;i<=count;i++)
printf("%d ",data[i]);
printf("\n");
}

perm perm::compose(perm p1, perm p2)


{ //perm *temp;
count=p1.count;
for(int i=1;i<=p1.count;i++)
data[i]=p1.data[p2.data[i]];
return *this;
}

perm perm::permNext(perm p)
{ int i=p.count;
while ((p.data[i]<p.data[i-1])&&(i>1))
i--;
if(i>1)
{ int aux=p.count;
while(p.data[i-1]>p.data[aux])
aux--;
int temp=p.data[i-1];
p.data[i-1]=p.data[aux];
p.data[aux]=temp;
for(int piv=i;piv<=p.count;piv++)
for(int j=piv+1;j<=p.count;j++)
if(p.data[piv]>p.data[j])
{ int te=p.data[piv];
p.data[piv]=p.data[j];
p.data[j]=te;
}
}
count=p.count;
for(i=1;i<=p.count;i++)
Structuri de date 6
data[i]=p.data[i];
return *this;
}

experm.cpp
#include "perm.cpp"
#include<conio.h>
void main()
{
perm p,p1,p2,p3;
int n;
printf("Introdeuceti dimensiunea permutarii:");
scanf("%d",&n);
printf("\n Introduceti prima permutare");
p.create(n);
p.permPrint();
printf("\nIntroduceti a doua permutare");
p2.create(n);
p2.permPrint();
printf("\nCompunerea celor doua permutari:");
p1.compose(p,p2);
p1.permPrint();
printf("Permutarea succesoare:");
p3.permNext(p);
p3.permPrint();
printf("\nPermutarea identica este:");
p.init();
p.permPrint();
getch();
}
Structuri de date 1

Laborator 4

Polinoame

O altă implementare a listelor este în cazul operaţiilor simbolice cu polinoame.


Un polinom poate fi implementat ca o matrice în care elementul de indice k indică
valoarea coeficientului termenului de grad k însă în această situaţie, polinoamele cu
un număr mare de coeficienţi nuli vor avea o cantitate prea mare de memorie alocată
lor.
Soluţia oferită de liste este cea a unei memorări sub formă de listă a perechilor
(grad, coeficient), consumând astfel memorie numai pentru termenii nenuli.
De exemplu, polinomul P(x)=3x5+5x3+7x2-5 este memorat sub forma unei
liste L=(4; (3,5); (5,3); (7,2); (-5,0)).
Operaţiile primitive ce se pot efectua cu polinoame sunt:
- adăugarea/ştergerea unui termen dintr-un polinom
- adunarea/scăderea a două polinoame
- înmulţiera/împărţirea a două polinoame
- înmulţirea unui polinom cu o constantă.
Clasa care implementează operaţiile pe polinoame este dată în continuare. Se
va folosi o clasă auxiliară termen cu ajutorul căreia vom efectua operaţiile pe
polinoame.

polinom.h

class termen{
public:
int grad;
int coef;
termen(int a, int b);
termen();
};

class polinom{
int count;
termen data[10];
public:
polinom();
polinom ordonare();
polinom atrib(polinom sursa);
polinom adTerm(polinom p,termen t);
polinom scadTerm(polinom p, termen t);
polinom mulCst(int cst);
polinom adPol(polinom p1, polinom p2);
polinom scadPol(polinom p1, polinom p2);
polinom mulPol(polinom p1,polinom p2);
void printPol();
};
Structuri de date 2
Polinom.cpp

#include "polinom.h"
#include<stdio.h>

inline termen::termen(int a, int b)


{ grad=a;
coef=b;
}

inline termen::termen()
{ grad=0;
coef=0;
}

inline polinom::polinom()
{ count=0;
}

polinom polinom::ordonare()
{ for(int i=0;i<count-1;i++)
for(int j=i+1;j<count;j++)
if(data[i].grad<data[j].grad)
{termen temp=data[i];
data[i]=data[j];
data[j]=temp;
}
return *this;
}

polinom polinom::atrib(polinom sursa)


{ count=sursa.count;
for(int i=0; i<count;i++)
data[i]=sursa.data[i];
return *this;
}

polinom polinom::adTerm(polinom p, termen t)


{ count=p.count;
for(int i=0;i<count;i++)
data[i]=p.data[i];
int ok=0;
for(int i=0;i<count;i++)
if(data[i].grad==t.grad)
{ data[i].coef+=t.coef;
ok=1;
}
if (ok==0)
{ count++;
data[count-1]=t;
}
return *this;
}

polinom polinom::scadTerm(polinom p, termen t)


{ count=p.count;
for(int i=0;i<count;i++)
Structuri de date 3
data[i]=p.data[i];
for(int i=0;i<count;i++)
if((data[i].grad==t.grad) && (data[i].coef==t.coef))
{ termen temp=data[i];
data[i]=data[count-1];
data[count-1]=temp;
count--;
}
return *this;
}

polinom polinom::mulCst(int cst)


{ for(int i=0;i<count;i++)
data[i].coef*=cst;
return *this;
}

polinom polinom::adPol(polinom p1, polinom p2)


{ count=p1.count;
for(int i=0;i<count;i++)
data[i]=p1.data[i];
for(int j=0;j<p2.count;j++)
{ int ok=0;
for(int i=0;i<count;i++)
{ if (data[i].grad==p2.data[j].grad)
{ data[i].coef+=p2.data[j].coef;
ok=1;
}
}
if(ok==0)
{ count++;
data[count-1]=p2.data[j];
}
}
for(int i=0;i<count;i++)
if(data[i].coef==0)
{ termen temp=data[i];
data[i]=data[count-1];
data[count-1]=temp;
count--;
}
return *this;
}

polinom polinom::scadPol(polinom p1, polinom p2)


{ count=p1.count;
for(int i=0;i<count;i++)
data[i]=p1.data[i];
for(int j=0;j<p2.count;j++)
{ int ok=0;
for(int i=0;i<count;i++)
if (data[i].grad==p2.data[j].grad)
{ data[i].coef-=p2.data[j].coef;
ok=1;
}
if(ok==0)
{ count++;
Structuri de date 4
data[count-1].grad=p2.data[j].grad;
data[count-1].coef=-p2.data[j].coef;
}
}
for(int i=0;i<count;i++)
if(data[i].coef==0)
{ termen temp=data[i];
data[i]=data[count-1];
data[count-1]=temp;
count--;
}
return *this;
}

polinom polinom::mulPol(polinom p1, polinom p2)


{ count=0;
for(int j=0;j<p2.count;j++)
{
termen temp;
for(int i=0;i<p1.count;i++)
{ int ok=0;
temp.grad=p2.data[j].grad+p1.data[i].grad;
temp.coef=p2.data[j].coef*p1.data[i].coef;
for(int k=0;k<count;k++)
if (data[k].grad==temp.grad)
{ data[k].coef+=temp.coef;
ok=1;
}
if(ok==0)
{ count++;
data[count-1]=temp;
}
}
}
for(int i=0;i<count;i++)
if(data[i].coef==0)
{ termen temp=data[i];
data[i]=data[count-1];
data[count-1]=temp;
count--;
}
return *this;
}

void polinom::printPol()
{for(int i=0;i<count;i++)
printf("%dX^%d + ",data[i].coef,data[i].grad);
printf("\n");
}

exPolinom.cpp

#include<stdio.h>
#include<conio.h>
#include"polinom.cpp"
Structuri de date 5
void main()
{ polinom p,p1,p2;
termen t;
int cst;
printf("Introduceti termenii primului polinom. Terminati cu coef.0");
printf("\n grad=");scanf("%d",&t.grad);
printf("\n coeficient=");scanf("%d",&t.coef);
while(t.coef!=0)
{p.adTerm(p,t);
printf("\n grad=");scanf("%d",&t.grad);
printf("\n coeficient=");scanf("%d",&t.coef);
}
printf("Polinomul este");
p.printPol();
printf("Introduceti constanta cu care doriti sa inmultiti polinomul:");
scanf("%d",&cst);
p.mulCst(cst);
printf("Polinomul este");
p.printPol();
printf("Introduceti al doilea polinom");
printf("\n grad=");scanf("%d",&t.grad);
printf("\n coeficient=");scanf("%d",&t.coef);
while(t.coef!=0)
{ p1.adTerm(p1,t);
printf("\n grad=");scanf("%d",&t.grad);
printf("\n coeficient=");scanf("%d",&t.coef);
}
printf("\nPolinomul este");
p1.printPol();
p2.adPol(p,p1);
printf("\nPolinomul suma este:");
p2.ordonare();
p2.printPol();
p2.scadPol(p,p1);
printf("\nPolinomul diferenta este:");
p2.ordonare();
p2.printPol();
printf("\nProdusul celor doua polinoame este:");
p2.mulPol(p,p1);
p2.ordonare();
p2.printPol();
getch();
}
Structuri de date 1

Laborator 5

Stiva

Este o listă ordonată în care toate operaţiile de inserare şi ştergere sunt


efectuate la un singur capăt, numit vârful stivei (top). Deci ea este o structură de tip
LIFO (Last In First Out).
Pe această strucură, operaţia de inserare a unui element nou poartă numele de
push iar operaţia de extragere a unui element din stivă poartă numele de pop.
În continuare vom defini o clasă stack care se va ocupa cu gestionarea
operaţiilor de pe o stivă.

stack.h

class stack{
int MaxElem;
int top;
int data[50];
public:
stack();
int IsFull();
int IsEmpty();
void push(int val);
int pop();
void printStack();
};

stack.cpp

#include<stdio.h>
#include "stack.h"
inline stack::stack()
{ top=0;
MaxElem=50;
}
inline int stack::IsFull()
{ if (top==MaxElem)
return 1;
else
return 0;
}

inline int stack::IsEmpty()


{ if (top==0)
return 1;
else
return 0;
}
Structuri de date 2

inline void stack::push(int val)


{ if(!IsFull())
{ top++;
data[top]=val;
}
else
printf("Error! Stiva plina");
}

inline int stack::pop()


{if(!IsEmpty())
{ top--;
return data[top+1];
}
else printf("Error! Stiva goala");
return 0;
}

void stack::printStack()
{ if(top>0)
{ for(int i=1;i<=top;i++)
printf("%d ", data[i]);
printf("\n");
}
else
printf("\n Stiva ete goala");
}

ExStack.cpp
#include<stdio.h>
#include<conio.h>
#include "stack.cpp"
void main()
{ stack st;
int val;
printf("\n Introduceti elemente in stiva. Terminati cu 0:");
scanf("%d",&val);
while(val!=0)
{ st.push(val);
scanf("%d",&val);
}
printf("\n Elementele stivei sunt ");
st.printStack();
printf("\n Elementul din varful stivei este:%d", st.pop());
printf("\nAcum stiva este:");
st.printStack();
printf("\n Vom distruge stiva si vom calcula produsul elementelor sale");
int p=1;
while (!st.IsEmpty())
p*=st.pop();
printf("\n Produsul elementelor din stiva este %d",p);
Structuri de date 3
st.printStack();
getch();
}

Coada

Este o listă ordonată în care toate inserările se fac la un capăt, denumit rear şi
toate ştergerile se fac la celălalt capăt denumit front. Deci ea este o structură de tip
FIFO (First In First Out).
În continuare vom defini o clasă queue care se va ocupa cu gestionarea
operaţiilor de pe o coada.

queue.h
class queue{
int MaxElem;
int front;
int rear;
int data[50];
public:
queue();
int IsFull();
int IsEmpty();
void add(int val);
int del();
void printQueue();
};

queue.cpp
#include<stdio.h>
#include "queue.h"
inline queue::queue()
{ front=1;
rear=0;
MaxElem=50;
}
inline int queue::IsFull()
{ if (rear==MaxElem)
return 1;
else
return 0;
}
inline int queue::IsEmpty()
{ if (rear==0)
return 1;
else
return 0;
}
inline void queue::add(int val)
{ if(!IsFull())
{ rear++;
Structuri de date 4
data[rear]=val;
}
else
printf("Error! Coada plina");
}
int queue::del()
{ int temp;
if(!IsEmpty())
{ temp=data[front];
for(int i=1;i<rear;i++)
data[i]=data[i+1];
rear--;
return temp;
}
else printf("Error! Coada goala");
return 0;
}
void queue::printQueue()
{ if(rear>0)
{ for(int i=1;i<=rear;i++)
printf("%d ", data[i]);
printf("\n");
}
else
printf("\n Coada ete goala");
}

exQueue.cpp
#include<stdio.h>
#include<conio.h>
#include "queue.cpp"
void main()
{ queue q;
int val;
printf("\n Introduceti elemente in coada. Terminati cu 0:");
scanf("%d",&val);
while(val!=0)
{ q.add(val);
scanf("%d",&val);
}
printf("\n Elementele cozii sunt ");
q.printQueue();
printf("\n Primul element din coada este:%d", q.del());
printf("\nAcum coada este:");
q.printQueue();
printf("\n Vom distruge coada si vom calcula produsul elementelor sale");
int p=1;
while (!q.IsEmpty())
p*=q.del();
printf("\n Produsul elementelor din coada este %d",p);
q.printQueue();
getch(); }
Structuri de date 5

Matrici rare

Matricile bidimensionale sunt structuri de date frecvent folosite în algoritmi. În


cazul în care majoritatea elementelor sunt nenule, atunci este foarte eficientă
memorarea ei sub formă de tablou bidimensional. Acest mod de memorare este însă
ineficient în momentul în care avem un număr foarte mare de elemente nule.
O metodă de memorare a matricilor rare este cea folosită de Horowitz & Sahni
sun formă de listă, fiecare element al listei conţinând 3 valori:
- cele 3 valori ale primului element conţin dimensiunile matricii (nr_linii,
nr_coloane, nr_elemente_nenule)
- celelalte linii conţin câte o intrare de tipul (linie, coloană, valoare) astfel
încât fiecare element nenul are trei locaţii de memorie folosite pentru
memorare.
În continuare, vom implementa clasele care se ocupă cu gestiunea matricilor
rare. Mai întâi vom defini o clasă element care va conţine perechile (linie, coloană,
valoare), iar apoi cu ajutorul acestei clase vom implementa clas mrara.

Mrara.h

class element{
public:
int lin;
int col;
int val;
element(){
lin=0;
col=0;
val=0;
};
element(int a, int b, int c){
lin=a;
col=b;
val=c;
};
};

class mrara{
int nr_lin;
int nr_col;
int nr_elem;
element data[10];
public:
mrara();
void atribuire(mrara ob);
void adelem(element e);
mrara creare();
void stergere(element e);
void adunare(mrara ob1, mrara ob2);
void mulcst(int cst);
Structuri de date 6
void print();
void mul(mrara ob1, mrara ob2);
};

Mrara.cpp
#include<iostream.h>
#include ”mrara.h”

mrara::mrara()
{
nr_col=0;
nr_lin=0;
nr_elem=0;
}

void mrara::atribuire(mrara ob)


{
nr_lin=ob.nr_lin;
nr_col=ob.nr_col;
nr_elem=ob.nr_elem;
for(int i=0;i<nr_elem;i++)
data[i]=ob.data[i];
}

void mrara::adelem(element e)
{
int ok=1;
for(int i=0;i<nr_elem;i++)
if ((data[i].lin==e.lin)&&(data[i].col==e.col))
{
data[i].val+=e.val;
ok=0;
}
if(ok==1)
{
nr_elem++;
data[nr_elem-1].lin=e.lin;
data[nr_elem-1].col=e.col;
data[nr_elem-1].val=e.val;
}
}

mrara mrara::creare()
{
cout<<"Introduceti nr. de linii:"<<endl;
cin>>nr_lin;
cout<<"Introduceti nr. de coloane"<<endl;
cin>>nr_col;
cout<<"Introdeceti nr. de elemente nenule"<<endl;
cin>>nr_elem;
cout<<"Introduceti elementele"<<endl;
for(int i=0;i<nr_elem;i++)
Structuri de date 7
{ cout<<"elementul "<<i+1<<endl;
cout<<"linie= ";
cin>>data[i].lin;
cout<<"coloana= ";
cin>>data[i].col;
cout<<"valoare= ";
cin>>data[i].val;
cout<<endl;
}
return *this;
}

void mrara::stergere(element e)
{
for(int i=0;i<nr_elem;i++)
if ((data[i].lin==e.lin)&&(data[i].col==e.col)&&(data[i].val==e.val))
{ element temp;
temp=data[i];
data[i]=data[nr_elem-1];
data[nr_elem-1]=temp;
nr_elem--;
}
}

void mrara::adunare(mrara ob1, mrara ob2)


{
atribuire(ob1);
for(int i=0;i<ob2.nr_elem;i++)
adelem(ob2.data[i]);
}

void mrara::mulcst(int cst)


{
for(int i=0;i<nr_elem;i++)
data[i].val*=cst;
}

void mrara::print()
{
for(int i=0;i<nr_lin;i++)
{
for(int j=0;j<nr_col;j++)
{ int ok=1;
for(int k=0;k<nr_elem;k++)
if ((data[k].lin==i)&&(data[k].col==j))
{
cout<<data[k].val<<" ";
ok=0;
}
if (ok==1)
cout<<"0 ";
}
Structuri de date 8
cout<<endl;
}
}

void mrara::mul(mrara ob1, mrara ob2)


{
nr_lin=ob1.nr_lin;
nr_col=ob2.nr_col;
nr_elem=0;
for(int i=0;i<ob1.nr_lin;i++)
for(int j=0;j<ob2.nr_col;j++)
{
int temp=0;
for(int k=0;k<ob1.nr_col;k++){
int poz1=-1,poz2=-1;
for(int l=0;l<ob1.nr_elem;l++)
if((ob1.data[l].lin==i)&&(ob1.data[l].col==k))
poz1=l;
for(l=0;l<ob2.nr_elem;l++)
if((ob2.data[l].lin==k)&&(ob2.data[l].col==j))
poz2=l;
if((poz1!=-1)&&(poz2!=-1))
temp+=ob1.data[poz1].val*ob2.data[poz2].val;
}
if(temp!=0){
nr_elem++;
data[nr_elem-1].val=temp;
data[nr_elem-1].lin=i;
data[nr_elem-1].col=j;
}
}
}

exMrara.cpp

#include<iostream.h>
#include”mrara.cpp”

void main()
{
mrara ob1,ob2,ob3;
cout<<"Introduceti prima matrice:"<<endl;
ob1.creare();
ob1.print();
cout<<"Introduceti a doua matrice:"<<endl;
ob2.creare();
ob2.print();
cout<<"Introduceti constanta cu care inmultiti prima matrice"<<endl;
int cst;
cin>>cst;
ob1.mulcst(cst);
Structuri de date 9
ob1.print();
cout<<"Introduceti termenul de scos din a doua matrice"<<endl;

element e;
cout<<"linie=";
cin>>e.lin;
cout<<"coloana=";
cin>>e.col;
cout<<"valoare=";
cin>>e.val;
ob2.stergere(e);
ob2.print();
cout<<"Matricea suma este:"<<endl;
ob3.adunare(ob1,ob2);
ob3.print();
cout<<"Matricea produs este:"<<endl;
ob4.mul(ob1,ob2);
ob4.print();
}
Structuri de Date 1

Laborator 6

Forma poloneză
Evaluarea expresiilor aritmetice folosind stiva

Fie expresia A op B, unde A şi B sunt expresii iar op este un operator. Pentru


simplificarea problemei vom considera că op poate lua numai una din următoarele
valori: +, -, *, /.
Pentru a putea face o corectă evaluare a expresiei, trebuie să stabilim nişte
priorităţi pentru operatorii pe care îi vom folosi. Aceste priorităţi sunt:
- prioritate 1 pentru +
- prioritate 2 pentru -
- prioritate 3 pentru *
- prioritate 4 pentru /

Expresia A opB poate fi scrisă în formă poloneză în unul din următoarele


moduri:
op A B – forma poloneză prefixată
A opB – forma poloneză infixată (normală)
A B op – forma poloneză postfixată
Vom implementa un algoritm care primeşte de la intrare un şir de caractere
care conţine o expresie matematică validă, ce poate avea ca operatori +, -, *, / iar ca
operanzi numai litere şi generează forma poloneză postfixată.
Principiul de generare al expresiei postfixate este următorul:
- se foloseşte o stivă st în care se depune rezultatul operaţiilor interne
- se citeşte pe rand câte un caracter de la intrare. Dacă este un operand (literă)
va fi scris în şirul de ieşire. Dacă este un operator atunci apar două situaţii:
o dacă există în vârful stivei un operator cu prioritate mai mare decât
operatorul curent, atunci acela este scos din stivă şi afişat, operaţia
repetându-se până când stiva se goleşte sau operatorul din vârful
stivei e mai puţin prioritar decât cel current.
o dacă nu există un operator în vârful stivei cu prioritate mai mare
decât cel curent, operatorul curent va fi pus pe stivă.
- în finalul parcurgerii expresiei de intrare se va goli stiva, scriindu-se la
ieşire operatorii de pe stivă, de la vârful stivei spre bază.
Pornind de la expresia în forma ploneză inversă, se calculează valoarea
expresiei în cazul în care se cunosc valorile variabilelor care intervin. Algoritmul are
la bază următorul principiu:
- se porneşte cu expresia în forma poloneză inversă;
- se citesc token-urile şi se prelucrează astfel:
o dacă este un operand, se introduce pe stivă;
o dacă este un operator, se extrag din stivă operanzii B şi A şi se
efectuează operaţia A op B, rezultatul depunându-se pe stivă;
Structuri de Date 2
o operaţia continuă până la epuizarea expresiei în forma poloneză
inversă; dacă expresia a fost scrisă corect, atunci pe stivă se mai află
un singur element: rezultatul.
Clasa care implementează operaţiile de mai sus este:

Polish.h
class polish{
double eval;
char* infix;
char* postfix;
int priority(char ch);
int isOperator(char ch);
int operate(int a, int b, char op);
int caracter(char c);
public:
polish(char *ch);
void ReversePolishNotation();
void ReversePolishEvaluate();
};

Polish.cpp
#include<stdio.h>
#include<string.h>
#include<iostream.h>

polish::polish(char *ch)
{
strcat(infix,ch);
}

int polish::priority(char ch)


{ if (ch=='*') return 3;
if (ch=='/') return 4;
if (ch=='+') return 1;
if (ch=='-‘) return 2;
return 0;
}

int polish::isOperator(char c)
{ if(priority(c)>0) return 1;
else return 0;
}

int polish::caracter(char c)
{ int ret;
if (c== '0') ret=0;
if (c== '1') ret=1;
if (c== '2') ret=2;
if (c== '3') ret=3;
if (c== '4') ret=4;
Structuri de Date 3
if (c== '5') ret=5;
if (c== '6') ret=6;
if (c== '7') ret=7;
if (c== '8') ret=8;
if (c== '9') ret=9;
return ret;
}

void polish::ReversePolishNotation()
{ int i;
char *ret;
ret="";
char c;
char st[10];
int top=-1;
i=0;
while(i<strlen(infix))
{ if(!isOperator(*(infix+i)))
ret=ret+(*(infix+i));
else{
while((top>=0)&&(priority(st[top])>=priority(*(infix+i))))
{ c=st[top];
top--;
ret+=c;
}
top++;
st[top]=*(infix+i);
}
i++;
}
while(top>=0)
{ c=st[top];
top--;
ret+=c;
}
postfix=ret;
cout<<ret;
}

int polish::operate(int a, int b, char op)


{ int rez;
if (op=='+') rez=a+b;
if (op=='-') rez=a-b;
if (op=='*') rez=a*b;
if (op=='/') rez=a/b;
return rez;
}

void polish::ReversePolishEvaluate()
{ int st[10];
int a,b;
int i,top=-1;
i=0;
Structuri de Date 4
while(i<strlen(postfix))
{ if(isOperator(*(postfix+i)))
{ b=st[top];
top--;
a=st[top];
st[top]=operate(a,b,*(postfix+i));
}
else
{
top++;
st[top]=caracter(*(postfix+i));
}
i++;
}
eval=st[top];
cin>>eval;
}

exPolish.cpp
void main(){
char *sir;
cout<<"Introduceti expresia de evaluat"<<endl;
cin>>sir;
polish p(sir);
p.ReversePolishNotation();
p.ReversePolishEvaluate();
}
Structuri de Date 1

Laborator 7

Liste simplu înlănţuite

O listă simplu înlănţuită este o secvenţă finită de elemente dinamice,


împreună cu operaţiile:
- iniţializarea listei pe mulţimea vidă
- determinarea lungimii listei
- inserarea unui nod în listă
- modificarea valorii unui element din listă
- ştergerea unui nod din listă
- afişarea elementelor listei
- distrugerea listei
În continuare vom defini o listă simplu înlănţuită prin structura de
date asociată ei şi o vom implementa în limbajul de pogramare C++.
Dlist.h
#include<stdlib.h>
#include<iostream.h>

class ListElement{
public:
int info;
ListElement *next;
// ListElement(int const& _info, ListElement *_next) info(_info), next(_next){}
};

class LinkedList{
ListElement *prim, *ultim;
public:
LinkedList();
~LinkedList();
void Distrugere();
void Creare();
void Afisare();
void StergereVal(int val);
void StergereIndex(int index);
void InsertInceput(int val);
void InsertSf(int val);
void InsertBefore(int infoNod, int val);
void InsertAfter(int infoNod, int val);
void InsertIndex(int index, int val);
void Modifica(int oldVal, int newVal);
int Gasit(int val);
int GetFirst();
int GetLast();
Structuri de Date 2
int& operator[](int index);
void operator=(LinkedList &ls);
int operator==(LinkedList &ls);
friend ostream& operator<<(ostream &stream, LinkedList ls);
friend istream& operator>>(istream &stream, LinkedList &ls);
};

Dlist.cpp
LinkedList::LinkedList(): prim(0),ultim(0) {};

LinkedList::~LinkedList()
{ Distrugere();
}

void LinkedList::Distrugere()
{ while (prim!=NULL)
{ ListElement *temp=prim;
prim=prim->next;
delete temp;
}
prim=NULL; ultim=NULL;
}

void LinkedList::Creare()
{ int n, x;
Distrugere();
prim=NULL; ultim=NULL;
cout<<"cate elemente are lista?"; cin>>n;
cout<<"dati valorile ";
for (int i=1;i<=n;i++) { cin>>x;
InsertSf(x);
}
}

void LinkedList::Afisare()
{ ListElement *p=prim;
if (p==NULL)
{ cout<<"Lista goala"<<endl;
return;
}
while (p)
{ cout<<p->info<<" ";
p=p->next;
}
cout<<endl;
}

void LinkedList::StergereVal(int val)


{ if (prim==NULL) { cout<<"Lista goala";
return ;
}
Structuri de Date 3
if (prim->info==val) //stergere inceput
{ ListElement *temp=prim;
prim=prim->next;
if (!prim) ultim=NULL;
delete temp;
return;
}
if (ultim->info==val)
{ ListElement *p=prim;
while (p->next!=ultim) p=p->next;
ListElement *temp=ultim;
p->next=NULL;
ultim=p;
delete temp;
return;
}

ListElement *p=prim, *q=prim->next;


while ((q!=ultim) && (q->info!=val))
{ p=p->next;
q=q->next;
}

if (q==ultim) { cout<<"valoarea data nu se gaseste in lista"<<endl;


return ;
}
//stergere interior nodul q
p->next=q->next;
delete q;
}

void LinkedList::StergereIndex(int index)


{ if (prim==NULL) { cout<<"Lista goala"<<endl;
return ;
}
if (index==1) //stergere inceput
{ ListElement *p=prim;
prim=prim->next;
delete p;
if (!prim) ultim=NULL;
return;
}
int i=2;
ListElement *p=prim, *q=prim->next;
while ((q) && (i<index))
{ p=p->next;
q=q->next;
i++;
}
if (q==NULL) { cout<<"index prea mare"<<endl;
return;
}
Structuri de Date 4
if (q==ultim) //stregere sfarsit
{ delete q;
ultim=p;
ultim->next=NULL;
return ;
}
p=q->next;
delete q;
}

void LinkedList::InsertInceput(int val)


{ ListElement *nou=new ListElement;
nou->info=val;
nou->next=prim;
prim=nou;
if (prim->next==NULL) ultim=prim;
}

void LinkedList::InsertSf(int val)


{ ListElement *nou=new ListElement;
nou->info=val;
nou->next=NULL;
if (prim==NULL) { prim=nou;
ultim=prim;
return;
}
ultim->next=nou;
ultim=nou;
}

void LinkedList::InsertBefore(int infoNod, int val)


{ if (prim==NULL) { cout<<"lista goala"<<endl;
return;
}
if (infoNod==prim->info) //inserare la inceput
{ InsertInceput(val);
return;
}
ListElement *p=prim, *q=prim->next;
while ((q) && (q->info!=infoNod))
{ q=q->next;
p=p->next;
}
if (q==NULL) { cout<<"nodul dat nu se gaseste in lista";
return;
}
ListElement *nou=new ListElement;
nou->info=val;
nou->next=q;
p->next=nou;
}
Structuri de Date 5
void LinkedList::InsertAfter(int infoNod, int val)
{ if (prim==NULL) { cout<<"lista goala";
return;
}
ListElement *p=prim;
while ((p) && (p->info!=infoNod)) p=p->next;
if (!p) { cout<<"nodul dat nu se afla in lista"<<endl;
return;
}
ListElement *nou;
nou->info=val;
nou->next=p->next;
p->next=nou;
if (p==ultim) ultim=nou;
}

void LinkedList::InsertIndex(int index, int val)


{ if (index==1) //inserare inceput
{ InsertInceput(val);
return;
}
if (prim==NULL) { cout<<"lista goala, index prea mare";
return;
}
ListElement *p=prim;
int i=1;
while ((p) && (i<index)) { p=p->next;
i++;
}
if ((!p)&&(i==index)) { InsertSf(val);
return;
}
if (!p) { cout<<"index prea mare"<<endl;
return;
}
InsertBefore(p->info, val);

int LinkedList::Gasit(int val)


//return poz pe care se gaseste val, sau 0 daca val nu se gaseste in lista
{ ListElement *p=prim;
int poz=0;
while (p)
{ poz++;
if (p->info==val) return poz;
p=p->next;
}
return 0;
}

void LinkedList::Modifica(int oldVal, int newVal)


Structuri de Date 6
{ int poz=Gasit(oldVal);
if (poz==0) { cout<<"Valoarea de modificat nu se gaseste in lista!"<<endl;
return;
}
(*this)[poz]=newVal;
}

int LinkedList::GetFirst()
{ if (prim==NULL) { cout<<"lista goala";
exit(1);
}
return prim->info;
}

int LinkedList::GetLast()
{ if (ultim==NULL) { cout<<"Lista goala!"<<endl;
exit(1);
}
return ultim->info;
}

int& LinkedList::operator[](int index)


{ static int val=0;
if (index<=0) { cout<<"Index negativ!"<<endl;
exit(1);
}
ListElement* p;
int j=0;
p=prim;
while (p)
{ j++;
if (j==index) return p->info;
p=p->next;
}
cout<<"Index prea mare!"<<endl;
exit(1);
return val;
}

void LinkedList::operator=(LinkedList &ls)


{ Distrugere();
prim=NULL; ultim=NULL;
ListElement *p;
p=ls.prim;
while (p)
{ InsertSf(p->info);
p=p->next;
}
}

int LinkedList::operator==(LinkedList &ls)


{ ListElement *p=prim;
Structuri de Date 7
ListElement *q=ls.prim;
if ((p==NULL)&&(q==NULL)) return 1;
if ((p==NULL)&&(q)) return 0;
if ((p)&&(q==NULL)) return 0;
while ((p)&&(q))
{ if (p->info!=q->info) return 0;
p=p->next;
q=q->next;
}
if ((p==NULL)&&(q==NULL)) return 1;
return 0;
}

ostream& operator<<(ostream &stream, LinkedList ls)


{ ListElement *p;
p=ls.prim;
if (p==NULL)
{ stream<<"Lista vida!"<<endl;
return stream;
}
while (p)
{ stream<<p->info<<" ";
p=p->next;
}
stream<<endl;
return stream;
}

istream& operator>>(istream &stream, LinkedList &ls)


{ int n, i, val;
cout<<"Cate elemente are lista: ";
cin>>n;
cout<<"Dati lista: ";
ls.Distrugere();
ls.prim=NULL; ls.ultim=NULL;
for (i=1;i<=n;i++)
{ stream>>val;
ls.InsertSf(val);
}
return stream;
}

void meniu()
{
cout<<"1.Creare 8.Stergere valoare"<<endl;
cout<<"2.Afisare 9.Stergere de pe o anumita pozitie"<<endl;
cout<<"3.Inserare inceput 10.Modificare"<<endl;
cout<<"4.Inserare sfarsit 11.Cautare"<<endl;
cout<<"5.Inserare inaintea unui nod 12.Distugere"<<endl;
cout<<"6.Inserare dupa un nod 13.Verificarea egalitatii cu o alta lista"<<endl;
cout<<"7.Inserare pe o anumita pozitie 14.Terminare. "<<endl;
}
Structuri de Date 8
void main()
{ LinkedList l;
int nr;
int val, infoNod, index, oldVal;
meniu();
cout<<"Optiunea: ";cin>>nr;
while (nr!=14)
{ switch (nr)
{case 1: //l.Creare();
cin>>l;
break;
case 2: l.Afisare();
//cout<<l;
break;
case 3: cout<<"dati val "; cin>>val;
l.InsertInceput(val);
l.Afisare(); break;
case 4: cout<<"dati val "; cin>>val;
l.InsertSf(val);
l.Afisare(); break;
case 5: cout<<"dati nodPoz si val ";
cin>>infoNod; cin>>val;
l.InsertBefore(infoNod, val);
l.Afisare(); break;
case 6: cout<<"dati nodul dupa care inserati "; cin>>infoNod;
cout<<"dai val"; cin>>val;
l.InsertAfter(infoNod, val);
l.Afisare(); break;
case 7: cout<<"dati index si val ";
cin>>index; cin>>val;
l.InsertIndex(index, val);
l.Afisare(); break;
case 8: cout<<"dati val"<<endl; cin>>val;
l.StergereVal(val);
l.Afisare(); break;
case 9: cout<<"dati pozitia"; cin>>index;
l.StergereIndex(index);
l.Afisare(); break;
case 10: cout<<"dati vechea valoare "; cin>>oldVal;
cout<<"dati noua valoare "; cin>>val;
l.Modifica(oldVal, val);
l.Afisare(); break;
case 11: cout<<"dati val cautata"; cin>>val;
if (l.Gasit(val)) cout<<"val se gaseste in lista"<<endl;
else cout<<"val nu se gaseste in lista"<<endl;
break;
case 12: l.Distrugere(); break;
case 13: LinkedList k;
cout<<"Pt a 2-a lista: ";
k.Creare();
if (l==k) cout<<"Listele sunt egale"<<endl;
else cout<<"Listele nu sunt egale"<<endl;
Structuri de Date 9
break;
}
cout<<"Optiunea: "; cin>>nr;
}

LinkedList k;
k=l;
k.Afisare();
cout<<"gata";
}
Structuri de Date 1

Laborator 8

Arbori binari echilibraţi

Arborele binar este un tip particular de arbore care apare foarte des în
algoritmică. El este caracterizat prin faptul că fiecare nod al său are cel mult doi fii.
Arborele binar echilibrat este un arbore binar care are proprietatea că dferenţa
de noduri dintre subarborele său stâng şi subarborele său drept este maxim 1 şi toate
nivelele arborelui cu excepţia ultimului sunt complete.
Opearţiile care se vor efectua asupra arborilor binari echilibraţi sunt:
- crearea arborelui
- compararea a doi arbori binar
- copierea unui arbore binar
- distrugerea unui arbore binar
- parcurgerea în adâncime a unui arbore binar (inordine, preordine şi
postordine)
- parcurgerea în lăţime a unui arbore binar
Construcţia unui arbore binar echilibrat cu n noduri se desfăşoară după
următorul algoritm: se porneşte cu un arbore binar vid, se citeşte informaţia pentru
nodul rădăcină, după care se va apela recursiv procedura pentru determinarea
subarborelui său stâng, după care se va apela procedura pentru construcţia
subarborelui său drept. Algoritmul se termină când n=0.
Compararea a doi arbori binari se face în felul următor: dacă informaţia
conţinută în nodul curent din primul arbore este mai mică decât cea din nodul curent
din cel de-al doilea arbore, atunci spunem că primul arbore este mai mic decât al
doilea. Dacă nodul curent din primul arbore este nul, iar nodul curent din cel de-al
doilea arbore este nenul, atunci primul arbore este mai mic decât al doilea. Criteriul
se aplică recursiv subarborilor stâng şi drept. Se va returna în final 0 dacă arborii sunt
egali, 1 dacă primul este mai mare decât al doilea şi -1 în caz contrar.
Funcţia de copiere va copia arborele sursă în arborele destinaţie.
La distrugerea arborelui, se va distruge mai întâi nodul rădăcină după care se
va apela recursiv funcţia pentru distrugerea subarborelui stâng şi drept.
În continuare este prezentată clasa care implementează operaţiile enumerate
mai sus:

Btreeechil.h

class btree {
int val;
btree *st,*dr;
public:
btree();
~btree();
btree* create(int n);
int btreecompare(btree *bt1,btree * bt2);
Structuri de Date 2
void btreedestroy(btree*bt);
btree* copybtree(btree * sursa);
void inordine(btree *bt);
void preordine(btree *bt);
void postordine(btree *bt);
btree* cautare(btree *bt, int inf);
void bredth(btree *bt);
};

Btreeechil.cpp

#include<iostream.h>
#include<conio.h>
#include<stdio.h>
#include”Breeechil.h”

btree::btree()
{
st=NULL;
dr=NULL;
}

btree::~btree()
{
btreedestroy(this);
}

btree* btree::create(int n)
{
int ns,nd,inf;
if (n==0) return NULL;
else {
cin>>inf;
val=inf;
ns=(n-1)/2;
nd=(n-ns-1);
if (ns>0)
{
st=new btree;
st->create(ns);
}
if (nd>0)
{
dr=new btree;
dr->create(nd);
}
}
return this;
}

btree* btree::copybtree(btree * sursa)


Structuri de Date 3
{ btree *bt;
if (sursa==NULL) bt=NULL;
else { bt=new btree;
bt->val=sursa->val;
bt->st=copybtree(sursa->st);
bt->dr=copybtree(sursa->dr);
}
return bt;
}

int btree::btreecompare(btree *bt1,btree *bt2)


{ int rez;
if (bt1==NULL)
if (bt2==NULL) return NULL;
else return -1;
else if (bt2==NULL) return 1;
else if (bt1->val>bt2->val) return 1;
else if (bt2->val>bt1->val) return -1;
else {
rez=btreecompare(bt1->st,bt2->st);
if (rez==0)
return btreecompare(bt1->dr,bt2->dr);
else return rez;
}
}

void btree::btreedestroy(btree *bt)


{ btree *left,*right;
if (bt==NULL) return;
else {
left=bt->st;
right=bt->dr;
delete bt;
btreedestroy(left);
btreedestroy(right);
}
}

void btree::inordine(btree *bt)


{ if (bt!=NULL)
{ inordine (bt->st);
printf ("%d",bt->val);
inordine (bt->dr);
}
}

void btree::preordine(btree *bt)


{if (bt!=NULL)
{ printf ("%d",bt->val);
preordine(bt->st);
preordine(bt->dr);
}
Structuri de Date 4
}
void btree::postordine(btree *bt)
{ if (bt!=NULL)
{ postordine(bt->st);
postordine(bt->dr);
printf ("%d",bt->val);
}
}

btree* btree::cautare(btree *bt, int inf)


{
if(bt->val==inf)
return bt;
if(bt!=NULL)
{
return cautare(bt->st,inf);
return cautare(bt->dr,inf);
}
}

void btree::bredth(btree *bt)


{ int q[30];
int front=0;
btree * temp=bt, *aux,*ok;
if (bt==NULL) return;
front++;
q[front]=temp->val;
while (front!=0)
{ printf("%d ", q[1]);
int tem=q[1];
for(int i=1;i<front;i++)
q[i]=q[i+1];
front--;
ok=bt;
aux=cautare(ok,tem);
if(aux->st!=NULL)
{ front++;
q[front]=aux->st->val;
}
if(aux->dr!=NULL)
{ front++;
q[front]=aux->dr->val;
}
}
}

exBtreeechil.cpp

#include”Btreeechil.cpp”
void main()
{ btree *bt,*copie;
Structuri de Date 5
btree *bt1;
int n;
int comp;
printf("Introduceti numarul de noduri din arbore\n");
scanf("%d", &n);
printf("Introduceti nodurile\n");
bt->create(n);
printf("\nParcurgere in inordine\n");
bt->inordine(bt);
printf("\nParcurgere in preordine\n");
bt->preordine(bt);
printf("\nParcurgere in postordine\n");
bt->postordine(bt);
copie=bt->copybtree(bt);
printf("\nParcurgerea in inordine a copiei\n");
bt->inordine(copie);
comp=bt->btreecompare(bt,copie);
if (comp==0)
printf("\nCei doi arbori sunt identici\n");
else
if(comp==1)
printf("\nPrimul arbore este mai mare decat al doilea\n");
else
printf("\nAl doilea arbore este mai mare decat primul\n");
printf("Parcurgerea primului arbore in latime este:");
bt->bredth(bt);
printf("\nIntroduceti dimensiunea celui de-al doilea arbore\n");
scanf("%d",&n);
printf("\nIntroduceti nodurile celui de-al doilea arbore\n");
bt1->create(n);
printf("\nVom compara cei doi arbori\n");
comp=bt->btreecompare(bt,bt1);
if (comp==0)
printf("\nCei doi arbori sunt identici\n");
else
if(comp==1)
printf("\nPrimul arbore este mai mare decat al doilea\n");
else
printf("\nAl doilea arbore este mai mare decat primul\n");
getch();
bt->btreedestroy(bt);
bt->btreedestroy(bt1);
bt->btreedestroy(copie);
}
Structuri de Date 1

Laborator 9

Arbori de căutare binară

Foarte important în căutare şi sotare este arborele de căutare binară.


Un arbore de căutare binară este un arbore binar în care primul nod citit devine
automat rădăcina arborelui, iar toate celelalte noduri sunt repartizate recursiv în
subarborele sâng şi subarborele drept după cum urmează: dacă nodul ce se doreşte să
fie inserat este mai mare decât rădăcina atunci el este inserat recursiv în subarborele
drept al acesteia, iar dacă este mai mic atunci el este inserat recursiv în subarborele
stâng al acesteia.
Operaţiile care se vor efectua asupra arborilor de căutare binară sunt:
- crearea arborelui de căutare binară
- căurea unei valori în arborele de căutare binară
- parcurgerea în adâncime a arborelui de căutare binară (inordine, preordine,
postordine)
- parcurgea în lăţime a arborelui de căutare binară
- stergerea unui nod din arborele de căutare binară
Vom scrie funcţia care construieşte arborele de căutare binară în două etape: o
funcţie care inserează un nou element într-un arbore şi o funcţie de construcţie a
arborelui de căutare binară.
Scopul construcţiei acestui arbore este de a uşura căutarea anumitor chei într-
un arbore. Funcţia de căutare va returna adresa nodului în care se gaseşte valoarea
căutată sau NULL în cazul în care aceasta nu se găseşte în arbore
Problema ştergerii unui nod dintr-un arbore de căutare binară este puţin mai
complicată decât celelalte. Funcţia care va realiza această operaţie va primi ca
parametru un pointer la nodul care trebuie şters şi va returna noul nod rădăcină al
arborelui rămas. La această operaţie se disting următoarele cazuri:
- nodul care trebuie şters este pointer-ul NULL: nu se va efectua nimic, se va
returna pointerul NULL;
- nodul ce urmează a fi şters nu are nici subarbore stâng nici subarbore drept:
se şterge nodul dorit şi se va returna NULL;
- nodul ce urmează a fi şters nu are subarbore drept: se şterge nodul dorit şi
se va returna subarborele său stâng;
- nodul ce urmează a fi şters nu are subarbore stâng: se şterge nodul dorit şi
se va returna subarborele său drept;
- nodul ce urmează a fi şters are atât subarbore stâng cât şi subarbore drept:
se va merge în subarborele drept şi se va găsi nodul cel mai din stânga, apoi
fiul său stâng va fi subarborele stâng al nodului iniţial, se va şterge nodul
respectiv şi se va returna NULL.
În continuare este prezentată clasa în C++ care implementează operaţiile
enumerate mai sus:
Structuri de Date 2
Btreecautbin.h

class btree{
public:
int val;
btree *st,*dr;
btree();
~btree();
btree* insert(btree* bt,int inf);
btree* readbtree();
void btreedestroy(btree*bt);
void inordine(btree *bt);
void preordine(btree *bt);
void postordine(btree *bt);
btree* cautaRe(btree *bt, int inf);
btree* cautaIt(btree *bt, int inf);
void bredth(btree *bt);
btree* deletebtree(btree *nods);
};

Btreecautbin.cpp

#include<iostream.h>
#include<conio.h>
#include<stdio.h>
#include”Btreecautbin.h”
btree::btree()
{
st=NULL;
dr=NULL;
}

btree::~btree()
{
btreedestroy(this);
}

void btree::btreedestroy(btree *bt)


{ btree *left,*right;
if (bt==NULL) return;
else {
left=bt->st;
right=bt->dr;
delete bt;
btreedestroy(left);
btreedestroy(right);
}
}

void btree::inordine(btree *bt)


{ if (bt!=NULL)
Structuri de Date 3
{ inordine (bt->st);
printf ("%d",bt->val);
inordine (bt->dr);
}
}

void btree::preordine(btree *bt)


{if (bt!=NULL)
{ printf ("%d",bt->val);
preordine(bt->st);
preordine(bt->dr);
}
}

void btree::postordine(btree *bt)


{ if (bt!=NULL)
{ postordine(bt->st);
postordine(bt->dr);
printf ("%d",bt->val);
}
}

btree* btree::insert(btree* bt,int inf)


{ if(bt==NULL)
{ bt=new btree;
bt->val=inf;
bt->st=NULL;
bt->dr=NULL;
}
else
if(bt->val<inf)
bt->dr=insert(bt->dr,inf);
else
bt->st=insert(bt->st,inf);
return bt;
}

btree* btree::readbtree()
{ int inf;
btree* bt=NULL;
scanf("%d",&inf);
while(inf!=0)
{bt=insert(bt,inf);
scanf("%d",&inf);
}
return bt;
}

btree* btree::cautaRe(btree* bt,int inf)


{ if(bt==NULL)
return NULL;
if(bt->val==inf)
Structuri de Date 4
return bt;
if(bt->val>inf)
return cautaRe(bt->st,inf);
else
return cautaRe(bt->dr,inf);
}

btree* btree::cautaIt(btree* bt,int inf)


{btree* temp;
btree* aux=NULL;
if(bt==NULL)
return NULL;
if(bt->val==inf)
return bt;
temp=bt;
while(temp!=NULL)
{ if(temp->val==inf)
aux=temp;
else
if(temp->val<inf)
temp=temp->dr;
else
temp=temp->st;
}
return aux;
}

void btree::bredth(btree *bt)


{ int q[30];
int front=0;
btree * temp=bt, *aux;
if (bt==NULL) return;
front++;
q[front]=temp->val;
while (front!=0)
{ printf("%d ", q[1]);
int tem=q[1];
for(int i=1;i<front;i++)
q[i]=q[i+1];
front--;
aux=cautaRe(bt,tem);
if(aux->st!=NULL)
{ front++;
q[front]=aux->st->val;
}
if(aux->dr!=NULL)
{ front++;
q[front]=aux->dr->val;
}
}
}
Structuri de Date 5
btree* btree::deletebtree(btree* nods)
{btree *temp;
if (nods==NULL) return NULL;
if ((nods->st==NULL)&&(nods->dr==NULL))
{
delete nods;
return NULL;
}
else
if(!nods->st)
{ temp=nods;
nods=temp->dr;
delete temp;
return nods;
}
else
if(!nods->dr)
{ temp=nods;
nods=temp->st;
delete temp;
return nods;
}
else
{ temp=nods->dr;
while (temp->st!=NULL)
temp=temp->st;
temp->st=nods->st;
temp=nods;
nods=nods->dr;
delete temp;
return nods;
}
}

exBtreecautbin.cpp

#include”Breecautbin.cpt”
void main()
{ btree *bt, *temp,*temp1,*aux;
int inf;
printf("\nIntroduceti elementele arborelui. Terminati cu 0\n");
bt->readbtree();
printf("\nParcurgere in inordine\n");
bt->inordine(bt);
printf("\nParcurgere in preordine\n");
bt->preordine(bt);
printf("\nParcurgere in postordine\n");
bt->postordine(bt);
printf("\nIntroduceti valoarea pe care doriti sa o cautati\n");
scanf("%d",&inf);
temp=bt->cautaRe(bt,inf);
Structuri de Date 6
if (temp!=NULL)
printf("\nValoarea %d se gaseste in arbore\n",inf);
else
printf("\nValoarea %d nu se gaseste in arbore\n",inf);
printf("Parcurgerea arborelui in latime este:");
bt->bredth(bt);
printf("\nIntroduceti valoarea pe care doriti sa o stergeti\n");
scanf("%d",&inf);
temp=bt->cautaRe(bt,inf);
if (temp!=NULL)
if(bt==temp)
{ temp1=bt->deletebtree(temp);
bt=temp1;
}
else
{
aux=bt;
int ok=0;
while(ok==0)
{ if(aux->st==temp)
{ temp1=bt->deletebtree(temp);
aux->st=temp1;
ok=1;
}
else
if(aux->dr==temp)
{ temp1=bt->deletebtree(temp);
aux->dr=temp1;
ok=1;
}
if(aux->val<inf)
aux=aux->dr;
else
aux=aux->st;
}
printf("\nParcurgere in inordine\n");
bt->inordine(bt);
getch();
bt->btreedestroy(bt);
}
}
Structuri de Date 52

Laborator 10

Grafuri

Fie V o mulţime nevidă şi E  V *V . Perechea G=(V*E) oartă numele de graf,


unde V reprezintă mulţimea nodurilor care compun graful şi E mulţimea muchiilor
care unesc nodurile grafului.
Există mai multe metode de memorare a grafurilor, fiecare având o clasă aparte
de situaţii unde sunt aplicabile. Cele mai utilizate sunt matricea de adiacenţă, listele
de adiacenţă şi multilistele de adiacenţă.
Operaţiile care se vor efectua asupra grafurilor sunt:
- iniţializarea grafului
- citirea grafului
- tipărirea grafului
- citirea muchiei
- adăugarea unei noi muchii
- distrugerea grafului
În continuare vom implementa operaţiile pe graf cu ajutorul listelor de
adiacenţă.

#include<stdio.h>
#include<conio.h>
#include<alloc.h>
#define MaxVertex 20

struct muchie{
int sursa;
int dest;
};
typedef struct muchie muchie;

struct list{
int val;
struct list *next;
};

typedef struct list list;


typedef list* plist;
typedef plist graph[MaxVertex];

void adMuchie(graph *g, muchie e)


{ list *temp,*aux;
if((e.sursa<0)||(e.dest<0)||(e.sursa>=20)||(e.dest>=20))
return;
temp=(*g)[e.sursa];
aux=new list;
aux->val=e.dest;
Structuri de Date 53
aux->next=NULL;
if(temp==NULL)
(*g)[e.sursa]=aux;
else
{ while(temp->next!=NULL)
temp=temp->next;
temp->next=aux;
}
}

int citireMuchie(muchie *e)


{ printf("\nSursa=:");
scanf("%d",&e->sursa);
printf("\nDestinatia=:");
scanf("%d",&e->dest);
if((e->sursa<0)||(e->dest<0)||(e->sursa>=20)||(e->dest>=20))
return 0;
else
return 1;
}

void citireGraph(graph *g)


{ muchie e;
while(citireMuchie(&e)==1)
adMuchie(g,e);
}

void initGraph(graph *g)


{ int i;
for(i=0;i<20;i++)
(*g)[i]=NULL;
}

void printGraph(graph *g)


{ int i;
list *temp;
for(i=0;i<20;i++)
{ printf("\nNodul %d: ",i);
temp=(*g)[i];
while(temp!=NULL)
{ printf("%d ",temp->val);
temp=temp->next;
}
}
}

void destroyGraph(graph *g)


{ plist temp,aux;
int i;
for(i=0;i<20;i++)
{ temp=(*g)[i];
while(temp!=NULL)
Structuri de Date 54
{ aux=temp->next;
free(temp);
temp=aux;
}
}
}

void main()
{
graph g;
initGraph(&g);
printf("\nCitie graf. Terminati cu nod<0\n");
citireGraph(&g);
printf("\nGraful citit este:");
printGraph(&g);
destroyGraph(&g);
getch();
}
Structuri de Date 1

Laborator 11

Algoritmi de sortare

1.HeapSort-ul

Heap-ul este un arbore binar cu un câmp cheie în fiecare nod, astfel încât:
- toate frunzele din arbore se află pe două nivele adiacente;
- toate frunzele de pe cel mai de jos nivel apar la stânga şi toate nivelele, cu
excepţia eventual a celui mai de jos sunt pline;
- cheia din nodul rădăcină este cel puţin atât de mare cât cheile fiilor stâng şi
drept (dacă aceştia există) , iar subarborele stâng şi drept sunt la rândul lor
heap-uri.
Memorarea unui astfel de arbore se face într-un vector unidimensional.
Nodurile din arbore vor fi puse în vector în urma unei parcurgeri în lăţime.
Timpul de execuţie al acestui algoritm este O(n*log(n)) chiar şi în cazul cel
mai nefavorabil.
Vom scrie în continuare programul în C care realizează sortarea cu ajutorul
acestui algoritm.

#include<stdio.h>
#include<dos.h>
#include<conio.h>

void HeapInsert(int v[200],int x,int a, int b)


{ int m;
m=2*a+1;
while(m<=b)
{ if(m<b)
if(v[m]<v[m+1])
m=m+1;
if(x>=v[m])
m=b+1; //isire din bucla
else
{ v[a]=v[m];
a=m;
m=2*a+1;
}
}
v[a]=x;
}

void HeapBuild(int v[200], int n)


{ int k;
int x;
for(k=n/2;k>=0;k--)
{ x=v[k];
Structuri de Date 2
HeapInsert(v,x,k,n-1);
}
}

void HeapSort(int v[200], int n)


{ int k;
int x;
HeapBuild(v,n);
for(k=n-1;k;--k)
{ x=v[k];
v[k]=v[0];
HeapInsert(v,x,0,k-1);
}
}

void main()
{ int v[50];
int n;
printf("\nIntroduceti numarul de elemente:");
scanf("%d",&n);
printf("\nIntroduceti elementele:");
for(int i=0;i<n;i++)
scanf("%d",&v[i]);
HeapSort(v,n);
printf("\nSirul ordonat este:\n");
for(int i=0;i<n;i++)
printf("%d ",v[i]);
getch();
}

După cum s-a văzut, la sortarea HeapSort s-a folosit de o funcţie HeapInsert
care inserează un element în heapul memorat de la adresa a la adresa b, dar care are
rădăcina de la adresa a vidă. Algoritmul presupune o parcurgere a heap-ului de la
rădăcină avându-se în vedere că:
- dacă noua valoare a lui x este mai mare decât cheile fiilor, atunci se pune x
chiar în rădăcină, şi algoritmul se termină, rezultatul fiind un heap memorat
de la adresa a la adresa b.
- dacă nu se determină cărui nod fiu îi corespunde valoarea cea mai mare a
cheii, se aduce acesta în rădăcină şi se continuă inserarea pe ramura acestuia
a valorii lui x, algoritmul terminându-se la parcurgerea totală a acestuia.
S-a folosit şi o funcţie de construire a heap-ului, HeapInsert. Pornind cu
arborele cu un element, care este evident un heap, se va insera succesiv câte un
element în el.

2. QuickSort-ul

Această metodă de sortare mai este cunoscută şi sub numele de sortare prin
partiţionare. Metoda are trei faze:
Structuri de Date 3
- partiţionarea în care elementele v[l], v[l+1], …, v[r] sunt împărţite în trei
clase:
o cele mai mici decât v[l]
o v[l]
o cele mai mari decât v[l]
De fapt v[l], numit şi pivot de partiţionare, este ales dintre elementele v[l],
v[l+1], …, v[r]; la finalul buclei while, i va fi egal cu k şi vor indica exact
poziţia la care se va afla elementul pivot v[l] în vectorul sortat; de aceea la
finalul acestui ciclu, vom interschimbă elementele v[l] şi v[r].
- sortarea părţii stângi, în care este apelată recursiv procedura pentru sortarea
elementelor aflate pe poziţiile v[l],…, v[k-1];
- sortarea părţii drepte, adică a elementelor mai mari decât v[k] şi anume
v[k+1],…, v[r].

Timpul mediu pentru QuickSort este logaritmic, iar acest algoritm este preferat
lui HeapSort deoarece constanta din faţa termenului dominant 2/log 2(e)=1.39 este mai
mică decât 2, care este coeficientul pentru HeapSort.
Codul în limbajul C este prezentat în continuare:
#include<stdio.h>
#include<conio.h>

void SortQuick(int v[], int l, int r)


{ int i,k,s,temp;
i=l;
k=r+1;
s=v[l];
while(i<k)
{ do
{ i++;
}
while (v[i]<s);
do
{ k--;
}
while(v[k]>s);
if(k>i)
{ temp=v[k];
v[k]=v[i];
v[i]=temp;
}
}
temp=v[l];
v[l]=v[k];
v[k]=temp;
if(l<k-1)
SortQuick(v,l,k-1);
if(k+1<r)
SortQuick(v,k+1,r);
Structuri de Date 4
}

void main()
{ int v[50];
int n,l,r;
printf("\nIntroduceti numarul de elemente:");
scanf("%d",&n);
printf("\nIntroduceti elementele:");
for(int i=0;i<n;i++)
scanf("%d",&v[i]);
l=0;
r=n-1;
SortQuick(v,l,r);
printf("\nSirul ordonat este:\n");
for(int i=0;i<n;i++)
printf("%d ",v[i]);
getch();
}

3. ShellSort-ul

Este o variantă a sortării prin distribuţie. Ideea metodei este următoarea:


- la pasul 1 se compară şi se interschimbă (dacă este cazul) elementele de pe
poziţia i şi i+n/2, pentru i=0,1,…,n/2-1.
- la pasul 2 se realizează acelaşi lucru cu elementele de pe poziţia i şi i+n/4.
Această metodă nu are un timp de sortare logaritmic însă este folosită datorită
faptului că nu are apeluri recursive, nu foloseşte memorie suplimentară, iar
coeficientul dominant al funcţiei de operaţii pătratice este relativ mic. În plus,
elementele de sortat sunt comparate două câte două într-o ordine cât mai puţin
prestabilită.
Codul funcţiei de sortare este următorul:
#include<stdio.h>
#include<conio.h>

void ShellSort(int v[20],int n)


{ int g,i,j;
int temp;
for(g=n/2;g>0;g=g/2)
for(i=g;i<n;i++)
for(j=i-g;j>=0 && v[j]>v[j+g];j=j-g)
{ temp=v[j];
v[j]=v[j+g];
v[j+g]=temp;
}
}

void main()
{ int v[50];
int n;
Structuri de Date 5
printf("\nIntroduceti numarul de elemente:");
scanf("%d",&n);
printf("\nIntroduceti elementele:");
for(int i=0;i<n;i++)
scanf("%d",&v[i]);
ShellSort(v,n);
printf("\nSirul ordonat este:\n");
for(int i=0;i<n;i++)
printf("%d ",v[i]);
getch();
}

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