Documente Academic
Documente Profesional
Documente Cultură
f)
g)
h)
i)
// PROGRAM definire:
#include<.>
#include<.>
................................
int k;
main( )
{
................................
}
dintr-un
-
M
n
k
Ti
adr( )
adr : J -> N
(2.1)
unde:
J mulimea identificatorilor;
N submulime a numerelor naturale cu care se localizeaz fiecare bait al
zonei de memorie la dispoziia programatorului;
N [ a, b] N
cont( )
tip( )
U Di
i 1
(2.2)
(2.3)
(2.4)
(2.5)
(2.6)
Dintre acestea numai f11 i f14 sunt inversabile, deci tabloul funciilor:
fij ( ), i = 1, 2, 3, 4, 5 i j =1, 2, 3, 4, 5
(2.7)
A:8
A+16
A+8
A+20
A: 8
A+8
(2.8)
unde:
U - mulimea irurilor ce se genereaz cu simbolurile alfabetului
nstruit pentru un limbaj;
Di
FALSE
f (x , i )
TRUE
daca x Di
daca x Di
(2.9)
De exemplu:
f(13, int) =TRUE
(2.10)
(2.11)
00
00
00
14
14
00
00
00
07AA0
07AA0
a
b
Figura 2.3 Zona de memorie asociat variabilei x
(a microprocesoare MOTOROLA, b microprocesoare INTEL)
adr(x) = 07AA0
cont(x) = (00000014)16
f(cont(x), int) = TRUE
tip (x) = int
Deci:
f(cont(x), tip(x)) = TRUE
(2.12)
Funcia de aliniere:
K: adresa x tipi -> TRUE
(2.13)
(2.14)
unde ki este factorul de aliniere cerut prin construcie pentru tipul de date Ti .
K(07AA0, int) = TRUE
(2.15)
pentru c 07AA0 4
K(adr(x), tip (x)) = TRUE
(2.16)
(2.17)
c
a
- cifra
- a sau b
b
[]
- construcie opional
+
-
ccccc. . . c
+- 60
44
sunt sau nu constante ntregi. Cu uurin ne dm seama c irurile . 3 + - 60
i 44 - nu ndeplinesc cerinele impuse de ablonul model.
Pentru constantele de tip real se prezint modelul de generare:
E
[cc ...c ] [.] [cc ...c ] e [cc ]
Figura 2.6 Modelul de generare a constantelor reale
irurile:
+ 1 . 2e-4
- . 3 E2
2 . e-1
1e + 4
b
c
(2.18)
g
e
(2.19)
(2.20)
pune n eviden ca dat conine dou date elementare i anume care are
tipul ntreg i care are tipul .
Aceste modele permit descrierea structurilor de date autoreferite: liste,
stive i arbori.
e) Modele grafice
Sunt utilizate reprezentri grafice pentru locaiile de memorie asociate
variabilelor i constantelor unui program. Prin arce se stabilesc legturile
dintre locaii. Acest model de descriere a datelor este sugestiv i fr
ambiguitate.
Construcia:
1
10
ni1
(2.21)
extended;
comp;
shortint;
word;
memorie
asociat
(2.22)
(2.23)
(2.24)
(2.25)
l1
12
y
Figura 2.10 Modelul de reacoperire a locaiilor de memorie
d(x,y) < lg (x) = l1
lg (y) = 12
(2.26)
(2.27)
(2.28)
(2.29)
(2.30)
(2.31)
variabile
S1. int i;
float s;
variabile
S2. float s;
int i;
(2.32)
sunt echivalente, rezultatele prelucrrii unui program care conine una din cele
dou secvene sunt identice.
Dac programului P i se ataeaz o secven S la stnga, se obine
programul P1:
P1 = S || P
(2.33)
(2.34)
(2.35)
(2.36)
unde:
P
mulimea programelor;
C
mulimea constantelor elementare, vectoriale, matricele i de alte
structuri.
n cazul secvenelor S1, S2 dac:
rez(S1 || P;d) = rez(S2 || P; d)
(2.37)
(2.38)
(2.39)
(2.40)
(2.41)
(2.42)
(2.43)
(2.44)
int i;
float s;
. . .
i = 1.;
s = 0;
int i;
float s;
. . .
i = 1;
s = 0.;
(2.45)
se observ c domeniile celor dou variabile care au acelai tip sunt disjuncte,
deci este definit o singur variabil care este utilizat de ambele secvene.
Dac:
rez (S2; rez (S1; i), j) = rez (S2; rez(S1;i), i)
(2.46)
secvena:
int i;
int j;
...
S1 (i);
...
S2 (j);
Caracterul local sau global, dinamic sau static, este dat de contextul n
care se utilizeaz fiecare variabil. Important este ca programul s realizeze
pentru un exemplu de test din specificaiile de programare, acelai coninut
pentru toate punctele de control.
Dac pentru valorile 1, 2, 3, 4, 5 ale vectorului x de 5 componente, la
iteraia a treia, n specificaiile de programare se indic pentru variabila s
valoarea 6 i dac prin:
rez (S1 S1 S1; s, i)
(2.47)
(2.48)
(2.49)
Dac:
cont_prg (i, m) = = cont_prg(i, m+1) (2.50)
oricare ar fi m [1, M] N, unde M este numrul de instruciuni executabile
care formeaz programul, se spune c i nu i modific coninutul, este deci o
constant i ori este defectuos utilizat, ori trebuia definit nu ca variabil ci ca
o constant simbolic.
Urma programului se obine prin:
(2.51)
(2.52)
(2.53)
(2.54)
(2.55)
int
...
a =
b =
c =
d =
e =
f =
...
a, b, c, d, e, f;
0;
0;
0;
0;
0;
0;
x[6];
i;
.
(i=0; i<6; i++)
x[i] = 0;
sau secvena:
int x[6] = {0, 0, 0, 0, 0, 0};
. . .
int x[4];
cin>>x[0]>>x[1]>>x[2];
x[3]=x[0]*x[1]*x[2];
cout<< volum = <<x[3];
. . .
asupra
rezultatelor
6. MATRICE RARE
6.1 Concepte de baz
Matricele rare i gsesc aplicabilitatea n modelarea unor procese de
natur industrial, economic, tehnic, social etc. Capitolul de fa i
propune s trateze modalitile de reprezentare n structuri de date a
matricelor rare, precum i principalele operaii matriceale implementate ntr-un
limbaj orientat pe obiecte. n final este prezentat o aplicaie concret
estimarea parametrilor unei regresii statistice.
n rezolvarea multor probleme de natur economic, tehnic, social, a
diverselor probleme de optimizare, precum i n modelarea unor procese
industriale i tehnologice este necesar s se determine modelul matematic care
descrie funcionarea procesului respectiv. Descrierea acestor sisteme fizice
conduce la obinerea unor modele matematice care fie n mod direct, prin
modelare, fie prin metoda de rezolvare implic sisteme de ecuaii algebrice
liniare sau probleme de programare liniar a cror matrice a coeficienilor este
rar (sparse), n sensul c ponderea elementelor nenule n totalul elementelor
matricei este mic.
Din punct de vedere practic trebuie remarcat faptul c analiza sistemelor
mai sus amintite conduce la obinerea unor modele matematice de mari
dimensiuni care implic sisteme de ecuaii algebrice liniare de mii de ecuaii,
pentru a cror rezolvare sunt necesare resurse mari de memorie i timp de
calcul. n multe cazuri practice, cum sunt sistemele n timp real, timpul de
calcul este o resurs critic, nefiind permis s depeasc o valoare limit.
Modelele matematice ale proceselor reale implic un numr foarte mare
de variabile i restricii care prezint fenomenul de raritate ,sparsity, adic o
slab interconectare a elementelor sale. Luarea n consideraie a fenomenului
de raritate furnizeaz un nou mod de abordare foarte eficient, ce implic n
dezvoltarea aplicaiilor informatice folosirea unor structuri de date speciale,
care s conduc la reducerea resurselor de memorie i a timpului de calcul.
n general, o matrice (n, n) - dimensional este rar atunci cnd conine
un numr mic de elemente nenule , adic n 2 . Cantitativ, matricele rare
sunt caracterizate de ponderea numrului de elemente nenule n totalul de
elemente, pondere ce definete gradul de umplere al matricei. n aplicaiile
curente se ntlnesc matrice rare cu grade de umplere ntre 0,15% i 3%.
0
1 0
0 0 2
A
0 0
0
0 1 0
0
0
0
0
4
0
(6.1)
p
100 (%)
nm
(6.2)
unde:
p numrul de elemente nenule;
n numrul de linii;
m numrul de coloane.
n general se accept c o matrice este rar dac densitatea sa este de
cel mult 3%. Densitatea matricei A este G ( A) 20% , ea fiind prezentat aici n
scopul ilustrrii conceptului de matrice rar.
Structura de date clasic folosit pentru manipularea matricelor, tabloul
de dimensiune (n, m) alocat la compilare, se dovedete a fi ineficient n cazul
n care matricea este rar. Un prim avantaj este legat de folosirea
neeconomic a spaiului de memorie prin alocarea de zone mari pentru
memorarea elementelor nule, care nu sunt purttoare de informaie. Ocuparea
unor zone de memorie cu elemente nule nu se justific deoarece acestea nu
contribuie la formarea rezultatului operaiilor cu matrice, adunare, nmulire
etc., conducnd totodat i la mrirea duratei de realizare a acestor operaii
prin ocuparea procesorului cu adunri i nmuliri scalare cu zero. Acest
inconvenient se manifest cu att mai pregnant cu ct dimensiunea matricei
este mai mare.
Prin urmare, pentru probleme de dimensiuni mari, s-a cutat gsirea
unor modaliti de reprezentare compact a matricelor rare, n care s se
renune la memorarea elementelor nule. n acest caz este necesar ca tehnicile
de memorare s ncorporeze pe lng elementele nenule i mijloacele de
identificare a poziiilor acestor elemente n matrice.
Sunt prezentate n continuare cteva posibiliti de memorare compact
a matricelor rare MR. Se face, de asemenea, o analiz a oportunitii folosirii
fiecrei tehnici n parte, n funcie de densitatea matricei.
Memorarea prin identificare binar se bazeaz pe natura binar a
sistemului de calcul, constnd n memorarea numai a elementelor nenule ale
1
1
11
0
5
0
15
0
6
0
16
0
10
1
20
0
c1
DMR1
1
G
8b
DM
(6.4)
c1 A 0,2
1
0,23 (6.5)
32
Glim 1
1
8b
(6.6)
Pentru matricea A:
Glim 1
1
0,96 96%
32
(6.7)
k
k+1
k+2
Jumtatea stng
Jumtatea dreapt
Numrul de linii
Numrul de coloane
Numrul de elemente nenule
Numrul de elemente nenule Numrul de elemente nenule
n linia 1
n linia 2
Numrul de elemente nenule Numrul de elemente nenule
n linia 3
n linia 4
memorat
Indicele de coloan al
ultimului element memorat
1
4
2
4
3
1
4
2 0
5
1
6
3
(5 m m * n * G ) / 2
(6.8)
valoarea fiind rotunjit la cel mai mare ntreg. Numrul total de cuvinte
necesar memorrii unei matrice prin intermediul celor dou zone ZP i ZS este
egal cu
DMR2 = (5 m 3 * m * n * G ) / 2
(6.9)
c2
3G
5 m
2
2*m*n
(6.10)
Glimm
2 5 m
1
0,666 66,6%
3
2m 2
(6.11)
1
1
1
1
2
-2
2
3
3
4
2
5
4
-1
4
2
(6.12)
c3 3 G
(6.13)
ig = i+(j-1)*n
(6.14)
unde n este numrul de coloane a matricei. Acest numr este suficient pentru
identificarea elementului n matrice.
Utiliznd acest artificiu, matricea A se memoreaz astfel:
Locaia
1 2
3
4
Valoare
1 -2 4 -1
Indice agregat, ig 1 12 22 9
Figura 6.5 Model derivat de memorare compact a matricei A
Pentru a regsi indicele de linie i de coloan al oricrui element
memorat n locaia k se utilizeaz urmtoarea tehnic de calcul:
- coloana j este obinut prin relaia:
j ig(k)/n (6.15)
-
(6.16)
c 4 2G
(6.18)
ZP
ZS
1
1
0
2
1
1
3
2
0
4
-2
3
5
4
5
6
4
0
7
-1
2
8
0
0
(6.19)
c5 2 * G
2 * (m 1)
m*n
(6.20)
ZP
ZSL
ZSC
ZSU
1
1
1
1
&2
2
-2
2
3
&3
3
4
2
5
&4
4
-1
4
2
NULL
c6 4 * G
(6.21)
0
7
A
0
0
0
0
8
6
0
0
2
0
0
9
0
0
0
0
(6.22)
5
0.25
54
(6.23)
Se definesc 3 vectori:
lin [ ]
memoreaz poziia liniei ce conine elemente nenule;
col [ ] memoreaz poziia coloanei ce conine elemente nenule;
val [ ] memoreaz valoarea nenul a elementelor.
Vectorii se iniializeaz cu valorile:
Tabelul nr. 6.2 Valorile iniiale ale vectorilor LIN, COL i VAL
LIN
1
2
3
4
4
COL
3
1
4
2
3
VAL
6
7
9
8
2
COL_A
1
2
4
VAL_A
-4
7
8
i
Tabelul nr. 6.4 Valorile matricei rare B
LIN_B
1
2
3
4
4
COL_B
1
2
2
1
3
VAL_B
4
-7
8
5
6
COL_C
1
2
2
1
3
4
?
?
VAL_C
0
0
8
5
6
8
?
?
(6.24)
(6.25)
atunci:
DIM (a) = n - m+1
(6.26)
COL_C
2
1
3
4
?
?
?
?
VAL_C
8
5
6
8
?
?
?
?
12
*100 = 37.5 %
32
(6.27)
7
0
A
0
3
2
0
8
5
4
9
9
0
8
0
8
0
0
5
(6.28)
a[0]
1
a[1]
2
a[2]
a[3]
-1
2 3 4 5
1
A 6
7 8 9 10
11 12 13 14 15
(6.29)
a01
2
b1
a02
3
b2
a03
4
b3
a04
5
b4
a10
6
b5
a11
7
b6
a20
11
b10
a21
12
b11
a22
13
b12
a23
14
b13
a24
15
b14
(6.30)
adr(b[0]) = adr(a[0][0])
(6.31)
(6.32)
8
3
A
0
0
3
0
6
0
0
0
9
0
0
1
0
4
0
7
0
0
0
0
(6.33)
1
1
B
0
1
care prin compactare, ocup
componentele vectorului:
0
1
0
1
0
0
0
1
0
0
1
0
1
0
1
0
0
0
0
(6.34)
C = ( 8, 4, 3, 3, 1, 7, 5, 6, 9)
descrieri, urmai de
(6.35)
Compactarea este procedeul care asociaz un bit fiecrei cifre din forma
liniarizat a matricei B.
class MatriceRara
{
/*******************************/
/*
Atribute
*/
/*******************************/
private:
long dim;
//numarul de elemente nenule
int m,n;
//dimensiunea matricei
int * coloane;
//vectorul pentru index coloane
int * linii;
//vectorul pentru index linii
double * valori;
//vectorul pentru valori
/*******************************/
/* Constructor & Destructor
*/
/*******************************/
public:
MatriceRara(void);
MatriceRara(const MatriceRara & MR);
MatriceRara(int M, int N, int D, double *val, int *lin, int *col);
MatriceRara(double **matrice, int M, int N);
virtual ~ MatriceRara( );
/*******************************/
/*
Metode auxiliare
*/
/*******************************/
public:
bool EsteRara();
static MatriceRara Unitate(int);
double Urma();
double ** GetMatrice();
/*******************************/
/*
Metode de acces
*/
/*******************************/
public:
inline int getDim();
inline int getLinii();
inline int getColoane();
inline double getValoareElement(int i);
inline int getColoanaElement(int i);
inline int getLinieElement(int i);
double getValoareElement(int i,int j);
bool setValoareElement(int i,int j, int valoare);
double operator ()(int i, int j);
friend ostream& operator <<(ostream&, MatriceRara &);
friend istream& operator >>(istream&, MatriceRara &);
/*******************************/
/*
Metode de prelucrare
*/
/*******************************/
void Sortare();
MatriceRara operator =(MatriceRara &);
MatriceRara operator +(MatriceRara &);
MatriceRara operator -(MatriceRara &);
MatriceRara
MatriceRara
MatriceRara
MatriceRara
};
/*****************************/
/* Constructori
*/
/*****************************/
MatriceRara::MatriceRara(void):m(0),n(0),dim(0)
{
coloane=NULL;
linii=NULL;
valori=NULL;
}
MatriceRara::MatriceRara(int M, int N, int D, double *val, int *lin, int
*col)
{
m=M;
n=N;
dim = D;
if(dim)
{
coloane = new int[dim];
linii = new int[dim];
valori = new double[dim];
for(int i=0;i<dim;i++)
{
coloane[i] = col[i];
linii[i] = lin[i];
valori[i] = val[i];
}
}
else
{
coloane = linii = NULL;
valori = NULL;
}
}
MatriceRara::MatriceRara(double **matrice, int M, int N)
{
/*
validare matrice rara
*/
int nenule = 0;
for(int i=0;i<M;i++)
for(int j=0;j<N;j++)
if(matrice[i][j]) nenule++;
if(((nenule*100)/(M*N))>100)
{
/*
matricea nu este rara
*/
coloane = linii = NULL;
valori = NULL;
m = n = dim = 0;
}
else
{
/*
matricea este rara
*/
coloane = new int[nenule];
linii = new int[nenule];
valori = new double[nenule];
m = M;
n = N;
dim = nenule;
int k=0;
for(i=0;i<M;i++)
for(int j=0;j<N;j++)
if(matrice[i][j])
{
coloane[k]= j;
linii[k] = i;
valori[k] = matrice[i][j];
k++;
}
}
}
/*****************************/
/* Copy constructor
*/
/*****************************/
MatriceRara::MatriceRara(const MatriceRara &MR)
{
dim = MR.dim;
m = MR.m;
n = MR.n;
if(dim)
{
coloane = new int[dim];
linii = new int[dim];
valori = new double[dim];
for(int i=0;i<dim;i++)
{
coloane[i] = MR.coloane[i];
linii[i] = MR.linii[i];
valori[i] = MR.valori[i];
}
}
else
{
coloane = linii = NULL;
valori = NULL;
}
}
MatriceRara MatriceRara::operator =(MatriceRara & MR)
{
if(dim)
{
delete[] coloane;
delete[] linii;
delete[] valori;
}
dim = MR.dim;
m = MR.m;
n = MR.n;
if(dim)
{
coloane = new int[dim];
linii = new int[dim];
valori = new double[dim];
for(int i=0;i<dim;i++)
{
coloane[i] = MR.coloane[i];
linii[i] = MR.linii[i];
valori[i] = MR.valori[i];
}
}
else
{
coloane = linii = NULL;
valori = NULL;
}
return *this;
}
/*****************************/
/* Desstructor
*/
/*****************************/
MatriceRara::~MatriceRara()
{
delete[] coloane;
delete[] linii;
delete[] valori;
}
*/
if(linii[i]>linii[i+1])
{
int temp = linii[i];
linii[i] = linii[i+1];
linii[i+1] = temp;
temp = coloane[i];
coloane[i] = coloane[i+1];
coloane[i+1] = temp;
double valoaretemp = valori[i];
valori[i] = valori[i+1];
valori[i+1] = valoaretemp;
flag = true;
}
else
if(linii[i]==linii[i+1])
if(coloane[i]>coloane[i+1])
{
int temp = coloane[i];
coloane[i] = coloane[i+1];
coloane[i+1] = temp;
double valoaretemp = valori[i];
valori[i] = valori[i+1];
valori[i+1] = valoaretemp;
flag = true;
}
}
}
}
bool MatriceRara::setValoareElement(int i, int j, int valoare)
{
/*
metoda valideaza noua valoare */
if(valoare) return false;
for(int k=0;k<dim;k++)
if((coloane[k]==i)&&(linii[k]==j))
{
valori[k]=valoare;
return true;
}
return false;
}
double MatriceRara::operator ()(int i, int j)
{
return this->getValoareElement(i,j);
}
*/
//
//
MatriceRara rezMR;
if((this->m!=MR.m)||(this->n!=MR.n))
return rezMR;
int nrsz = 0, nrsnz = 0;
int i = 0, j = 0;
while((i<this->dim)&&(j<MR.dim))
{
if(this->linii[i]<MR.linii[j])
i++;
else
if(this->linii[i]>MR.linii[j])
j++;
else
if(this->coloane[i]<MR.coloane[j])
i++;
else
if(this->coloane[i]>MR.coloane[j])
j++;
else
if(this->valori[i]+MR.valori[j])
{
nrsnz++;
i++;
j++;
}
else
{
nrsz++;
i++;
j++;
}
}
int rezdim = this->dim+MR.dim-nrsnz-2*nrsz;
rezMR.dim = rezdim;
rezMR.m = this->m;
rezMR.n = this->n;
rezMR.coloane = new int[rezdim];
rezMR.linii = new int[rezdim];
rezMR.valori = new double[rezdim];
//
int k=i=j=0;
while((i<this->dim)&&(j<MR.dim))
{
if(this->linii[i]<MR.linii[j])
{
rezMR.linii[k] = this->linii[i];
rezMR.coloane[k] = this->coloane[i];
rezMR.valori[k] = this->valori[i];
i++;
k++;
}
else
if(this->linii[i]>MR.linii[j])
{
rezMR.linii[k] = MR.linii[j];
rezMR.coloane[k] = MR.coloane[j];
rezMR.valori[k] = MR.valori[j];
k++;
j++;
}
else
if(this->coloane[i]<MR.coloane[j])
{
rezMR.linii[k] = this->linii[i];
rezMR.coloane[k] = this->coloane[i];
rezMR.valori[k] = this->valori[i];
i++;
k++;
}
else
if(this->coloane[i]>MR.coloane[j])
{
rezMR.linii[k] = MR.linii[j];
rezMR.coloane[k] = MR.coloane[j];
rezMR.valori[k] = MR.valori[j];
k++;
j++;
}
else
if(this->valori[i]+MR.valori[j])
{
rezMR.linii[k] = MR.linii[j];
rezMR.coloane[k] = MR.coloane[j];
rezMR.valori[k]
=
this>valori[i]+MR.valori[j];
k++;
j++;
i++;
}
else
{
i++;
j++;
}
}
if(i<this->dim)
for(;i<dim;i++,k++)
{
rezMR.linii[k] = this->linii[i];
rezMR.coloane[k] = this->coloane[i];
rezMR.valori[k] = this->valori[i];
}
if(j<MR.dim)
for(;j<MR.dim;j++,k++)
{
rezMR.linii[k] = MR.linii[j];
rezMR.coloane[k] = MR.coloane[j];
rezMR.valori[k] = MR.valori[j];
}
return rezMR;
}
*/
{
val+=this->getValoareElement(i,k)*MR.getValoareElement(k,j);
}
if(val) rezdim++;
}
rezMR.dim = rezdim;
rezMR.m = this->m;
rezMR.n = MR.n;
rezMR.coloane = new int[rezdim];
rezMR.linii = new int[rezdim];
rezMR.valori = new double[rezdim];
int l = 0;
for(i=0;i<this->m;i++)
for(int j=0;j<MR.n;j++)
{
double val = 0;
for(int k=0;k<this->n;k++)
{
val+=this->getValoareElement(i,k)*MR.getValoareElement(k,j);
}
if(val)
{
rezMR.linii[l] = i;
rezMR.coloane[l] = j;
rezMR.valori[l] = val;
l++;
}
}
return rezMR;
}
1
p1 tr(A1 )
1
1
p 2 tr(A 2 )
2
n: An = A* Bn-1
pn
B1 I p1 * A1
B2 = I p2 * A2
1
tr(A n 1 ) B n 1 I p n 1 * A n 1
n 1
1
tr(A)
n
Bn I p n * A n
(6.36)
if(initialaMR.m==initialaMR.n)
{
double p = initialaMR.Urma() ;
rezMR = initialaMR - (unitateMR*p);
for(int k=2;k<initialaMR.m;k++)
{
tempMR = initialaMR*rezMR;
p = (1.0/(double)k)*tempMR.Urma();
rezMR = tempMR - (unitateMR * p);
}
tempMR = initialaMR*rezMR;
p = (1.0/(double)k)*tempMR.Urma();
rezMR = rezMR*(1.0/p);
}
return rezMR;
}
10
7
0
0
0
0
0
12
0
0
0
9
3
3
0
0
0
0
3
0
0
0
0
0
5
0
0
0
0
0
0
0
0
0
10
0 1 2 3 5
1 3 3 4 7
9 10 7 0 9 12 3 3 3 5 0 10
linia 1
linia 5
//dimensiunea matricei
//numarul de elemente nenule
//vector pentru index start
//vector pentru index terminare
//vector pentru valori
public:
MatriceBanda();
MatriceBanda(double **matrice, int m, int n);
MatriceBanda(const MatriceBanda&);
~MatriceBanda();
double getValoare(int i, int j);}
MatriceDiagonala();
MatriceDiagonala(MatriceDiagonala&);
~MatriceDiagonala();
n 1 * n ,
2
unde n reprezint
n 1
n 1
0 4 7 9
2 9 3 3 7 1 5 10 2 3
linia 1
linia 2
linia 3
linia 4
MatriceTriunghiulara operator+(MatriceTriunghiulara& );
MatriceTriunghiulara operator=(MatriceTriunghiulara& );
friend ostream& operator <<(ostream&, MatriceTriunghiulara&);
};
(const
MatriceTriunghiulara&
{
if(MT.n)
{
this->n=MT.n;
linii = new int[n];
valori = new double[n*(n+1)/2];
for(int i=0;i<n;i++)
linii[i] = MT.linii[i];
for(int j=0;j<n*(n+1)/2;j++)
valori[j]=MT.valori[j];
}
else
{
n=0;
linii = NULL;
valori=NULL;
}
}
MatriceTriunghiulara
MatriceTriunghiulara::operator
(MatriceTriunghiulara &MT)
{
if(n)
{
delete[] linii;
delete[] valori;
}
if(MT.n)
{
this->n=MT.n;
linii = new int[n];
valori = new double[n*(n+1)/2];
for(int i=0;i<n;i++)
linii[i] = MT.linii[i];
for(int j=0;j<n*(n+1)/2;j++)
valori[j]=MT.valori[j];
}
else
{
n=0;
linii = NULL;
valori=NULL;
}
return *this;
}
{
rezMT.linii[i] = this->linii[i];
for(int j=0;j<n-i;j++)
{
rezMT.valori[rezMT.linii[i]+j]=valori[linii[i]+j]+MT.valori[MT.lini
i[i]+j];
}
}
}
return rezMT;
}
0
0
0
1
0
0
1
0
0
0
1
0
0
0
0
0
0
0
0
1
//ordinul matricei
//indexul coloanei
MatricePermutare(const MatricePermutare&);
};
3 2 0 1 5
pe linia i = 2, valoarea 1 se gsete pe
coloana j = 0
x1
x2
(6.38)
y i a 0 a 1x 1i a 2 x 2i
(6.39)
y1 1
y2 1
yn 1
x11
x12
x1n
x 21 a 0 u1
x 2 2 a1 u2
x 2 n a n un
(6.40)
Aadar:
Y = XA + U
(6.41)
Y XA
(6.42)
iar
a 0 , a1 i a 2 . n acest
scop se utilizeaz metoda celor mai mici ptrate. Aceast metod presupune
minimizarea expresiei:
2
t
(6.43)
U U Y XA Y XA
(6.44)
A X X X Y
1
(6.45)
A !X * X .Inversa() * !X * Y (6.46)
Aadar, pentru aflarea matricei A sunt necesare dou operaii de
transpunere, trei nmuliri i o inversare. Matricele X i Y asupra crora se
opereaz au n multe dintre cazurile practice o densitate foarte mic, astfel c
este pe deplin justificat folosirea unor structuri de memorare specifice
matricelor rare.
Asistm n prezent la un fenomen care tinde s ating tot mai multe
domenii de activitate. Necesitatea de a cunoate ct mai precis anumii
factori sau parametri ce caracterizeaz domeniul respectiv, care pn nu de
mult erau fie considerai aleatori, fie nu se punea problema determinrii lor,
considerat a fi imposibil. Cunoaterea acestor factori ofer o descriere mai
detaliat a sistemului n care se lucreaz, permind n acest fel o mai bun
activitate de control i comand a acestuia.
n cele mai multe dintre cazuri baza de calcul a acestor factori o
constituie statistica matematic i teoria probabilitilor, ceea ce conduce la
necesitatea rezolvrii unor probleme liniare de foarte mari dimensiuni.
Caracterul de raritate al structurilor implicate n rezolvarea problemelor,
datorat caracteristicilor reale ale sistemelor, la care se adaug necesitatea unei
rezolvri rapide, n concordan cu dinamica crescnd a sistemelor actuale,
justific pe deplin introducerea n aplicaiile informatice asociate a unor
structuri de date adaptate acestor particulariti.
(7.1)
C8
C1
C2
C3
C4
C5
C6
C7
C9
nume articol
primul element.
din ablon
al 2-lea elem.
din ablon
...
ultimul elem.
din ablon
(7.3)
j 1
unde:
(7.4)
int c4;
int c5;
};
i
a x;
c w,y;
adr(c4)
(7.5)
iar
adr(v[4]) = adr(v[1]) + (4-1) * lg(int)
(7.6)
03 telefon
03 oras
02 varsta
02 data_angajarii
03 zi
03 luna
03 an
02 adresa_actuala
03 data_stabilirii
04 zi
04 luna
04 an
03 strada
03 numar
03 telefon
03 oras
Oricare ar fi modalitatea de descriere a structurii arborescente,
aceasta trebuie s rmn n continuare neambigu.
Dac se accept ca definiie a lungimii elementului de la nivelul i:
ni
lg(x , i ) ( y , j , i 1)
(7.7)
j 0
(7.8)
j 1
k 1
h 1
adr y j , 0 adr y1 , i lg y k , i k lg y h , i k
(7.9)
student
data_nasterii
nume
zi
luna
data_admiterii
an
zi
an
luna
(7.10)
pentru c 2 = 3 = 4 = 0.
Dac se consider punctul operator ca orice alt operator, atunci
construcia:
a.b.c.d
(7.11)
x[0]
nume
varsta
facult
x[1]
x[2]
an_studiu
x[14]
nume
varsta
x[19]
facult
an_studiu
x[14].varsta
n cazul n care cmpurile unui articol sunt elemente ale unui masiv
unidimensional, definim o structur de vectori. De exemplu:
typedef struct student
{
char nume[30];
int note[10];
};
student x;
care
conin
vectori, respectiv
stud y[20];
Pentru a referi nota a 5-a a studentului al 17-lea se face referirea:
y[16].nota[4]
Lucrurile iau amploare dac se definesc structuri de matrice i
matrice de structuri.
Astfel, dac ntr-o secie sunt 20 de muncitori i ntreprinderea are
30 de secii i pentru fiecare muncitor trebuie cunoscut: timpul lucrat,
salariul orar, numele, definind:
typedef struct muncitor
{
char nume[20];
long int salariu;
int ore;
};
long int salariu_total;
muncitor muncit[30][20];
(7.13)
corespunde descrierii:
int c[5][5][5];
iar:
typedef int x[5][5];
x y[5][5];
corespunde descrierii:
int z[5][5][5][5];
(7.14)
(7.15)
(7.16)
(7.17)
<windows.h>
<process.h>
<ctype.h>
<stdio.h>
<conio.h>
<string.h>
struct data
{
int da_year,da_day,da_mon;
};
struct adresa
{
};
char str[25];
int nr;
char bloc[3];
char sc;
int ap;
int sect;
long codp;
char loc[25];
char jud[20];
struct ID
{
char seria[3];
long nr;
data dataE;
int circa;
};
struct actionar
{
char cod[6];
char nume[30];
struct adresa adr;
data dataN;
struct ID BI;
char reprez[6];
int nr_act;
};
struct ind
{
char cheie[6];
long poz;
};
struct nod
{
char sir[6];
nod *st;
nod *dr;
};
ind index[1000];
char *mes[40]={
"Data trebuie sa fie numerica!",
"Ziua trebuie sa fie intre 1 si 31!",
"Luna trebuie sa fie intre 1 si 12!",
"Anul trebuie sa fie intre 1900 si 2001!",
"",
"Data trebuie sa fie cuprinsa intre 0 si 1!",
"Serie incorecta!"
};
long lg_fis()
{
long lung;
FILE *pf;
pf=fopen("actionar.dat","rb");
fseek(pf, 0, SEEK_END);
lung=ftell(pf);
fclose(pf);
return lung;
index[i]=index[j];
index[j]=temp;
fwrite(&act,sizeof(struct actionar),1,pt);
vb=1;
}
fseek(pt,ftell(pt)-sizeof(struct actionar),0);
}
}
while(vb==1);
fclose(pt);
}
while(VB!=0);
i=0;
while(VB==0&&i<strlen(tab))
{
if(isdigit(tab[i]))
i++;
else
VB=1;
}
}
if(VB==0)
sscanf(tab,"%f",&val);
else
eroare(cod);
}
while(VB!=0);
}
while(VB!=0);
i=0;
while(VB==0&&i<2)
{
if(isalpha(tab[i]))
i++;
else
VB=1;
}
}
if(VB==0)
strncpy(val,tab,3);
else
eroare(cod);
}
while(VB!=0);
void sortareA()
{
struct actionar act,act1;
FILE *pf,*pt;
if((pf=fopen("actionar.dat","rb+"))==NULL)
{
printf("Fisierul cu date despre actionari nu exista!");
getch();
return;
}
pt=fopen("temp.dat","wb");
int vb,na=lg_fis()/sizeof(struct actionar);
for(int i=0;i<na;i++)
{
fread(&act,sizeof(struct actionar),1,pf);
fwrite(&act,sizeof(struct actionar),1,pt);
}
fclose(pt);
fclose(pf);
pt=fopen("temp.dat","rb+");
do
{
vb=0;
fseek(pt,0,0);
for(int i=0;i<na-1;i++)
{
fread(&act,sizeof(struct actionar),1,pt);
fread(&act1,sizeof(struct actionar),1,pt);
if ((unsigned)act.nr_act<(unsigned)act1.nr_act)
{
fseek(pt,ftell(pt)-2*sizeof(struct
actionar),0);
fwrite(&act1,sizeof(struct actionar),1,pt);
fwrite(&act,sizeof(struct actionar),1,pt);
vb=1;
}
fseek(pt,ftell(pt)-sizeof(struct actionar),0);
}
}
while(vb==1);
fclose(pt);
}
void creare()
{
int v;
char c,key[6];
FILE *pf;
actionar act;
nod *RAD=NULL;
if ((pf=fopen("actionar.dat","rb"))!=NULL)
{
printf("ATENTIE\n");
printf("Fiserul cu date despre actionari exista!\n");
printf("Datele existente se vor pierde!\n");
printf("Doriti sa-l rescrieti?[D/N]: ");
do
c=getch();
while(c!='D'&&c!='N');
if (c=='N')
{
return;
}
}
if ((pf=fopen("actionar.dat","wb"))==NULL)
{
printf("Eroare la creare!");
exit(1);
}
else
{
printf("Cod: ");
while(scanf("%6s",key)!=0)
{
v=0;
insnod(RAD,key,v);
if (v)
{
printf("\n\aArticolul
cu
aceasta
cheie
exista!");
Sleep(500);
fflush(stdin);
continue;
}
strncpy(act.cod,key,6);
fflush(stdin);
printf("Nume: ");
gets(act.nume);
fflush(stdin);
printf("Adresa actionarului\n");
printf("\tStrada: ");
gets(act.adr.str);
printf("\tNumarul: ");
valid_nr_i(act.adr.nr,1);
printf("\tBloc: ");
scanf("%s",act.adr.bloc);
fflush(stdin);
printf("\tScara: ");
scanf("%c",&act.adr.sc);
printf("\tApartament: ");
valid_nr_i(act.adr.ap,1);
printf("\tSector: ");
valid_nr_i(act.adr.sect,1);
printf("\tCod postal: ");
valid_nr_l(act.adr.codp,1);
fflush(stdin);
printf("\tLocalitatea: ");
gets(act.adr.loc);
printf("\tJudetul: ");
gets(act.adr.jud);
do
{
printf("Data nasterii\n");
printf("\tZiua:");
valid_nr_i(act.dataN.da_day,1);
if(act.dataN.da_day<1||act.dataN.da_day>31)
eroare(2);
}
while(act.dataN.da_day<1||act.dataN.da_day>31);
printf("\tLuna:");
do
{
valid_nr_i(act.dataN.da_mon,1);
if(act.dataN.da_mon<1||act.dataN.da_mon>12)
eroare(3);
}
while(act.dataN.da_mon<1||act.dataN.da_mon>12);
printf("\tAnul:");
do
{
valid_nr_i(act.dataN.da_year,1);
if(act.dataN.da_year<1900||act.dataN.da_year>2001)
eroare(4);
}
while(act.dataN.da_year<1900||act.dataN.da_year>2001);
printf("Buletin de identitate\n");
printf("\tSeria:");
valid_ab_sb(act.BI.seria,7);
printf("\tNumarul:");
valid_nr_l(act.BI.nr,1);
printf("Data eliberarii\n");
printf("\tZiua:");
do
{
valid_nr_i(act.BI.dataE.da_day,1);
if(act.BI.dataE.da_day<1||act.BI.dataE.da_day>31)
eroare(2);
}
while(act.BI.dataE.da_day<1||act.BI.dataE.da_day>31);
printf("\tLuna:");
do
{
valid_nr_i(act.BI.dataE.da_mon,1);
if(act.BI.dataE.da_mon<1||act.BI.dataE.da_mon>12)
eroare(3);
}
while(act.BI.dataE.da_mon<1||act.BI.dataE.da_mon>12);
printf("\tAnul: ");
do
{
valid_nr_i(act.BI.dataE.da_year,1);
if(act.BI.dataE.da_year<1900||act.BI.dataE.da_year>2001)
eroare(4);
}
while(act.BI.dataE.da_year<1900||act.BI.dataE.da_year>2001);
printf("\tCirca de politie: ");
valid_nr_i(act.BI.circa,1);
printf("Numarul de actiuni detinute: ");
valid_nr_i(act.nr_act,1);
printf("\n");
fwrite(&act,sizeof(struct actionar),1,pf);
printf("Cod: ");
}
}
del_arb(RAD);
fclose(pf);
void creare_date()
{
char c;
float ksoc,pfn,cota;
long int val_A;
FILE *pd;
if ((pd=fopen("date.dat","rb"))!=NULL)
{
printf("ATENTIE\n");
printf("Fiserul cu date despre profit exista!\n");
printf("Datele existente se vor pierde!\n");
printf("Doriti sa-l rescrieti?[D/N]: ");
do
c=getch();
while(c!='D'&&c!='N');
if (c=='N')
{
return;
}
}
if ((pd=fopen("date.dat","wb"))==NULL)
{
printf("Eroare la creare!");
getch();
return;
}
printf("DATE PRIVIND CAPITALUL SOCIAL SI PROFITUL\n");
printf("Valoarea unei actiuni:");
valid_nr_l(val_A,1);
fwrite(&val_A,sizeof(long int),1,pd);
printf("Capital Social:");
valid_nr_f(ksoc,1);
fwrite(&ksoc,sizeof(float),1,pd);
printf("Profit net:");
valid_nr_f(pfn,1);
fwrite(&pfn,sizeof(float),1,pd);
do
{
printf("Cota
din
profit
[subunitara]:");
scanf("%f",&cota);
if (cota>1||cota <0)
eroare(6);
}
while(cota>1||cota <0);
fwrite(&cota,sizeof(float),1,pd);
fclose(pd);
}
repartizata
la
dividende
}
}
fclose(pf);
afis_date(act);
getch();
void modif()
{
int n;
char key[6];
int vb,i,nr;
actionar act;
n=indexare();
sortare(n);
FILE *pf=fopen("actionar.dat","rb+");
while(printf("\nCod actionar:"),scanf("%6s",key)!=EOF)
{
vb=cautare(n,i,key);
if(vb==-1)
{
printf("\n\aArticolul cu aceasta cheie nu exista!");
Sleep(500);
}
else
{
fseek(pf,index[i].poz,0);
fread(&act,sizeof(struct actionar),1,pf);
afis_date(act);
printf("Noul numar:");
valid_nr_i(nr,1);
act.nr_act=nr;
fseek(pf,index[i].poz,0);
fwrite(&act,sizeof(struct actionar),1,pf);
}
}
fclose(pf);
}
void listA()
{
FILE *pt,*ptxt;
unsigned int tot_a=0;
long int val_a;
float ksoc;
actionar act;
sortareA();
FILE *pd=fopen("date.dat","rb");
fread(&val_a,sizeof(long int),1,pd);
fread(&ksoc,sizeof(float),1,pd);
fclose(pd);
pt=fopen("temp.dat","rb");
while(fread(&act,sizeof(struct actionar),1,pt))
tot_a+=act.nr_act;
rewind(pt);
ptxt=fopen("lista1.txt","w");
fprintf(ptxt,"\n\n\n\t\tLista
actionarilor
dupa
numarul
de
actiuni\n");
fprintf(ptxt,"\t\t******************************************\n\n
");
fprintf(ptxt,"**************************************************
*********************\n");
fprintf(ptxt,"* Cod
*
Nume
Prenume
* Numar *
Ponderea actiunilor*\n");
fprintf(ptxt,"*
*
* actiuni *
in capitalul social*\n");
fprintf(ptxt,"**************************************************
*********************\n");
while(fread(&act,sizeof(struct actionar),1,pt))
{
fprintf(ptxt,"*%6s
*%-30s*%8u
*%18.3f
%%*\n",act.cod,act.nume,act.nr_act,(float)(unsigned)act.nr_act*val_a/k
soc*100);
fprintf(ptxt,"**************************************************
*********************\n");
}
fprintf(ptxt,"**************************************************
*********************\n");
fclose(pt);
fclose(ptxt);
}
void listD()
{
FILE *pt,*ptxt;
SYSTEMTIME data;
float pfn,cota;
float div;
actionar act;
sortareA();
unsigned int tot_a=0;
FILE *pd=fopen("date.dat","rb");
fseek(pd,sizeof(long int)+sizeof(float),0);
fread(&pfn,sizeof(float),1,pd);
fread(&cota,sizeof(float),1,pd);
fclose(pd);
pt=fopen("temp.dat","rb");
while(fread(&act,sizeof(struct actionar),1,pt))
tot_a+=act.nr_act;
div=(pfn*cota)/tot_a;
rewind(pt);
ptxt=fopen("lista2.txt","w");
GetSystemTime(&data);
fprintf(ptxt,"\n\t\t\t\tDividende cuvenite actionarilor la data
%d.%d.%d\n",data.wDay,data.wMonth,data.wYear);
fprintf(ptxt,"\t\t\t\t******************************************
******\n\n");
fprintf(ptxt,"Profit net:%.0f lei\n",pfn);
fprintf(ptxt,"Cota
de
profit
repartizata
la
dividende:%.2f\n",cota);
fprintf(ptxt,"Total actiuni:%u\n",tot_a);
fprintf(ptxt,"Dividende per actiune:%.2f lei/act\n\n",div);
fprintf(ptxt,"**************************************************
**********************************************************************
\n");
fprintf(ptxt,"*
Nume
Prenume
*
Data
*
Adresa
*Buletin de * Numar * Dividende
*\n");
fprintf(ptxt,"*
* nasterii *
*identitate * actiuni*
*\n");
fprintf(ptxt,"**************************************************
**********************************************************************
\n");
while(fread(&act,sizeof(struct actionar),1,pt))
{
fprintf(ptxt,"*%-30s*%2d.%2d.%d*Str:%-29s
Nr:%-5d*%-2s
%8ld*%8u*%11.2f
*\n",act.nume,act.dataN.da_day,act.dataN.da_mon,act.dataN.da_year,act.
adr.str,act.adr.nr,act.BI.seria,act.BI.nr,act.nr_act,(unsigned)act.nr_
act*div);
fprintf(ptxt,"*
*
*Bl:%c%c%c Sc:%c Ap:%-3d Sect:%-2d Cod p:%-8ld *
*
*
*\n",act.adr.bloc[0],act.adr.bloc[1],act.adr.bloc[2],act.adr.sc,act.ad
r.ap,act.adr.sect,act.adr.codp);
fprintf(ptxt,"*
*
*Loc:%-20s
*
*
*
*\n",act.adr.loc);
fprintf(ptxt,"**************************************************
**********************************************************************
\n");
}
fprintf(ptxt,"**************************************************
**********************************************************************
\n");
fclose(pt);
fclose(ptxt);
}
void listAB()
{
FILE *pt,*ptxt;
actionar act;
sortareN();
pt=fopen("temp.dat","rb");
ptxt=fopen("lista3.txt","w");
fprintf(ptxt,"\n\n\n\t\t\tLista
actionarilor
in
ordine
alfabetica\n");
fprintf(ptxt,"\t\t\t***************************************\n\n"
);
fprintf(ptxt,"\t\t**********************************************
****\n");
fprintf(ptxt,"\t\t*
Nr.
*
Nume
Prenume
*
Numar *\n");
fprintf(ptxt,"\t\t* crt. *
*
actiuni *\n");
fprintf(ptxt,"\t\t**********************************************
****\n");
int i=0;
while(fread(&act,sizeof(struct actionar),1,pt))
{
fprintf(ptxt,"\t\t*%6d
*%-30s*%8u
*\n",++i,act.nume,act.nr_act);
fprintf(ptxt,"\t\t**********************************************
****\n");
}
fprintf(ptxt,"\t\t**********************************************
****\n");
fclose(pt);
fclose(ptxt);
void do_sterg()
{
int n,c;
int vb,i;
actionar act;
n=indexare();
sortare(n);
char key[6];
FILE *pf=fopen("actionar.dat","rb");
while(printf("\nCod actionar:"),scanf("%6s",key)!=0)
{
vb=cautare(n,i,key);
if(vb==-1)
{
printf("\n\aArticolul cu aceasta cheie nu exista!\n");
Sleep(500);
fflush(stdin);
continue;
}
else
{
fseek(pf,index[i].poz,0);
fread(&act,sizeof(struct actionar),1,pf);
afis_date(act);
printf("Doriti sa stergeti acest articol?[D/N]: ");
do
{
c=getch();
}
while(c!='D'&&c!='N');
if (c=='N')
{
continue;
}
}
//rescriere fisier
FILE *ptmp=fopen("tmp.dat","wb");
rewind(pf);
for(int j=0;j<index[i].poz/sizeof(struct actionar);j++)
{
fread(&act,sizeof(struct actionar),1,pf);
fwrite(&act,sizeof(struct actionar),1,ptmp);
}
fread(&act,sizeof(struct actionar),1,pf);
while(fread(&act,sizeof(struct actionar),1,pf))
fwrite(&act,sizeof(struct actionar),1,ptmp);
fclose(pf);
fclose(ptmp);
unlink("actionar.dat");
rename("tmp.dat","actionar.dat");
n=indexare();
sortare(n);
pf=fopen("actionar.dat","rb");
}
fclose(pf);
}
void adaug()
{
int v;
char key[6];
actionar act;
nod *RAD=NULL;
FILE *pf;
if ((pf=fopen("actionar.dat","rb+"))==NULL)
{
printf("Fiserul cu date despre actionari nu exista!");
return;
}
else
{
strncpy(act.reprez,"
",6);
while(fread(&act,sizeof(struct actionar),1,pf))
insnod(RAD,act.cod,v);
//fseek(pf,0,2);
printf("Cod:\n");
while(scanf("%6s",key)!=0)
{
v=0;
insnod(RAD,key,v);
if (v)
{
printf("\n\aArticolul cu aceasta cheie exista!\n");
Sleep(500);
fflush(stdin);
continue;
}
strncpy(act.cod,key,6);
fflush(stdin);
printf("Nume: ");
gets(act.nume);
fflush(stdin);
printf("Adresa actionarului\n");
printf("\tStrada: ");
gets(act.adr.str);
printf("\tNumarul: ");
valid_nr_i(act.adr.nr,1);
printf("\tBloc: ");
scanf("%s",act.adr.bloc);
fflush(stdin);
printf("\tScara: ");
scanf("%c",&act.adr.sc);
printf("\tApartament: ");
valid_nr_i(act.adr.ap,1);
printf("\tSector: ");
valid_nr_i(act.adr.sect,1);
printf("\tCod postal: ");
valid_nr_l(act.adr.codp,1);
fflush(stdin);
printf("\tLocalitatea: ");
gets(act.adr.loc);
printf("\tJudetul: ");
gets(act.adr.jud);
do
{
printf("Data nasterii\n");
printf("\tZiua:");
valid_nr_i(act.dataN.da_day,1);
if(act.dataN.da_day<1||act.dataN.da_day>31)
eroare(2);
}
while(act.dataN.da_day<1||act.dataN.da_day>31);
printf("\tLuna:");
do
{
valid_nr_i(act.dataN.da_mon,1);
if(act.dataN.da_mon<1||act.dataN.da_mon>12)
eroare(3);
}
while(act.dataN.da_mon<1||act.dataN.da_mon>12);
printf("\tAnul:");
do
{
valid_nr_i(act.dataN.da_year,1);
if(act.dataN.da_year<1900||act.dataN.da_year>2001)
eroare(4);
}
while(act.dataN.da_year<1900||act.dataN.da_year>2001);
printf("Buletin de identitate\n");
printf("\tSeria:");
valid_ab_sb(act.BI.seria,7);
printf("\tNumarul:");
valid_nr_l(act.BI.nr,1);
printf("Data eliberarii\n");
printf("\tZiua:");
do
{
valid_nr_i(act.BI.dataE.da_day,1);
if(act.BI.dataE.da_day<1||act.BI.dataE.da_day>31)
eroare(2);
}
while(act.BI.dataE.da_day<1||act.BI.dataE.da_day>31);
printf("\tLuna:");
do
{
valid_nr_i(act.BI.dataE.da_mon,1);
if(act.BI.dataE.da_mon<1||act.BI.dataE.da_mon>12)
eroare(3);
}
while(act.BI.dataE.da_mon<1||act.BI.dataE.da_mon>12);
printf("\tAnul: ");
do
{
valid_nr_i(act.BI.dataE.da_year,1);
if(act.BI.dataE.da_year<1900||act.BI.dataE.da_year>2001)
eroare(4);
}
while(act.BI.dataE.da_year<1900||act.BI.dataE.da_year>2001);
printf("\tCirca de politie: ");
valid_nr_i(act.BI.circa,1);
printf("Numarul de actiuni detinute: ");
valid_nr_i(act.nr_act,1);
printf("\n");
fwrite(&act,sizeof(struct actionar),1,pf);
printf("Cod: ");
}
}
del_arb(RAD);
fclose(pf);
void men_fis()
{
int rasp,cont=1;
while(cont)
{
do
{
printf("MENIUL FISIERE\n\n");
printf("1.CREARE FISIER ACTIONARI\n");
printf("2.CREARE FISER CU DATE PRIVIND PROFITUL\n" );
printf("3.ADAUGARE ACTIONARI\n");
printf("4.MODIFICARE NUMAR DE ACTIUNI\n");
printf("5.STERGERE ACTIONARI DIN FISIER\n");
printf("6.REVENIRE LA MENIUL PRINCIPAL\n\n");
printf("Optiunea:");
valid_nr_i(rasp,5);//scanf("%d",&rasp);
}
while(rasp<1||rasp>6);
switch(rasp)
{
case 1:creare();break;
case 2:creare_date();break;
case 3:adaug();break;
case 4:modif();break;
case 5:do_sterg();break;
case 6:cont=0;break;
}
}
}
void men_sit()
{
int rasp,cont=1;
while(cont)
{
do
{
printf("MENIUL SITUATII DE IESIRE\n\n");
printf("1.LISTA ACTIONARILOR IN ORDINEA NUMARULUI DE
ACTIUNI\n");
printf("2.LISTA
ACTIONARILOR
IN
ORDINE
ALFABETICA\n");
printf("3.LISTA
DIVIDENDELOR
CUVENITE
FIECARUI
ACTIONAR\n");
printf("4.CONSULTARE FISIER DUPA COD ACTIONAR\n");
printf("5.REVENIRE LA MENIUL PRINCIPAL\n\n");
printf("Optiunea:");
valid_nr_i(rasp,5);//scanf("%d",&rasp);
}
while(rasp<1||rasp>5);
switch(rasp)
{
case 1:listA();break;
case 2:listAB();break;
case 3:listD();break;
case 4:cons();break;
case 5:cont=0;break;
}
void main()
{
int rasp,cont=1;
while(cont)
{
do
{
printf("MENIUL PRINCIPAL\n\n");
printf("1.FISIERE\n");
printf("2.SITUATII DE IESIRE\n");
printf("3.TERMINARE PROGRAM\n\n");
printf("Optiunea:");
valid_nr_i(rasp,5);//scanf("%d",&rasp);
}
while(rasp<1||rasp>3);
switch(rasp)
{
case 1:men_fis();break;
case 2:men_sit();break;
case 3:cont=0;break;
}
}
}
8. VARIABILE POINTER
8.1 Tipul variabilei pointer
Pentru programatorii care cunosc un limbaj de asamblare, definirea i
utilizarea variabilelor pointer n limbaje evoluate de programare reprezint
operanzii necesari implementrii adresrii indirecte.
La adresarea indirect se utilizeaz doi operanzi i anume: operandul
care refer i operandul referit, notai n continuare R0, respectiv Or.
Operandul R0 conine adresa de nceput a zonei de memorie asociat
operandului Or. Evaluarea expresiilor:
R0 adr(Or), Or 15
(8.1)
cont(R0) adr(Or)
(8.2)
R0
Or
07441A
15
07441A
(8.3)
adic
(8.4)
(8.5)
R0
07441A
07441A
Figura 8.2 Noul coninut al operandului R0
n sine, expresia nu are o semnificaie deosebit, mai mult ofer
riscul nchiderii unui lan de referire, transformndu-l n ciclu infinit. Dac
operandul R0 devine reper i toate deplasrile sunt evaluate avndu-l ca
baz, expresia de mai sus se justific.
Dac se definesc variabilele a, b, c avnd tipul Ti, i variabilele pa,
pb, pc avnd tipul Tp, evaluarea expresiilor:
pa = adr(a)
pb = adr(b)
pc = adr(c)
realizeaz iniializarea operanzilor de tip Tp.
Dac sunt luate n considerare aceste expresii, n loc de:
c = a+b;
(8.6)
se va utiliza expresia:
ref(pc) = ref(pa)+ref(pb)
(8.7)
(8.8)
unde mulimea
este interpretat drept coninutul zonei de memorie
asociate identificatorilor.
Se observ c prin definirea funciei adr():
(8.9)
funciile adr() i ref() nu sunt una invers celeilalte. Este adevrat numai
egalitatea:
x = ref(adr(x))
(8.10)
ref(x)
adr(x)
(8.11)
ref(adr(xi)) ref(adr(xj))
(8.12)
(8.13)
unde Ti, reprezint tipul variabilei referite i pointer este tipul specific,
fundamental al variabilei. Dac variabila care refer px, este de tip Tp i
variabila referit x, este de tip Ti, n vorbirea curent expresia se
interpreteaz, pornind de la efectul fizic al operaiilor cu pointeri, ca pointer
spre Ti.
Dac x are tipul int i px este de tip Tp, se spune c px este pointer
spre int i toi operatorii din expresiile omogene ca tip de date unde apare
px, sunt selectai pentru lucrul cu operanzi de tip int.
Tipul variabilei referite nu influeneaz lungimea variabilelor de tip Tp
i coninutul.
Dac o variabila x, este definit ca avnd tipul Ti i variabila px este
definit ca avnd tipul (pointer, Tj), expresia:
px = adr(x) (8.14)
nu este evaluat dect numai dup ce ara loc conversia de la tipul Ti la tipul
Tj, operatorul de atribuire necesitnd operanzi de acelai tip. Aceast
conversie realizeaz de fapt schimbarea setului de informaii n concordan
cu operandul din stnga.
Prin conversie, adresa este asociat unei variabile de tip Tj cu toate
implicaiile ce decurg asupra alinierilor i lungimii zonelor de memorie
asociate noului tip, asociat zonei de memoria pus n coresponden cu
variabila x.
Exist situaii n care conversia de tip este implicit (n cazul evalurii
expresiilor aritmetice), dar sunt numeroase cazurile n care aceasta trebuie
specificat explicit.
Funcia conv(x, Tj) modific tipul variabilei x de la Ti la Tj. Dac:
tip(x) = Ti
(8.15)
x = conv(x,Tj)
(8.16)
conduce la:
tip(x) = Tj
(8.17)
i n mod corespunztor:
px = convp(adr(x),Tj)
(8.18)
(8.19)
(8.20)
(8.21)
(8.22)
(8.23)
evaluarea expresiei:
px = px + 6 = adr(x[l]) + l*lg(real) = adr(x[2])
(8.24)
(8.25)
i se evalueaz expresia:
px = px-24
(8.26)
px = adr(x[10])-4*lg(real) = adr(x[6])
(8.27)
n expresiile:
adr(z+k) = adr(z)+k*lg(Ti)
(8.28)
unde z este o variabil de tip Ti, se observ c pentru variabila pz de tip Tp,
care a fost iniializat prin:
pz: = adr(z);
(8.29)
adr(z+k) = pz + k*lg(Ti)
(8.30)
variabila px, permite referirea rnd pe rnd a elementelor x[0], x[1], ...,
x[9] ale vectorului x.
Mai mult, definind px variabila de tip Tp n secvena:
px = adr(x);
s = 0;
pi = adr(x[0]);
do
{
s = s+ref(pi);
pi = pi+4 ;
} while (pi <= adr(x[9]));
(8.31)
(8.32)
(8.33)
(8.34)
Se consider c expresia:
px+int(expr(a0 a1 .....an-1))*lg(Ti) =
(8.35)
// (pointer, integer);
// (pointer,(pointer, integer));
prin expresiile:
x = 20;
px = adr(x);
ppx = adr(px));
(8.36)
(8.37)
y = 15;
px = &x;
py = &y;
ppx = &px;
*py = *py + **ppx;
cout << *py ;
};
Construcia
(pointer, Tp) permite compunerea unei funcii adr()
asociate nivelurilor indirectate.
n definiia:
int
int
int
int
x ;
*px ; // (pointer, integer)
**ppx ; // (pointer, (pointer, integer))
***pppx ; // (pointer, (pointer,(pointer, integer)))
i din secvena:
x = 17;
px =adr(x);
ppx = adr(px);
pppx = adr(ppx);
se obine:
pppx - adr(adr(adr(x))) = adr3 (x)
(8.38)
(8.39)
(8.40)
Ptr($00AA,$0020);
(8.41)
(8.42)
Dac se definete:
int x1[10], x2[10], x3[10], x4[10];
Tp y[4];
T 2p z;
prin atribuirile:
y[0]=adr(xl[0]);
y[1]=adr(x2[0]);
y[2]=adr(x3[0]);
y[3]=adr(x4[0]);
z = adr(y[0]);
y[0]
y[1]
X2
3]2]
y[
y[3]
X3
X4
(8.43)
(8.44)
i = pi;
i = 1, 2, ...,n
(8.45)
i = conv(pi,Ti)
(8.46)
(8.47)
iniializat astfel:
pf[i] = f( );
i=1, 2, , m
(8.48)
definesc:
x ca variabil de tip articol;
y ca variabil de tip pointer spre articol.
Expresiile:
y = adr(x)
ref(y).m1
(8.49)
(8.50)
ref(y).c = adr(z)
ref(y) = ref(c)
(8.51)
(8.52)
Funciei
Instruciunea:
de
referire
px
= & x;
py
= & y;
corespunde
operatorul
*.
(8.53)
int d;
int e;
int * g;
};
typedef
b *a;
a x;
b y;
Expresiile:
x = & y;
x->c = 3
x->d = x-> c*5;
x->e = 1
x->g = Addr(x,e);
x->e = x-> e +x-> g;
int c;
c * b;
b * a;
a x;
b y;
c z;
expresiile:
z =
y =
x =
cout
7;
&z;
&y;
<< **x;
&(x);
&(p1);
&(pk-1);
Instruciunile:
int * px;
int x;
px = &(x);
x = 7;
cout << *px
int i,j,k;
int s[3] = {0,0,0};
mat a = {1,1,1,2,2,2};
mat b = {3,3,3,4,4,4};
mat c = {5,5,5,6,6,6};
main()
{
vp[0] = &a;
vp[1] = &b;
vp[2] = &c;
for (i=0; i<3 ;i++)
vpp[i] = &vp[i];
for (k=0 ; k<3 ; k++)
{
for (i=0; i<2; i++)
for (j=0; j<3; j++)
s[k] + = (**vpp[k])[i][j];
cout<<"\n Suma matricei "<<k<<" este "<<s[k];
}
}
n programul:
//pointeri spre vectori de pointeri
#include <iostream>
using namespace std;
typedef vecp *pvec;
int * ppp;
vec a = {1,2,3,4,5};
vecp p;
pvec pp;
int i;
main()
{
for (i=0; i<5; i++)
p[i] = &a[i];
ppp = a;
pp = &p;
for (i=0; i<5; i++)
{
cout<<"\n"<<*(ppp+i)<<" ** "<<(*p[i]);
cout<<"\n"<<(*(*pp)[i]);
}
}
st[0].aa[0] = 100;
st[0].aa[1] = 200;
st[0].paa[0] = &st[0].aa[0];
st[0].paa[1] = &st[0].aa[1];
st[1].aa[0] = 300;
st[1].aa[1] = 400;
st[1].paa[0] = &st[1].aa[0];
st[1].paa[1] = &st[1].aa[1];
pst[0] = &st[0];
pst[1] = &st[1];
pss = &pst;
st[0].pppa = &st[0].paa;
st[1].pppa = &st[1].paa;
for (i=0; i<2; i++)
for (j=0; j<2; j++)
{
cout<<"\n*"<<st[i].aa[j]<<"**"<<*(pst[i]->paa[j]);
cout<<"++"<<*((*pss)[i]->paa[j])<<"--"<<*((*pss)[i]->pppa[j]);
}
}
cod_material
01A880
cod_grup
cod_subgrup
0100A0
0100A0
(9.1)
secvena:
for(i=0; i<10; i++)
for(j=0; j<10; j++)
for(k=0; k<10; k++)
a[i][j][k] = 0;
Etapa
Etapa 1
Etapa 2
Etapa 3
*
*
*
*
01 AA00
B [ 1, 1]
U [1]
01 BB00
V[1]
01 BB00
X [1]
C
01 CC00
(9.2)
i:
union (m1, m2,...,mn) = TRUE
(9.3)
[Ai, Af] N
(9.4)
Se noteaz:
(9.5)
i:
(9.6)
(9.7)
(9.8)
dac:
i 1, 2, ..., n
adr (mi)
(9.9)
i structura:
struct k
{
int x;
char g[10];
};
k t;
i datele elementare:
int x, y;
Funcia:
union (a[3], b[5], g, x, y )
(9.10)
a0
b0
b1
b2
a1
b3
a3
b4
g0
g1
g2
.......
g8
g9
x
y
Figura 9.4 Modelul grafic al suprapunerilor pe o zon de memorie
adr ( a [3] ) = adr ( b [5] ) = adr ( t*g) = adr (x) = adr (y) =
(9.11)
x[i][j]=i*3+j;
cout<<"Adresa de memorie alocata pentru x este:"<<&x<<endl;
cout<<"Adresa de memorie alocata pentru y este:"<<&y<<endl;
cout<<"Adresa de memorie alocata pentru z este:"<<&z<<endl;
cout<<"Adresele de memorie la care sunt stocate liniile pornind
de la variabila x:"<<endl;
for(i=0;i<3;i++)
cout<<"Linia "<<i+1<<"este incepe la adresa "<<x[i]<<endl;
cout<<"Adresele de memorie la care sunt stocate liniile pornind
de la variabila y:"<<endl;
for(i=0;i<3;i++)
cout<<"Linia "<<i+1<<"este incepe la adresa "<<y[i]<<endl;
cout<<"Adresele de memorie la care sunt stocate liniile pornind
de la variabila z:"<<endl;
for(i=0;i<3;i++)
cout<<"Linia
"<<i+1<<"este
incepe
la
adresa
"<<*(z+i)<<endl;
cout<<"Elementele matricei afisate prin variabila x:"<<endl;
for(i=0;i<3;i++){
cout<<endl;
for(int j=0;j<3;j++)
cout<<"X["<<i+1<<"]["<<j+1<<"]="<<x[i][j]<<" ";
}
cout<<"Elementele matricei afisate prin variabila y:"<<endl;
for(i=0;i<3;i++){
cout<<endl;
for(int j=0;j<3;j++)
cout<<"Y["<<i+1<<"]["<<j+1<<"]="<<*(y[i]+j)<<" ";
}
cout<<"Elementele
matricei
afisate
prin
variabila
z:"<<endl;
for(i=0;i<3;i++){
cout<<endl;
for(int j=0;j<3;j++)
cout<<"Z["<<i+1<<"]["<<j+1<<"]="<<*(*(z+i)+j)<<" ";
}
cout<<"Adresele elementelor matricei afisate prin variabila
x:"<<endl;
for(i=0;i<3;i++){
cout<<endl;
for(int j=0;j<3;j++)
cout<<"ADR(X["<<i+1<<"]["<<j+1<<"])="<<&x[i][j]<<" ";
}
cout<<"Adresele elementelor matricei afisate prin variabila
y:"<<endl;
for(i=0;i<3;i++){
cout<<endl;
for(int j=0;j<3;j++)
cout<<"ADR(Y["<<i+1<<"]["<<j+1<<"])="<<y[i]+j<<" ";
}
cout<<"Adresele
elementelor
matricei
afisate
prin
variabila
z:"<<endl;
for(i=0;i<3;i++){
cout<<endl;
for(int j=0;j<3;j++)
cout<<"ADR(Z["<<i+1<<"]["<<j+1<<"])="<<*(z+i)+j<<" ";
}
=
=
=
=
=
=
=
=
=
y[0]+0
y[0]+1
y[0]+2
y[1]+0
y[1]+1
y[1]+2
y[2]+0
y[2]+1
y[2]+2
=
=
=
=
=
=
=
=
=
*(z+0)+0
*(z+0)+1
*(z+0)+2
*(z+1)+0
*(z+1)+1
*(z+1)+2
*(z+2)+0
*(z+2)+1
*(z+2)+2
ntre variabilele x i z.
Astfel, aceeai zon de memorie este accesat prin intermediul
variabilelor x, y i z.
n condiiile construirii de tipuri de date derivate, nu se efectueaz
alocare de zone de memorie. Prin definirea de variabile pointer p1, p2, ..., pn
spre tipurile de date derivate, o dat cu construirea modelului grafic al
reuniunii de date, se evalueaz adresa ca fiind adresa de nceput a unei
variabile dk, din lista d1, d2, ..., dn.
(9.12)
cu condiia ca:
adr(m1) = adr(m2) = ... = adr(mn)
Se calculeaz deplasrile:
Di = depl(di, dk)
cu Di > 0 pentru i = 1, 2, ..., n.
Prin evaluarea expresiei:
(9.14)
(9.13)
Pi convp ( , Ti ) D i
(9.15)
se obine adresa de nceput a fiecrei date din tipul Ti, astfel nct:
adr(m1) = adr(m2) = ... = adr(mn) = adr(d1) + depl(m1, d1)
(9.16)
(9.17)
(9.18)
(9.19)
lg(dk) - lg(d'k)=1
(9.20)
d1
d'1
d'2
d4
d3
d'3
d'4
d5
d'5
(9.21)
(9.22)
unde Ti, este unul din tipurile fundamentale T1, T2,..., Tn, n fiind numrul de
tipuri fundamentale implementate n limbajul de programare considerat.
Masivul unidimensional, se definete ca tip vector Tv astfel:
Tv = (Ti, Ti, ..., Ti)
(9.23)
(9.24)
(9.25)
(9.26)
(9.27)
(9.28)
dac exist cel puin un Tki Txi, astfel nct oricare ar fi dou elemente de
tip Txi i Txj s existe:
tadr ( Tk i ) tadr ( Tk j )
(9.29)
unde, Tki reprezint tipul membrului cu poziia k din tipul derivat Txi.
n acest context, tadr(Tki) reprezint o mulime a adreselor
operanzilor de tip Tki ai structurii de tip derivat Txi.
Se consider spre exemplificare structurile:
struct a
{
char e[20];
int a;
float c;
};
i:
struct x
{
int y;
char z[4];
float u;
int w;
};
Se consider structura:
Ta = ( char[], int, float, bool)
(9.30)
(9.31)
i structura:
(9.32)
(9.33)
(9.34)
(9.35)
(9.36)
(9.37)
(9.38)
tadr ( Tx bool )
(9.39)
(9.40)
deci:
union ( Ta , Tx ) TRUE
(9.41)
(9.42)
(9.43)
int i, j;
for(i=0; i<9; i++)
z.b[i] = i * i;
for(i=0; i<3; i++)
{
for(j=0; j<3; j++)
cout<<"\n "<<z.a[i][j];
}
strcpy(u2.un1.x,"1234567890");
cout<<u2.un1.x;
cout<<"\n";
for(int i=0; i<5; i++)
u2.un2.y[i]='a'+i;
for(i=0; i<5; i++)
cout<<u2.un2.y[i];
cout<<"\n"<<u2.un1.x;
cout<<"\n";
INFO
URM
NULL
PREC
INFO
URM
NULL
n situaia n care se realizeaz o nchidere a nlnuirilor, pierznduse astfel noiunile de nceput i de sfrit ale unei liste liniare, se obine o
list circular simplu sau dublu nlnuit.
INFO
URM
prim
NULL
ultim
acestuia ntr-o poziie oarecare a listei, i anume, dup sau naintea unui
anumit nod specificat prin referina sa spec. Schematic cele dou situaii
sunt prezentate n figurile urmtoare, observndu-se o oarecare dificultate
la operaia de inserie a noului nod naintea celui specificat.
spec
spec
INFO
void Lista::inserare_ordonata(TINFO X)
{
ElementLista *q1=NULL,*q2;
ElementLista* ptr=new ElementLista(X);
if (ptr==NULL)
{
cout<<"Eroare la alocare spatiu pentru inserare";
return;
}
for(q2=Prim;q2&&q2->info<X;q1=q2,q2=q2->urm);
if(q2==Prim)
{
if(Prim==NULL) Ultim=ptr;
ptr->urm=Prim;
Prim=ptr;
}
else
{
if(q2==NULL) Ultim=ptr;
q1->urm=ptr;
ptr->urm=q2;
}
cout<<"Inserare ordonata cu succes!\n";
}
return(q);
else
return(0);
}
cout<<"\n";
void Lista::inserare(int X)
{
ElementLista *p;
for(p=Prim;p&&p->info!=X;p=p->urm);
if(p)
p->contor++;
Else
{
p=new ElementLista(X);
p->urm=Prim;
Prim=p;
}
}
void main()
{
Lista Listamea;
int cheie;
cout<<"Introduceti cheia de inserat:";
cin>>cheie;
while(cheie)
{ Listamea.inserare(cheie);
cout<<"Introduceti cheia de inserat:";
cin>>cheie;
}
cout<<"Inserare incheiata!\n";
cout<<"\nTraversare lista:\n";
Listamea.traversare();
}
q2
q1
prim
3
X
INFO
URM
prim
NULL
fanion
if(q1)
{
q1->contor++;
if(q2)
{
q2->urm=q1->urm;
q1->urm=Prim;
Prim=q1;
}
}
else
{
p=new ElementLista(X);
p->urm=Prim;
Prim=p;
}
public:
ElementLista(int val=0);
friend class Lista;
};
class Lista
{
protected:
ElementLista *Ultim;
public:
Lista()
{ Ultim = NULL;}
~Lista();
void traversare();
void inserare_sfarsit(TINFO);
void inserare_inaintea_unui_elem(TINFO,TINFO);
ElementLista *cautare(TINFO);
void suprimare(TINFO);
};
ElementLista::ElementLista(TINFO val)
{
info=val;
urm=NULL;
}
Lista::~Lista()
{
ElementLista* ptr;
if(Ultim!=NULL)
{ while (Ultim->urm!=Ultim)
{
ptr=Ultim->urm;
Ultim->urm=Ultim->urm->urm;
delete ptr;
}
delete Ultim;
}
}
void Lista::traversare()
{
ElementLista* ptr=Ultim;
if (Ultim==NULL)
cout << "\n Lista este vida! \n";
else
{ while (ptr->urm!=Ultim)
{
ptr=ptr->urm;
cout << ptr->info<<" ";
}
cout << ptr->urm->info<<" ";
cout<<"\n";
}
}
void Lista::inserare_sfarsit(TINFO val)
{
ElementLista* ptr=new ElementLista(val);
if (ptr==NULL)
{
}
if(Ultim)
{
ptr->urm=Ultim->urm;
Ultim->urm=ptr;
Ultim=ptr;
}
else
{
Ultim=ptr;
ptr->urm=ptr;
}
cout<<"Inserare sfarsit cu succes!\n";
if(q2->info==X)
{
if(q2->urm==q2)
{
Ultim=NULL;
delete(q2);
}
else
{
if(q2==Ultim) Ultim=q1;
q1->urm=q2->urm;
delete(q2);
}
cout<<"Suprimare cu succes!\n";
}
else
cout<<"Nodul nu exista!\n";
void main()
{
Lista Listamea;
int opt;
TINFO valoare,cheie;
do
{
cout<<"\n Optiuni de lucru cu lista:";
cout<<"\n 1 - Afisare lista";
cout<<"\n 2 - Inserare element la sfarsitul listei";
cout<<"\n 3 - Inserare element inaintea unui elem specificat";
cout<<"\n 4 - Cautarea unui element specificat";
cout<<"\n 5 - Suprimarea unui element";
cout<<"\n 9 - Terminare lucru \n\n";
cout<<"Introduceti optiunea dorita:";
cin>>opt;
switch(opt)
{
case 1:
{
cout<<"Traversare lista:";
Listamea.traversare();
break;
}
case 2:
{
cout<<"Introduceti elementul de inserat:";
cin>>valoare;
Listamea.inserare_sfarsit(valoare);
break;
}
case 3:
{
cout<<"Introduceti elementul de inserat:";
cin>>valoare;
cout<<"Introduceti elem inaintea caruia inseram:";
cin>>cheie;
Listamea.inserare_inaintea_unui_elem(valoare,cheie);
break;
}
case 4:
{
prin [ D i , D f ] N , unde:
Di
adresa de nceput a zonei;
adresa de sfrit a zonei.
Df
La intrarea n execuie a programului, un registru RO, sau o zon de
memorie fixat, se iniializeaz cu valoarea Di.
Dac ntr-un program este activat funcia de alocare definit prin:
y = alocare (lg (Ti) )
(10.1)
i
(10.2)
alocare : N [ D i , D f ] N
Dac:
cont ( RO ) > Df
lg ( Ti )
(10.3)
(10.4)
0
(10.5)
(10.6)
RO = RO lg ( Ti )
(10.7)
(10.8)
i variabila x din
alocare (lg (x) )
(10.9)
(10.10)
int a[50][50];
(10.11)
(10.12)
i se are n vedere c:
lg ( Pi )
lg ( P )
(10.13)
(10.14)
a0
a1
a2
a3
a4
a5
a6
a7
a8
a9
...
b0
b1
b2
b8
b9
(10.15)
i dac:
adr( Ei+1 ) = adr( Ei ) + lg(TE) + i
(10.16)
(10.17)
pred( Zj) = Zj 1
(10.18)
i
adr( Zj+1 ) = adr( Zj ) + lg(Ti) + j = j
(10.19)
Dac:
1 = 2 = = n
(10.20)
nu se mai justific,
(10.21)
j = cont ( RO )
(10.22)
(10.23)
zona;
unde pg este o variabil de tip pa, iar pa la rndul ei este un pointer spre
structura zona, se aloc o zon de memorie de adresa cont(RO) i lungime
lg(Tzona), ce este referit folosind variabila pointer pg, care este de tipul Tp =
(pointer, Tzona).
n program, membrii structurii se refer prin:
pg->i
pg->j
pg->val
j = adr(succ( Zj ))
(10.24)
pg
01788 A
018800
pg->poz = pn;
new(pg)
01788 A
i
Zj
new (pn)
018800
i
val
poz
val
Zj+1
(10.25)
atunci:
grafic:
(10.26)
pg->poz->poz = NULL;
(10.27)
...
n conduce la modelul
NULL
Totul depinde de modul n care programul solicit spaii din zon [Di,
Df] N i mai ales de dimensiunile proiectate ale acestei zone la generarea
sistemului de operare.
Dac n loc de:
adr( succ( Zn)) = NULL
(10.28)
se construiete:
adr( succ( Zn)) = adr( Z1)
(10.29)
...
pg->poz = pn;
pg->poz = pg;
Figura 10.10 Modelul grafic al listei circulare
Lungimea listei liniare:
L lg [ ( Z i , i ) ]
(10.30)
i <> NULL
(10.31)
i 1
parcurgere (pg)
{
while (pg->poz != NULL)
{
tipareste (pg->i, pg->j, pg->val);
parcurgere (pg->poz);
}
}
(10.32)
Zk-1
Zk
k+1
Zk+1
k+2
....
Zk-1
k+1
Zk
k+1
Zk+1
k+2
....
(10.33)
( Z1, 1)
( Z2, 2)
( Z3, 3)
...
...
NULL
( U1, 1)
( U2, 2)
( U3, 3)
( Zn, n)
( Um, m)
(10.34)
(10.35)
(10.36)
cont(Zj) = cont(Zj)
(10.37)
astfel nct:
pentru j = 1, 2, ..., n.
copiere_lista (w, u)
{
while (ref (w). != NULL)
{
ref (u).Z = ref (w).Z;
alocare (v);
ref (u). = v;
copiere_lista (ref (w).), v);
}
ref (u). = NULL;
}
cont ( Z j ) cont ( Z j 1 )
(10.38)
pentru orice j = 1, 2, , n 1.
A insera un element ntr-o list, nseamn mai nti a gsi o valoare k
{1, 2, , n} astfel nct:
cont ( Z k ) a cont ( Z k 1 )
(10.39)
cont ( Z k ) a cont ( Z k 1 )
(10.40)
sau
dup cum lista este ordonat cresctor sau descresctor. n aceste condiii,
inserarea elementului a, nseamn conform modelului grafic, a trece de la
configuraia:
(Zk, k)
(Zk+1, k+1)
...
...
a
(, )
Figura 10.14 Configuraia nainte de inserare nodului n interiorul listei
la configuraia:
(Zk+1, k+1)
(Zk, adr())
...
...
a
(, adr (Zk+1))
Figura 10.15 Configuraia dup inserarea nodului n interiorul listei
Exist cazuri particulare de inserare n care elementul este poziionat
fie la nceputul listei, fie la sfritul acesteia, operaia numindu-se adugare.
Dac elementele a i b vor fi inserate la nceputul, respectiv, la
sfritul listei, se trece de la configuraia:
(Zn, n)
(Z1, 1)
NULL
...
(, )
(, )
...
(Z1, 1)
(Zn, adr( ))
...
...
NULL
(, )
(,adr ( Z1)
(Zk-1, k-1)
(Zk, k)
(Zk+1, k+1)
...
...
(Zj-1, j-1)
...
(Zj, j)
(Zj+1, j+1)
...
(Zk, k)
(Zk+1, k+1)
...
...
(Zk-1, k-1)
(Zj, j)
...
...
(Zj-1, j-1)
(Zj+1, j+1)
k-1 = adr( Zj )
(10.41)
j-1 = adr( Zk )
(10.42)
(10.45)
cont ( Z k ) cont ( Z k 1 )
(10.46)
pentru orice k = 1, 2, , n 1.
Funcia de sortare apeleaz la rndul ei funcia de interschimb a dou
elemente adiacente, pn cnd n final se obine ordinea cresctoare sau
descresctoare a termenilor Zi din lista iniial.
Un exemplu simplu de sortare, fr a lua n considerare multitudinea
de tehnici este:
sortare (w)
{
k = 1;
while (k != 0)
{
k = 0;
while (ref (w). != NULL)
{
if (ref (w).Z > ref (w).ref().Z)
{
k = 1;
interschimb (w, w.);
}
}
}
}
(Zj , j, j )
...
...
...
...
j) cu proprietile:
adr ( Z j )
adr ( j )
adr ( j ) lg ( j )
cont ( Z j , j ) adr ( Z j 1 )
cont ( Z j , j )
adr ( Z j 1 )
cont (
cont (
j 1
j 1
(10.47)
if (Prim==NULL)
cout << "\n Lista este vida!";
else
while (ptr)
{
cout << ptr->info<<" ";
ptr=ptr->suc;
}
cout<<"\n";
}
else
}
}
delete(ptr);
cout<<"Suprimare cu succes!\n";
cout<<"Nodul nu exista!\n";
void main()
{
ListaDubluInlan Listamea;
int opt;
TINFO valoare,cheie;
do
{
cout<<"\n Optiuni de lucru cu lista:";
cout<<"\n 1 - Afisare lista";
cout<<"\n 2 - Inserare element la inceputul listei";
cout<<"\n 3 - Inserare element inaintea unui elem specificat";
cout<<"\n 4 - Inserare dupa un element specificat";
cout<<"\n 5 - Cautarea unui element specificat";
cout<<"\n 6 - Suprimarea unui element";
cout<<"\n 9 - Terminare lucru \n\n";
cout<<"Introduceti optiunea dorita:";
cin>>opt;
switch(opt)
{
case 1:
}
cout<<"Traversare lista:";
Listamea.traversare_inainte();
break;
}
case 2:
{
cout<<"Introduceti elementul de inserat:";
cin>>valoare;
Listamea.inserare_inceput(valoare);
break;
}
case 3:
{
cout<<"Introduceti elementul de inserat:";
cin>>valoare;
cout<<"Introduceti elem inaintea caruia inseram:";
cin>>cheie;
Listamea.inserare_inaintea_unui_elem(valoare,cheie);
break;
}
case 4:
{
cout<<"Introduceti elementul de inserat:";
cin>>valoare;
cout<<"Introduceti elementul dupa care inseram:";
cin>>cheie;
Listamea.inserare_dupa_elem(valoare,cheie);
break;
}
case 5:
{
cout<<"Introduceti elementul cautat:";
cin>>valoare;
if(Listamea.cautare(valoare))
cout<<"Elementul a fost gasit!\n";
else
cout<<"Elementul nu exista in lista!\n";
break;
}
case 6:
{
cout<<"Introd elem pe care doriti sa-l suprimati:";
cin>>valoare;
Listamea.suprimare(valoare);
break;
}
case 9:
break;
default:
cout<<"\n Nu exista optiunea! \n ";
}
}while (opt!=9);
push
pop
push
pop
adr (C4)
adr (C3)
(Z'4, '4)
(Z'3, '3)
adr (C2)
(Z'2, '2)
adr (C1)
(Z'1, '1)
NULL
baza activ
b
a
NULL
baza activ
(11.1)
public:
elementstiva *vs; //varful stivei
stiva()
{
vs=NULL;
}
void sterg()
{
elementstiva* aux=vs;
if(vs == NULL) cout<<"\n Stiva este vida!";
else
{
aux = vs->prec;
free(vs);
while(aux !=NULL)
{
vs=aux;
aux=aux->prec;
delete vs;
}
vs = NULL;
}
}//
void tipar()
{
elementstiva* aux;
if(vs == NULL) cout<<"\n Stiva este vida!";
else
{
aux = vs;
while(aux !=NULL)
{
cout<<aux->info;
aux=aux->prec;
}
}
}
void inserare(int el)
{
elementstiva *aux;
aux = new elementstiva();
aux->info = el;
aux->prec = vs;
vs = aux;
}//
int extrag()
{
elementstiva* aux;
int el;
if (vs == NULL) return -1;
else
{
aux = vs->prec;
el = vs->info;
delete vs;
vs = aux;
return el;
}
}
};
void main()
{
stiva st;
char opt;
int x,el;
do
{
cout<<"\n Optiuni de lucru cu stiva ";
cout<<"\n P - Tiparire stiva";
cout<<"\n A - Adaugare element n stiva";
cout<<"\n E - Extragere element din stiva";
cout<<"\n T - Terminare lucru";
cin>>opt;
switch(opt)
{
case 'a':
cout<<"element:";cin>>el;
st.inserare(el);
break;
case 'e':
{
x = st.extrag();
if (x==-1)
cout<<"\n Stiva este vida!";
else
cout<<"\n Element extras"<<x;
}
break;
case 's':
st.sterg();
break;
case 'p':
st.tipar();
break;
default:
cout<<"\n Nu exista optiunea!";
}
}while (opt!='t');
}
Expresia n forma
polonez invers
(scriere
postfixat)
4 + 5
+ 4 5
4 5 +
4 + 5 * 5
+ 4 * 5 5
4 5 5 * +
4 * 2 + 3
+ * 4 2 3
4 2 * 3 +
4 + 2 + 3
+ + 4 2 3
4 2 + 3 +
4 * (2 + 3)
* 4 + 2 3
4 2 3 + *
Expresia
matematic
(scriere infixat)
Ierarhie
( [ {
) ] }
+ -
* /
Algoritmul este:
se iniializeaz stiva i scrierea postfixat;
att timp ct nu s-a ajuns la sfritul expresiei matematice:
- se citete urmtorul element din expresie;
- dac este valoare se adaug n scrierea postfixat;
- dac este ( se introduce n stiv;
- dac este ) se transfer elemente din stiv n scrierea postfixat
pn la (;
- altfel:
Stiv a
8
4
2
8
4
3
2
8
4
6
8
4
2
4
2
2
4
1
4
#pragma warning(disable:4786)
#include <deque>
#include <iostream>
#include <string>
using namespace std;
#include
#include
#include
#include
"ierarhie.h"
"stiva.h"
"fisier.h"
"coada.h"
/////////////////////Variabile globale
fisier f;
stiva <char> OPER;
stiva <double> EVAL;
coada POSTFIX;
void eroare(const char * text,int nr){
cout<<"\n"<<text<<"\n";
exit(nr);
}
void scrierePOSTFIX(string &op)
{
char opc;
if(op=="")
return;
int ierOp=ierarhie(op);
//daca e valoare, se trece direct in scrierea postfixata
if(!ierOp)
POSTFIX.adauga(op);
else
{
opc=op[0];
switch(ierOp)
{
//daca e paranteza deschisa, se introduce pe stiva
case PD: //([{
OPER.push(opc);
break;
//daca e paranteza inchisa, se extrag toate elementele
//de pe stiva pana la intalnirea unei paranteze deschise
case PI: //)]}
while(ierarhie(OPER.top())!=PD)
POSTFIX.adauga(OPER.pop());
OPER.pop();
break;
//daca e alt operator, se extrag elemente de pe stiva atat
//timp cat stiva nu este goala si ierarhia operatorului
//din varful stivei este mai mare sau egala decat ierahia
//operatorului curent
//la sfarsit operatorul curent se depune pe stiva
default:
while((!OPER.eGoala())&&ierarhie(OPER.top())>=ierOp)
POSTFIX.adauga(OPER.pop());
OPER.push(opc);
break;
}
}
}
void evalPOSTFIX()
{
string op;
char opc;
double t1, t2, rez;
//atat timp cat nu s-a ajuns la sfarsitul expresiei postfixate
while(!POSTFIX.eGoala())
{
//daca elementul curent este numar acesta se depune pe stiva
while(POSTFIX.eNumar())
EVAL.push(POSTFIX.getNumar());
//se extrag 2 valori de pe stiva
t2=EVAL.pop();
t1=EVAL.pop();
op=POSTFIX.extrage();
opc=op[0];
//se efectueaza operatia dintre cele 2 valori
switch(opc)
{
case '+':
rez=t1+t2;
break;
case '-':
rez=t1-t2;
break;
case '*':
rez=t1*t2;
break;
case '/':
rez=t1/t2;
break;
default:
eroare("Operator necunoscut!", 1);
}
//rezultatul operatiei se depune pe stiva
EVAL.push(rez);
}
}
void main(int argc, char* argv[])
{
//se primeste ca parametru numele fisierului in care se
//gaseste expresia matematica ce se doreste a fi evaluata
string numefis;
if(argc!=2)
{
cout<<"Specificati
scrierea postfixata!";
exit(1);
}
numele
unui
fisier
pentru
care
doriti
numefis=argv[1];
f.open(numefis.c_str());
if(f.bad())
{
cout<<"Fisierul "<<numefis<<" nu exista.\n";
exit(2);
}
cout<<"Lucrez cu fisierul "<<numefis<<".\n";
break;
case '*':
case '/':
return
break;
case '(':
case '[':
case '{':
return
break;
case ')':
case ']':
case '}':
return
break;
default:
return
break;
INMIMP;
PD;
PI;
0;
}
};
int ierarhie(string & s)
{
char c;
c=s[0];
return ierarhie(c);
};
/////coada.h - Clasa coada
void eroare(const char * text,int nr);
class coada{
private:
//implementarea cozii cu o clasa template double ended que din
//C++ Standard Template Library
deque <string> s;
public:
//verifica daca coada e goala
bool eGoala()
{
return s.empty();
};
str=c;
s.push_back(str);
};
//intoarce si extrage primul element din coada
string extrage()
{
string t;
if(!s.empty())
{
t=s.front();
s.pop_front();
}
else eroare("Eroare de sintaxa.",2);
return t;
};
//verifica daca primul element din coada reprezinta un numar
bool eNumar()
{
char *stop;
string st=s.front();
strtod(st.c_str(), &stop);
return (*stop) == 0;
};
//extrage elementul din coada ca numar
double getNumar()
{
char *stop;
double v;
string st;
st=s.front();
s.pop_front();
v=strtod(st.c_str(), &stop);
return v;
};
//intoarce a i-lea element din coada (0 - primul element)
string operator [] (unsigned int i)
{
if((i>=0) && (i<s.size()))
return s[i];
eroare("Eroare de sintaxa.",4);
return "";
};
//intoarce numarul de elemente din coada
int size()
{
return s.size();
};
};
/////stiva.h - Clasa template stiva
void eroare(const char * text,int nr);
rez=fis.get();
if(!isSeparator(rez))
while(!isSeparator(fis.peek()) && !fis.eof())
rez+=fis.get();
eatWhite();
return rez;
}
//deschide fisierul
void fisier::open(const char * numefis)
{
fis.open(numefis);
eatWhite();
}
//verifica daca fisierul a fost deschis cu succes
bool fisier::bad()
{
return fis.bad();
}
//verifica daca s-a ajuns la sfarsitul fisierului
bool fisier::eof()
{
return fis.eof();
}
//inchide fisierul deschis
void fisier::close()
{
fis.close();
}
c(a b)/ 2
(12.1)
f ( a )*f ( c ) 0
(12.2)
Dac:
[a ,
a+b
a+b
[a ,
3a + b
4
,b]
3a + b
4
a+b
a+b
a + 3b
a + 3b
,b]
(a b c d ) ( x y )
cd
(12.3)
*
e
/
*
c
+
x
+
a
biblioteca
1xxxxx : 7xxxxx
matematica
1xxxxx : 23xxxx
algebra
1xxxxx /
197xxx
geometrie
198xxx /
23xxxx
calculatoare
24xxxx : 51xxxx
hardware
24xxxx /
419xxx
software
420xxx /
51xxxx
economie
52xxxx : 7xxxxx
teorie
52xxxx /
680xxx
software
681xxx /
7xxxxx
Zj-1
j-1
Zj
Zj + 1
j+1
j-1
adr (Z j - 1 )
adr (Z j 1 )
j-1
j,
j)
( Z j , j, j, j , j )
(12.4)
(12.5)
=
+
e
c
+
a
null
null
null
null
null
pp;
ref (pc) .
pd;
pp pc;
pc pd;
(12.6)
new (pd);
Dup efectuare secvenei se face trecerea la pasul urmtor. Folosind
simbolurile, orice structur arborescent se reprezint prin:
N mulimea nodurilor
A mulimea arcelor
De exemplu, arborescena dat pentru calculul expresiei 12.5 se
reprezint prin:
N={e,
i
, a, +, b, + , c }
(12.7)
A = { (a+) ,
(b+) ,
(c+) ,
(+, =) ,
(=, e) }
(12.8)
adr (ZD)
adr (ZE)
adr (ZF)
adr (ZG)
(12.9)
Baleierea mulimii:
(12.10)
ref
ref
ref
ref
ref
ref
ref
ref
ref
ref
(pp[1] ).
(pp[2] ).
(pp[3] ).
(pp[4] ).
(pp[2] ).
(pp[4] ).
(pp[3] ).
(pp[6] ).
(pp[7] ).
(pp[1] ).
pp[2]
pp[4]
pp[6]
ref (pp[5] ). ref (pp[6] ). ref (pp[7] ). NULL (12.11)
pp[1]
pp[2]
pp[1]
pp[3]
pp[3]
ref (pp[1] ). NULL
A
B
D
k
Figura 12.9 Structur arborescent cu noduri fictive
20
10
25
22
26
(12.12)
10
25
12
22
26
<iostream.h>
<conio.h>
<stdio.h>
<malloc.h>
<string.h>
struct nod
{
int info;
nod *stg,*drt;
};
class arbbin
{
nod *rad;
int stergere(nod *&);
void stergere_nod(nod*&,int);
public:
arbbin()
{rad=NULL;};
~arbbin()
{rad=NULL;};
void traversare_srd(nod*);
void srd();
void traversare_rsd(nod *);
void rsd();
void traversare_sdr(nod *);
void sdr();
int sumaFrunze(nod*);
int sFrunza();
int numara(nod *);
int numara_nod();
void print(nod *);
void tiparire();
void salvare();
nod *inserare_nod(nod *,int );
void operator + (int);
void operator - (int);
arbbin &operator >(FILE *);
arbbin &operator <(FILE *);
void inserare_cuv(nod *& ,char*);
void insert(char *);
nod *operator [] (int);
};
nod *arbbin::inserare_nod(nod *rad,int k)
{
if (rad)
{
if (k<rad->info) rad->stg=inserare_nod(rad->stg,k);
else
if (k>rad->info) rad->drt=inserare_nod(rad->drt,k);
else printf("\nNodul exista in arbore!");
return rad;
}
else
{
nod *p=new nod;
p->stg=NULL;
p->drt=NULL;
p->info=k;
return p;
}
}
void arbbin::operator +(int k)
{
rad=inserare_nod(rad,k);
}
void arbbin::traversare_srd(nod *rad)
{
if (rad)
{
traversare_srd(rad->stg);
printf(" %d",rad->info);
traversare_srd(rad->drt);
}
}
void arbbin::srd()
{
nod *p;
p=rad;
traversare_srd(p);
}
void arbbin::traversare_rsd(nod *rad)
{
if (rad)
{
printf(" %d",rad->info);
traversare_rsd(rad->stg);
traversare_rsd(rad->drt);
}
}
void arbbin::rsd()
{
nod *p;
p=rad;
traversare_rsd(p);
}
void arbbin::traversare_sdr(nod *rad)
{
if (rad)
{
traversare_sdr(rad->stg);
traversare_sdr(rad->drt);
printf(" %d",rad->info);
}
}
void arbbin::sdr()
{
nod *p;
p=rad;
traversare_sdr(p);
}
void arbbin::print(nod *rad)
{
if (rad)
{
printf("%d",rad->info);
if((rad->stg)||(rad->drt))
{
printf("(");
print(rad->stg);
printf(",");
print(rad->drt);
printf(")");
}
}
else
printf("-");
}
void arbbin::tiparire()
{
nod *p;
p=rad;
print(p);
}
int arbbin::sumaFrunze(nod *rad)
{
if (rad)
if(!rad->stg&&!rad->drt)
return rad->info;
else
return sumaFrunze(rad->stg)+sumaFrunze(rad->drt);
else
return 0;
}
int arbbin::sFrunza()
{
nod *p;
p=rad;
return sumaFrunze(p);
}
int arbbin::numara(nod *rad)
{
if (rad)
return 1+numara(rad->stg)+numara(rad->drt);
else return 0;
}
int arbbin::numara_nod()
{
nod *p;
int nr;
p=rad;
nr=numara(p);
return nr;
}
void arbbin::stergere_nod(nod *&rad,int inf)
{
nod *aux;
if (!rad) printf("\nNodul nu exista in arbore!");
else
if (inf<rad->info) stergere_nod(rad->stg,inf);
else
if (inf>rad->info) stergere_nod(rad->drt,inf);
else
{
aux=rad;
if (!aux->stg)
{
rad=aux->stg;
delete(aux);
}
else
if(!aux->drt)
{
rad=aux->drt;
delete(aux);
}
else
rad->info=stergere(rad->stg);
}
}
int arbbin::stergere(nod *&p)
{
if (p->stg)
return stergere(p->stg);
else
{
nod *q=p;
int inf=q->info;
p=p->stg;
delete(q);
return inf;
}
}
void arbbin::operator -(int inform)
{
nod *nou;
nou=rad;
stergere_nod(nou,inform);
}
nod *arbbin::operator [] (int inf)
{
nod *aux;
aux=rad;
while(aux&&aux->info!=inf)
{
if (inf<aux->info)
aux=aux->stg;
else
if (inf>aux->info)
aux=aux->drt;
};
if (aux&&aux->info==inf)
cout<<"\nNodul cautat exista in arbore!";
else
cout<<"\nNodul cautat nu exista in arbore!";
return aux;
}
void meniu()
{
cout<<"\n
cout<<"\n
cout<<"\n
cout<<"\n
cout<<"\n
cout<<"\n
cout<<"\n
cout<<"\n
}
void main()
{
arbbin arb;
int informatie;
char optiune;
arb+10;arb+7;arb+15;arb+9;arb+3;arb+8;arb+25;
meniu();
optiune='1';
while (optiune!='0')
{
cout<<"\nOptiunea dorita este:";
cin>>optiune;
if(((optiune>='0')&&(optiune<='9'))||(optiune=='n'))
{
switch(optiune)
{
case '1':
char op;
cout<<"\nNoul nod de introdus:";
cin>>informatie;
arb+informatie;
cout<<"\nMai doriti adaugarea unui alt nod(d/n)?";
cin>>op;
while (op=='d')
{
cout<<"\nNoul nod de introdus:";
cin>>informatie;
arb+informatie;
cout<<"\nSe va mai adauga alt nod(d/n)?";
cin>>op;
}
getch();
meniu();
break;
case '2':
cout<<"\nNodul care se va sterge:";
cin>>informatie;
arb-informatie;
getch();
meniu();
break;
case '3':
int elem;
cout<<"\nNodul care va fi cautat:";
cin>>elem;
arb[elem];
getch();
meniu();
break;
case '4':
printf("\nArborele traversat in SRD:");
arb.srd();
printf("\nArborele traversat in RSD:");
arb.rsd();
printf("\nArborele traversat in SDR:");
arb.sdr();
getch();
meniu();
break;
case '5':
printf("\nSuma inf frunze:%d", arb.sFrunza());
getch();
meniu();
break;
case '6':
cout<<"\nNumarul de noduri:"<<arb.numara_nod();
getch();
meniu();
break;
case '7':
printf("\nArborele tiparit in RSD:");
arb.tiparire();
getch();
meniu();
break;
case '0':
break;
}
}
else cout<<"\nOptiunea nu exista in meniu!";
}
}
13. ARBORI B
13.1 Arbori B. Definiie. Proprieti.
n cazul sistemelor de gestiune a bazelor de date relaionale (SGBDR)
este important ca pe lng stocarea datelor s se realizeze i regsirea
rapid a acestora. n acest scop sunt folosii indecii. Un index este o
colecie de perechi <valoare cheie, adresa articol>. Scopul primar al unui
index este acela de a facilita accesul la o colecie de articole. Un index se
spune ca este dens dac el conine cte o pereche <valoare cheie, adresa
articol> pentru fiecare articol din colecie. Un index care nu este dens
uneori este numit index rar.
Structura de date foarte des folosit pentru implementarea indecilor
este arborele de cutare. Articolele memorate pot fi orict de complexe, dar
ele conin un cmp numit cheie ce servete la identificarea acestora. S
notm cu C mulimea cheilor posibile ce vor trebui regsite cu ajutorul
arborelui de cutare. Dac arborele de cutare este astfel construit nct
folosete o relaie de ordine total pe C, atunci vom spune c arborele de
cutare este bazat pe ordinea cheilor. Arborii de cutare, bazai pe ordinea
cheilor, sunt de dou feluri: arbori binari de cutare (au o singur cheie
asociat fiecrui nod) sau arbori multici de cutare (au mai multe chei
asociate fiecrui nod).
Performanele unui index se mbuntesc n mod semnificativ prin
mrirea factorului de ramificare a arborelui de cutare folosit. Arborii
multici de cutare sunt o generalizare a arborilor binari de cutare. Astfel,
unui nod oarecare, n loc s i se ataeze o singur cheie care permite
ramificarea n doi subarbori, i se ataeaz un numr de m chei, ordonate
strict cresctor, care permit ramificarea n m + 1 subarbori. Numrul m
difer de la nod la nod, dar n general pentru fiecare nod trebuie s fie ntre
anumite limite (ceea ce va asigura folosirea eficient a mediului de stocare).
Cele m chei ataate unui nod formeaz o pagin. Determinarea poziiei cheii
cutate n cadrul unui nod se realizeaz secvenial n cazul paginilor cu
numr mic de chei sau prin cutare binar. Un exemplu de arbore multici
de cutare de ordin 3 este dat n figura 13.1.
15
18
20
26
30
40
42
36
50
100
43
58
70
60
62
65
120
110
130
140
136
69
150
145
P0
K0
P1
K1
P2
Pn
Kn - 1
Pn
(13.1)
iii. fiecare pagin conine cel puin chei (excepie face rdcina
2
care poate avea mai puine chei, dac este frunz);
iv. nodul este fie frunz, fie are n + 1 descendeni (unde n este
N 1
h log m
2
2
(13.2)
fisioneaz. Cele din dreapta vor forma cel de-al doilea nod.
2
Cheia median va urca n nodul printe, care la rndul lui poate s
41
57
59
22
41
54
57
22
59
41
57
54
c
22
41
57
59
59
54
22
33
41
57
59
75
124
Figura 13.7 Structura arborelui dup inserarea cheilor 33, 75, 124
Inserarea cheii 62 ns duce la divizarea nodului c, figura 13.8.
Cheia mediana 62
va promova
c
57
59
62
75
57
124
59
75
124
a
54
62
c
22
41
57
59
75
124
b
33
41
62
122
22
54
45
55
d
57
59
60
66
75
123
124
c
55
Cheia mediana 57
va promova
56
57
59
60
55
56
59
60
Oricum, nodul printe a este deja plin i nu poate primi noua cheie 57
i pointerul ctre nodul nou format f. Algoritmul de fisionare este aplicat din
nou, dar de data aceasta nodului a, figura 13.12.
a
35
Cheia mediana 57
va promova
54
57
62
35
122
54
62
122
a
35
b
22
f
33
41
54
62
c
45
55
g
56
59
122
d
60
66
e
75
123
124
m
1 chei. Probabilitatea ca o fisionare s fie necesar
2
puin 1 p 1
p2
m
1 p 1 1
2
divizari
chei
(13.3)
care este mai mic dect 1 divizare per 1 inserri de chei (deoarece
2
p 1
1
tinde ctre 0 pentru o valoare mare a lui p i
este aproximativ
p2
p2
acesta are cel puin chei, caz n care avem de-a face cu o
2
partajare. Dac nu se poate face o partajare cu nici unul din
35
54
d
22
62
f
33
22
55
56
122
59
60
66
75
123
124
e
40
41
45
50
b
35
d
22
e
33
34
41
c
54
62
f
50
55
g
56
59
122
h
60
66
i
75
123
124
a
57
valoarea de cheie 35
coboara; valoarea de
cheie 34 urca
35
54
22
33
34
62
41
50
55
56
59
122
h
60
66
75
123
124
a
57
34
22
33
54
62
35
41
122
55
56
59
60
66
75
123
124
fuzionare
34
d
22
e
33
35
c
54
62
f
41
55
122
g
56
59
h
60
66
i
75
123
124
a
fuzionare
57
c
54
d
33
62
f
34
35
41
55
122
g
56
59
h
60
66
i
75
123
124
123
124
54
33
34
35
41
55
57
56
62
122
59
60
66
75
KEY_NODE_TYPE key_node_type ;
key_node_type* key_node_ptr ;
btree_node<KEY_NODE_TYPE> btree_node_type ;
btree_node_type* btree_node_ptr ;
typedef struct {
key_node_type
key_value ;
btree_node_ptr node_ptr ;
} btree_node_tuple ;
public:
enum BTREE_NODE_STATUS {
EMPTY = 0,
UNDERFLOW,
MINIMAL,
OPERATIONAL,
FULL,
OVERFLOW
} ;
public:
btree_node( int ncapacity ) ;
virtual ~btree_node( void ) ;
BTREE_NODE_STATUS status( void ) const ;
int capacity( void ) const ;
int size( void ) const ;
key_node_type& key_value( int position ) ;
btree_node<KEY_NODE_TYPE>* child( int position ) ;
int push( const key_node_type& value, btree_node_ptr child ) ;
bool find( const key_node_type& value, int& position ) ;
int remove_at( const int position ) ;
bool is_leaf( void ) const ;
int split( btree_node_tuple* tuple ) ;
protected:
static int initialize( btree_node_ptr node ) ;
int shift2right( const int start ) ;
int shift2left( const int start ) ;
protected:
btree_node( const btree_node<KEY_NODE_TYPE>& ) ;
btree_node<KEY_NODE_TYPE>& operator =( const
btree_node<KEY_NODE_TYPE>& ) ;
protected:
less_than<key_node_type>
equal_to<key_node_type>
_less_than ;
_equal_to ;
protected:
key_node_ptr
node_keys ;
btree_node_ptr*
node_childs ;
int
node_capacity ;
int
node_size ;
} ;
/**
class btree_node
*/
Destructorul
memoria alocat:
btree_node<KEY_TYPE>::~btree_node()
elibereaz
{ return this->node_size ; }
return true ;
}
position > 0;
position-) ;
ret_value = _equal_to( value, this->node_keys[position] ) ;
if( !ret_value ) position++ ;
}
return ret_value ;
}
*/
tuple
KEY_TYPE
key_type ;
btree_node<KEY_TYPE>
btree_node_type ;
btree_node_type*
btree_node_ptr ;
btree_node_type::btree_node_tuple btree_node_tuple ;
btree<KEY_TYPE>
btree_type ;
btree_type*
btree_ptr ;
public:
btree( int order ) ;
virtual ~btree( void ) ;
int push( const key_type& value ) ;
int remove( const key_type& value ) ;
protected:
int push_down( btree_node_tuple* tuple, btree_node_ptr current ) ;
int remove_down( const key_type& value, btree_node_ptr current ) ;
int replace_with_predecessor( btree_node_ptr node, int position ) ;
void restore( btree_node_ptr current, const int position ) ;
void move_left( btree_node_ptr current, const int position ) ;
void move_right( btree_node_ptr current, const int position ) ;
void combine( btree_node_ptr current, const int position ) ;
private:
btree_node_ptr root ;
int
order ;
} ; /**
class btree
*/
Clasa btree este o clas template dup tipul valorii de cheie. La fel ca
la clasa btree_node au fost folosite o serie de typedef-uri n cadrul clasei
(codul este mai uor de scris / citit dac tipul btree_node<KEY_TYPE> se
redefinete ca fiind btree_node_type). Nodul rdcin al arborelui B este
dat de cmpul root. Ordinul arborelui B este dat de cmpul order.
Constructorul btree<KEY_TYPE>::btree() primete ca parametru
ordinul arborelui i seteaz rdcina arborelui la 0.
template <typename KEY_TYPE>
btree<KEY_TYPE>::btree( int order ) {
this->order = order ;
this->root = 0 ;
}
btree_node_tuple* tuple,
btree_node_ptr
current
) {
if( 0 == current ) return 0 ;
int key_position ;
bool duplicate_key = current->find( tuple->key_value, key_position)
;
if( duplicate_key ) {
/**
signal duplicate value
return -1 ;
}
*/
if( current->is_leaf() ) {
current->push( tuple->key_value, tuple->node_ptr );
} else {
if( push_down( tuple, current->child( key_position ) ) )
current->push( tuple->key_value, tuple->node_ptr);
}
if( btree_node_type::OVERFLOW == current->status() ) {
current->split( tuple ) ;
return 1 ;
}
return 0 ;
}
gsete n arbore. Altfel, funcie de tipul nodului unde cheia este gsit
avem urmtoarele cazuri:
dac valoarea de cheie se gsete ntr-un nod frunz, atunci
tergerea nseamn apelarea metodei remove() a nodului frunz
pentru eliminarea cheii aflat n poziia dat de variabila position ;
dac valoarea de cheie a fost gsit ntr-un nod care nu este nod
frunza, atunci valoarea de cheie care trebuie tears va fi
nlocuit, n implementarea de fa, cu valoarea de cheie care o
precede (se poate demonstra c valoarea de cheie care o precede
se gsete ntr-un nod frunz). Dup ce se face nlocuirea folosind
funcia replace_with_predecessor(), se va continua algoritmul de
tergere, dar de data aceasta se va solicita tergerea valorii de
cheie cu care s-a fcut nlocuirea.
Se observ c dac nodul curent este valid (nu este 0) i valoarea de
cheie care se caut nu se gsete n nodul curent, atunci variabila position
va fi poziionat de metoda find() a nodului ca fiind poziia subarborelui care
este posibil s conin valoarea de cheie.
n finalul funciei, dac nodul curent nu este frunz (este un nod
printe care are descendeni care au fost afectai), se testeaz starea
nodului rdcin pentru subarborele pe care s-a efectuat coborrea n
procesul de tergere. Dac starea acestui nod este UNDERFLOW (conine
prea puine valori de cheie), atunci va fi apelat funcia restore() care va
restaura proprietile de arbore B.
template <typename KEY_TYPE>
int btree<KEY_TYPE>::remove_down(
const key_type& value,
btree_node_ptr current
) {
if( 0 == current ) {
/**
signal value not found
return 0 ;
}
*/
int position ;
if( current->find( value, position ) ) {
if( current->is_leaf() ) current->remove_at( position ) ;
else {
replace_with_predecessor( current, position ) ;
remove_down(current->key_value(position ),
current->child( position)) ;
}
} else remove_down( value, current->child( position ) ) ;
if( !current->is_leaf() &&
btree_node_type::UNDERFLOW
>status() )
restore( current, position ) ;
current->child(position)-
return 0 ;
}
move_right()
move_left()
x
combine()
const int
position
) {
if( 0 == position ) {
if( current->child( 1 )->status() > btree_node_type::MINIMAL )
move_left( current, 1 ) ;
else
combine( current, 1 ) ;
} else if( position == current->size() ) {
if(current->child(current->size()-1)->status()>
btree_node_type::MINIMAL)
move_right( current, position ) ;
else
combine( current, position ) ;
}
else
if(
current->child(
position
1
)->status()
btree_node_type::MINIMAL )
move_right( current, position ) ;
else
if(
current->child(
position
+
1
)->status()
btree_node_type::MINIMAL )
move_left( current, position + 1 ) ;
else
combine( current, position );
}
>
>
10
27
18
else{
if (dreapta==stanga)
radacina = inserareArbore (radacina, chei[stanga]);
else{
radacina = inserareArbore (radacina, chei[mijloc]);
echlibrareArbore (chei,dim,stanga, mijloc -1, radacina);
echlibrareArbore (chei,dim, mijloc +1,dreapta, radacina);
}
}
}
}
23
10
27
18
23
18
27
(14.1)
(14.2)
n care funcia max() este utilizat pentru a determina maximul dintre dou
valori.
int max(int valoare_1, valoare_2)
{
return valoare_1 < valoare_2 ? valoare_2 : valoare_1;
}
10
GE = 0
GE = -1
GE = 0
23
3
GE = 0
GE = 0
2
18
GE = 0
27
10
GE = -1
GE = -2
GE = 0
23
3
GE = -1
GE = 0
2
18
GE = 0
27
GE =0
1
Figura 14.5 Arbore binar AVL dezechilibrat
n urma procesului de inserarea se recalculeaza gradul de echilibru al
nodurilor ce sunt afectate. Aecstea noduri se gasesc in multimea nodurilor
{10, 3, 2, 1}. Se observa ca arborele i pierde caracteristica de a fi AVL
deoarece nodul cu cheia 3 are un grad de echilibru egal cu -2, ceea ce
evideniaz un dezechilibru puternic la stnga.
Pentru a aplica procesul de echilibrare, bazat pe operaie de rotire, se
identifica un nod, numit pivot, n care se realizeaz rotirea subarborelui.
GE = -2
NOD PIVOT
GE = 0
GE = 0
GE = -1
NOD FIU PE
DIRECTIA
DEZECHILIBRULUI
X - Subarbore drept
pivot
Y - Subarbore stang
fiu dreapta pivot
NOD PIVOT
GE = 0
GE = H1 (H1 + 2) = -2
GE = 0
2
H1
GE = H1 (H1 + 1) = -1
H1+2
H1+1
H1
H1+1
H1+1
H1
X
H1
arborelui
10
analizat,
GE = 0
23
GE = 0
GE =0
structura
GE = 0
GE = 0
rezult
18
GE = 0
27
GE = 0
10
GE = 1
GE = -1
GE = 2
23
GE =0
GE = 1
27
GE = 0
30
?
NOD PIVOT
X - Subarbore stng
pivot
GE = 2
GE = 0
23
GE = 1
30
GE = 0
NOD FIU PE
DIRECTIA
DEZECHILIBRULUI
30
23
Y - Subarbore stang
fiu stnga pivot
pivot->Echilibru = 0;
FiuDreapta->Echilibru = 0;
pivot = FiuDreapta;
}
10
GE = 1
GE = -1
GE = 0
2
GE =0
27
GE = 0
GE = 0
23
30
10
GE = 2
GE = -1
2
27
GE =0
GE = -2
GE = 1
GE = 0
23
GE = 0
16
30
GE = 1
24
GE = 0
26
GE = 2
GE = -1
GE = 2
2
GE =0
23
GE = 0
GE = -1
16
27
GE = 1
24
30
GE = 0
GE = 0
26
a doua rotaie se
dezechilibrului.
10
GE = 2
GE = -1
27
GE = -1
GE = 0
16
27
GE =0
23
30
GE = 1
GE = -2
NOD PIVOT
GE = 1
NOD FIU
GE = 2
10
GE = -2
2
GE =0
NOD PIVOT
GE = -1
GE = 0
24
30
GE = -1
GE = 0
24
GE = 0
23
26
GE = 0
26
16
GE = 0
10
GE = 1
GE = -1
GE = 0
2
GE =0
24
GE = -1
GE = 0
23
GE = 0
27
GE = 0
16
26
GE = 0
30
C) ARBORE REECHILIBRAT
Situaie final
Pivot
FiuStanga
FiuStanga_FiuDreapta
Pivot
FiuStanga
FiuStanga_FiuDreapta
-2
-2
-2
+1
+1
+1
-1
0
+1
1
0
0
0
0
-1
0
0
0
Situaia descris n tabelul anterior este utilizat pentru a defini mai eficient
metoda care implementeaz acest tip de rotaie. Astfel este evitat efortul
suplimentar de a recalcula gradul de echilibru pentru cele trei noduri
afectate.
GE = 2
GE = -1
GE = 2
2
GE =0
24
GE = -1
GE = -1
23
27
GE = -1
26
GE = 0
30
GE = 0
25
GE = -1
GE = -1
GE =0
GE = -1
23
GE = 2
NOD PIVOT
24
GE = 2
10
GE = 2
NOD PIVOT
2
GE =0
GE = 2
27
GE = -1
26
NOD FIU
24
GE = -1
GE = 1
23
26
NOD FIU
GE = 0
GE = 0
GE = 1
25
30
27
GE = 0
B) ROTATIE SIMPLA LA STANGA
25
GE = 0
30
10
GE = 1
GE = -1
GE = 0
2
GE =0
26
GE = 0
GE = 1
24
27
GE = 0
GE = 0
23
25
GE = 0
30
C) ARBORE REECHILIBRAT
Nod fiu
analizat
Grad
echilibru
nod fiu
+2
+2
dreapta
dreapta
+1
-1
-2
-2
stnga
stnga
-1
+1
Rotire
Simpl la stnga
Dubl la stnga: rotire simpl la
dreapta n fiul din dreapta al pivotului;
rotire simpl la stnga n pivot.
Simpl la dreapta
Dubl la dreapta: rotire simpl la
stnga n fiul din stnga al pivotului;
rotire simpl la dreapta n pivot.
}
AVLNod::AVLNod(int echilibru, int info, AVLNod * stanga, AVLNod *
dreapta)
{
Echilibru = echilibru;
Info = info;
st = stanga;
dr = dreapta;
}
23
18
27
2
3
23
10
2
18
27
18
18
3
23
27
23
27
else
if(rad->Info>Valoare)
rad->st = Inserare(rad->st,Valoare,echilibru);
return rad;
}
Reechilibrare);
-1){
0){
= 1;
ReechilibrareSubarboreDrept(arbore,echilibruNou);
}
else
echilibruNou = 0;
}
else
echilibruNou = 0;
}}
struct NodeStack
{
AVLNod* Nod;
NodeStack *next;
};
class AVLNodeStack
{
private:
NodeStack * VarfStiva;
public:
AVLNodeStack()
{
VarfStiva=NULL;
}
void PUSH(AVLNod* &NodNou){
NodeStack *elementNou= new NodeStack;
elementNou->Nod = NodNou;
if(this->VarfStiva==NULL){
this->VarfStiva = elementNou;
elementNou->next=NULL;
}
else
{
elementNou->next = this->VarfStiva;
this->VarfStiva = elementNou;
}
}
AVLNod* POP(){
if(this->VarfStiva==NULL)
return NULL;
else
{
NodeStack *elementSters = this->VarfStiva;
AVLNod* NodAuxiliar = this->VarfStiva->Nod;
this->VarfStiva = this->VarfStiva->next;
delete elementSters;
return NodAuxiliar;
}
}
void AfiseazaStiva()
{
NodeStack *temp = this->VarfStiva;
while(temp!=NULL)
{
printf("\n Nod in stiva este %d",temp->Nod->Info);
temp=temp->next;
}
}
};
47
GE = -1
stiva
35
22
47
GE = -1
GE = 1
16
31
GE = -1
37
GE = -1
GE = 1
50
GE =0
27
32
GE =0
42
GE =0
GE = -1
GE =0
29
GE =0
35
35
GE = -1
stiva
35
GE = -2
22
47
GE = -2
GE = 1
22
37
GE =0
GE = 1
16
31
GE = -1
37
GE = -1
GE = 1
16
31
GE = -1
27
32
GE =0
GE =0
GE = -1
42
GE = -1
42
9
GE =0
27
47
GE = 0
32
GE =0
GE =0
29
GE = -1
GE =0
GE =0
29
GE =0
GE =0
31
GE = -2
22
GE =0
(2)
22
37
35 GE = -1
GE =0
GE =0
GE = 1
16
16
GE = -1
31
(1)
GE = -1
27
32
42
GE = 0
47
27
GE = -1
32
37 GE =0
GE = 1
GE =0
29
42
47
GE =0
GE =0
GE = -1
GE =0
29
GE =0
GE =0
GE = 0
GE =0
17
20
GE = 2
GE = 1
16
GE = -1
20
20
GE = 0
17
GE = 0
23
GE = -1
GE = 0
GE =0
19
23
19
23
19
GE =0
GE =0
GE =0
GE =0
GE =0
else
if(temp->Echilibru==-2){
AVLNod *parinte = stiva.POP();
if(parinte!=NULL){
if(parinte->dr==temp)
this->ReechilibrareSubarboreStang(parinte->dr,valTemp);
else
this->ReechilibrareSubarboreStang(parinte->st,valTemp);
parinte->Echilibru=this->CalculeazaEchilibru(parinte);
}
}
temp=stiva.POP();
}
}
} }
negru
rou
rou
23
3
negru
negru
2
18
negru
27
15
nod bunic
nod printe
nod unchi
23
3
nod analizat
2
18
27
43
nod rou
nod negru
43
25
78
43
25
43
dezechilibru
78
25
14
14
dezechilibru
nod bunic
43
nod printe
nod unchi
25
78
nod nou
14
78
nod printe
14
nod NULL
17
dezechilibru
nod nou
43
43
nod bunic
nod bunic
78
25
78
25
nod printe
14
nod NULL
17
nod NULL
17
nod nou
14
dezechilibru
43
nod bunic
25
17
78
nod NULL
78
17
14
25
nod bunic vechi
nod NULL
14
dezechilibru
43
43
nod bunic
89
17
78
17
nod parinte
14
89
25
nod nou
dezechilibru
14
78
25
95
95
78
43
14
25
78
89
17
89
17
95
14
Pstrare
culoare
25
95
fiu. Arborele este n continuare Rou i Negru deoarece tergerea unui nod
rou nu are implicaii asupra numrului de noduri negre de pe fiecare drum.
43
43
nod de ters
89
17
14
89
78
14
78
15
15
Figura 14.33 Cazul 1 de tergere nod din arbore Rou & Negru
Dac nodul ters este de culoare neagr, iar fiul su este de culoare
roie, figura 14.34, atunci arborele devine dezechilibrat pe drumul care
trece prin aceast zon deoarece numrul de noduri negre este mai mic cu
unul. Reechilibrarea structurii arborescente se face n aceast situaie prin
recolorarea n negru a nodului fiu. Astfel este refcut numrul de noduri
negre.
43
43
nod de ters
79
17
79
14
recolorat in
negru
54
14
15
48
83
59
80
54
15
48
83
59
80
Figura 14.34 Cazul 2 de tergere nod din arbore Rou & Negru
Situaiile complexe aprute la tergerea unui nod dintr-un arbore de
tip Rou i Negru sunt apar n cazul n care nodul de ters i fiul su sunt de
culoare neagr. Prin eliminarea nodului, arborele devine dezechilibrat
deoarece o parte din drumuri conin cu un nod negru mai puin. Spre
deosebire de cazurile prezentate anterior, nu mai este posibil refacerea
numrului de noduri negre prin recolorarea fiului deoarece acesta are deja
culoarea neagr. Reechilibrarea arborelui este realizat printr-un numr fix
de operaii de rotire sau recolorare.
Pentru a descrie aceste cazuri particulare de dezechilibru i soluiile
asociate, se fac o serie de notaii care s ajute nelegerea operaiilor, figura
14.35. Se noteaz cu:
- P, nodul printe al nodului de ters;
- F, nodul fiu al nodului de ters;
- B, nodul bunic al nodului de ters; acest nod este nodul printe al
nodului P;
- U, nodul unchi al nodului de ters; acest nod este reprezentat de
al doilea fiu al nodului B;
nod bunic
32
nod printe
P
nod unchi
U
79
25
nod nepot
nod de ters
N1
14
nod fiu
17
45
N2
54
58
89
81
B
P
32
nod de ters
10
N1
14
17
79
25
45
dezechilibru
N2
54
58
89
81
10
32
U
79
14
17
N1
45
N2
54
58
89
81
Figura 14.36 Cazul 3 de tergere nod din arbore Rou & Negru
Prin tergerea nodului cu valoarea 25, arborele sau subarborele
analizat ce are rdcin pe nodul cu valoarea 32 este dezechilibrat la
dreapta deoarece drumurile care pornesc din rdcin i continu pe partea
stng au cu un nod negru mai puin. Reechilibrarea arborelui se realizeaz
prin modificarea culorii nodului unchi, valoarea 79, n rou, figura 14.37.
Astfel, este redus cu unu numrul de noduri negre din drumurile ce pornesc
din rdcina 32.
B
P
dezechilibru
79
14
10
N1
17
32
N2
54
45
58
89
32
U
79
14
10
N1
17
81
N2
54
45
58
89
81
Figura 14.37 Soluie de reechilibrare caz 3 pentru arbore Rou & Negru
n cazul n care, nodul cu valoarea 32 reprezint rdcina unui
subarbore, analiza se continu n sus pn cnd se atinge rdcina arborelui
sau pn cnd arborele este reechilibrat pe baza unei soluii din cele
descrise.
Al patrulea caz de tergere a unui nod dintr-un arbore Rou i Negru
ia n considerare situaia descris n figura 14.38:
- nodul de ters este negru;
- unicul fiu al nodului de ters este negru;
- nodul unchi al nodului de ters este negru;
- nodul printe este rou;
- nodurile nepoi sunt negre.
B
B
P
22
nod de ters
N1
69
15
45
dezechilibru
N2
54
58
89
81
22
U
69
N1
45
N2
54
58
89
81
Figura 14.38 Cazul 4 de tergere nod din arbore Rou & Negru
Asemenea cazului anterior, arborele i pierde calitatea de a fi Rou i
Negru n urma tergerii deoarece nu toate drumurile de la rdcin la
nodurile frunz au acelai numr de noduri negre. Reechilibrarea este
realizat prin interschimbarea culorilor nodului printe i nodului unchi,
figura 14.39.
B
P
dezechilibru
F
B
P
22
U
N1
N2
54
45
58
69
89
22
69
N1
81
N2
54
45
58
89
81
Figura 14.39 Soluie de reechilibrare caz 4 pentru arbore Rou & Negru
n situaia n care arborele din figura 14.34 reprezint un subarbore
atunci soluia de reechilibrare prezentat are doar efecte locale, deoarece
lungimea msurat n numr de noduri negre a tuturor drumurilor din acest
subarbore este mai mic cu unu fa de situaia iniial. Din acest motiv,
reechilibrarea se continu recursiv ctre rdcina arborelui.
Cazul al cincilea de tergere a unui nod ia n considerare ipotezele
descrise n figura 14.40:
- nodul de ters este negru;
- unicul fiu al nodului de ters este negru;
- nodul unchi al nodului de ters este rou;
- nodul printe este negru;
- nodurile nepoi sunt negre.
B
B
P
32
nod de ters
10
N1
14
17
79
25
45
dezechilibru
N2
54
58
89
81
10
32
U
79
14
17
N1
45
N2
54
58
89
81
Figura 14.40 Cazul 5 de tergere nod din arbore Rou & Negru
Reechilibrarea arborelui pentru cazul 5 de dezechilibru se realizeaz
prin interschimbarea culorilor nodului unchi i nodului printe, urmat de o
rotaie la stnga n nodul printe, figura 14.41.
B
P
32
14
10
N1
17
dezechilibru
79
(2)
N2
54
45
(1)
58
89
81
N2
32
N1
14
10
79
17
81
54
45
89
58
Figura 14.41 Soluie de reechilibrare caz 5 pentru arbore Rou & Negru
Analiznd figura 14.41 se observ c soluia cazului 5 nu conduce la
reechilibrarea total a arborelui. Zona de dezechilibru este modificat astfel
nct s poat fi reechilibrat ntr-un numr finit de pai. Aceast este
analizat prin prisma cazului patru care a fost descris sau prin intermediul
cazurilor ase i apte. De exemplu, arborele obinut n figura 14.41 este
reechilibrat, n figura 14.42 prin intermediul soluie oferite n cazul patru,
interschimbnd culorile nodului cu valoare 32 i nodului cu valoarea 54.
B
U
dezechilibru
10
17
N2
N1
45
Interschimbare culori
79
32
14
89
F
81
54
58
10
79
N2
32
N1
14
17
45
89
81
54
58
Figura 14.42 Reechilibrare arbore Rou & Negru din figura 14.41
Urmtoarele dou cazuri analizeaz culoarea nodurilor nepoi lund n
calcul situaii derivate din cazul patru.
Cazul ase, descris n figura 14.43, este definit de urmtoarele
ipoteze:
- nodul de ters este negru;
- unicul fiu al nodului de ters este negru;
- nodul unchi al nodului de ters este negru;
- nodul printe este rou sau negru;
- nodul nepot N1 este rou;
- nodul nepot N2 este negru.
B
P
22
nod de ters
N1
N2
54
45
58
89
22
U
69
15
dezechilibru
69
N1
45
81
N2
54
58
89
81
Figura 14.43 Cazul 6 de tergere nod din arbore Rou & Negru
Reechilibrarea arborelui din figura 14.43 este realizat prin:
- interschimbarea culorilor nodului printe i a nodului unchi;
- rotirea subarborelui cu rdcin n nodul unchi la dreapta.
B
P
dezechilibru
F
22
B
interschimb culori (1) + rotire (2)
U
69
(1)
dezechilibru
22
N1
54
N2
N1
45
54
89
(2)
58
81
69
45
58
N2
89
81
Figura 14.44 Soluie de reechilibrare caz 6 pentru arbore Rou & Negru
Rezultatul obinut n urma operaiei de schimbare a culorii i de rotire
nu conduce la reechilibrarea arborelui. Cu toate acestea, noua form a
subarborelui permite reechilibrarea la pasul urmtor, deoarece situaia
curent descrie cazul apte .
Cazul ase, descris n figura 14.45, este definit de urmtoarele
ipoteze:
- nodul de ters este negru;
- unicul fiu al nodului de ters este negru;
- nodul unchi al nodului de ters este negru;
- nodul printe este rou sau negru;
- nodul nepot N1 este rou sau negru;
- nodul nepot N2 este rou.
B
P
22
nod de ters
N1
N2
54
45
58
89
22
U
69
15
dezechilibru
69
N1
45
81
N2
54
58
89
81
Figura 14.45 Cazul 7 de tergere nod din arbore Rou & Negru
Reechilibrarea situaie descrise n figura 14.46 se realizeaz prin:
- interschimbare culoare nod printe cu nodul unchi;
- rotire la stnga a arborelui n nodul printe;
- modificare culoare nepot N2 n negru.
B
P
dezechilibru
F
22
(1)
N1
45
22
(3)
N2
54
58
69
(2)
69
89
81
N2
N1
45
54
89
81
58
Figura 14.46 Soluie de reechilibrare caz 7 pentru arbore Rou & Negru
Figura 14.46 prezint rezultatul obinut n urma reechilibrrii. Se
observ eliminarea dezechilibrului din acest arbore sau subarbore.
Pentru exemplele analizate n acest capitol s-a considerat c nodul de
ters se gsete n partea stng a nodului printe. Pentru situaia opus,
soluiile descrise au aceleai efect dac sufer mici modificri prin prisma
noului reper de vizualizare a arborelui.
De asemenea, n exemplele prezentate reechilibrarea arborelui are un
caracter local pentru a descrie tehnicile de reechilibrare, ns realizare unei
aplicaii trebuie s implementeze secvene care s parcurg arborele de jos
n sus, de la poziia nodului de ters ctre rdcina arborelui i care s
reechilibreze toat structura.
15. HEAP
24
12
23
17
32
32
12
24
17
23
12
a) Situaia iniial
24
17
24
12
23
17
24
12
23
17
i 1
Parinte(i )
, Stnga (i ) 2 i 1, Dreapta(i ) 2 i 2
2
(15.1)
--- //
};
this->memorieAlocata = this->memorieAlocata * 2;
this->memorieAlocata = this->memorieAlocata / 2;
return this->elemente[this->dimensiuneHeap];
// i ntoarcem maximul
return this->elemente[0];
Metodele
de
inserare
i
extragere
utilizeaz
funciile
CresteMemoriaAlocata i ScadeMemoria pentru extinderea / restrngerea
memoriei utilizate de ctre heap.
tip servire dac mai exist clieni n coad. Pe msur ce sunt procesate
evenimentele sunt reinute i informaiile necesare pentru calcularea
indicatorilor de performan afereni sistemului simulat.
Codul surs pentru implementarea simulatorului pe baza clasei Heap
prezentat n seciunea 15.2 este urmtorul:
#include <cmath>
#include <ctime>
#include <iostream>
#include "Heap.h"
// --- Definirea clasei Eveniment --- //
enum TipEveniment { Sosire, Servire };
class Eveniment
{
public:
// Constructor
Eveniment(int timp = 0, TipEveniment tip = Sosire) :
timp(timp), tip(tip) {}
// Implementarea relatiei de ordine pentru min-heap
bool operator > (Eveniment& eveniment)
{
return this->timp < eveniment.timp;
}
// Acces la elemente
int GetTimp() { return this->timp; }
TipEveniment GetTip() { return this->tip; }
private:
int timp;
TipEveniment tip;
};
// --- Generarea timpilor de sosire / servire --- //
int GenerareTimpSosire(int timpCurent,
int minIntervalSosire, int maxIntervalSosire)
{
return timpCurent + minIntervalSosire + rand() %
maxIntervalSosire;
}
int GenerareTimpServire(int timpCurent,
int medieServire, int dispersieServire)
{
// generare variabila aleatoare distribuita
// normal folosind metoda Box - Muller
double a = (double)rand() / RAND_MAX;
double b = (double)rand() / RAND_MAX;
double PI = 3.14159265358979323846;
double c = sqrt(-2 * log(a)) * cos(2 * PI * b);
// Parametri de iesire:
double& timpMediuAsteptare,
double& timpMediuServire,
double& lungimeMedieCoada,
int& numarClientiServiti)
// iniializare indicatori
int timp = 0;
int numarMasuratoriCoada = 0;
timpMediuAsteptare = 0;
timpMediuServire = 0;
lungimeMedieCoada = 0;
numarClientiServiti = 0;
// lista de clienti care asteapta sa fie serviti (inclusiv
// clientul care este servit la momentul curent)
Heap<Eveniment> clientiInAsteptare;
// lista de evenimente programate in viitor
Heap<Eveniment> coadaEvenimente;
// simularea incepe cu o sosire
coadaEvenimente.Insereaza(Eveniment(0, Sosire));
while(timp < durata)
{
// extragem ev urmtor din coad (n funcie de timp)
Eveniment e = coadaEvenimente.ExtrageMaxim();
timp = e.GetTimp();
lungimeMedieCoada += clientiInAsteptare.GetNumarElemente();
numarMasuratoriCoada++;
if (e.GetTip() == Sosire)
{
// A. Eveniment de tip sosire
// adugm clientul n coada de ateptare
clientiInAsteptare.Insereaza(e);
// programm sosirea urmtoare
Eveniment sosire = Eveniment(GenerareTimpSosire(
timp, minIntervalSosire, maxIntervalSosire), Sosire);
coadaEvenimente.Insereaza(sosire);
// dac este unicul client din coad
if (clientiInAsteptare.GetNumarElemente() == 1)
{
}
else
{
// calcul indicatori
lungimeMedieCoada = lungimeMedieCoada / numarMasuratoriCoada;
timpMediuAsteptare = timpMediuAsteptare / numarClientiServiti;
timpMediuServire = timpMediuServire /
(numarClientiServiti + clientiInAsteptare.GetNumarElemente());
}
void main()
{
// --- Citirea datelor de intrare --- //
// Parametri de intrare:
int durata, medieServire, dispersieServire;
int minIntervalSosire, maxIntervalSosire;
// Parametri de iesire:
double timpMediuAsteptare;
double timpMediuServire;
double lungimeMedieCoada;
int numarClientiServiti;
// Citire parametri:
cout << "Durata simularii:";
cin >> durata;
this->dimensiuneHeap--;
this->Filtrare(0);
16. GRAFURI
16.1 Structura de date de tip graf
Proiectarea unui sistem informatic care s gestioneze reeaua
naional de ci ferate presupune crearea unui mediu de lucru capabil s
utilizeze baza de date a staiilor i pe cea a liniilor de cale ferate pentru a
oferi soluii optime i reale care s minimizeze costurile i timpul de folosire
a reelei. Lund de exemplu situaia real din figura 16.1, se pune problema
parcurgerii traseului Arad Bucureti cu cost redus, acest lucru implicnd
parcurgerea distanei cea mai scurt.
Arad
274
59
Cluj
Timioara
331
324
497
225
Craiova
209
Constana
Bucureti
sens ntre dou noduri Ni, Nj i arcul este direcionat (Ni Nj sau
Ni Nj sau Ni Nj) atunci graful este unul orientat;
B
Graf neorientat
Graf orientat
2
C
Nod liber
D
M[i][j] =
A
5
A
C
0 7 5 0
1 1 0
0 0 8 1
0 0 0 3
0
0
0
0 1 1
0 0 1
0 0 0
0 0 0 0
0
0
2
M
0
0
0
0
0
1
0
0
0
2
1
0
0
0
3
M
0
0
0
0
0
0
0
0
0
1
0
0
0
4
M
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
(16.1)
vect_r();
//afieaz vectorul rezultat
matr_r();
//afieaz matricea rezultat
matr_r1();
drum_minim();/* se calculeaz drumul minim intre oricare 2
este_drum(); //verif. existenta drumului intre 2 noduri
drum_minim(int, int);
//drumul minim ntre 2 noduri date
toate_drm(int,int);
//toate drumurile dintre 2 noduri
este_arbore();
//verific daca este sau nu arbore
componente_conexe();
//determin componentele conexe
graf_matrice::este_eulerian();
parcurgere_bf(int);
//parcurgerea grafului n lime
parcurgere_df(int);
//parcurgerea grafului n adncime
};
void hamiltonian();
void prim();
graf_matrice::graf_matrice()
{
nr_noduri = 0;
nr_arce = 0;
nr_rez = 0;
for(int i = 0; i < MaxN;
{
for(int j = 0; j <
{
matm[i][j] =
matc[i][j] =
}
}
}
i++)
MaxN; j++)
0;
Infinit;
MatriceAdiacenta)
<< "Se va introduce matricea de adiacenta" << endl;
<< "Se introduc valorile (1-e drum; 0- nu e drum\n";
}
else
{
matc[i][j]=Infinit;
matc[j][i]=Infinit;
do
{
}
} // for j
} // for i
if (matc[i][j] != 0)
{
nr_arce++;
matm[j][i] = matm[i][j] = 1;
}
else
{
matc[i][j] = matc[j][i] = Infinit;
matm[i][j] = matm[j][i] = 0;
}
void graf_matrice::vect_r()
{
cout << "Vectorul rezultat este:" << endl;
for (int i = 0; i < nr_rez; i++)
{
cout << vect_rez[i] << " " << endl;
}
}
void graf_matrice::matr_r()
{
for (int i = 0; i < nr_noduri; i++)
{
for (int j = 0; j < i; j++)
{
cout << "Intre " << i + 1 << " si " << j + 1 <<
(matr[i][j] != 0 ? "" : " nu") << "exista drum.\n";
}
}
}
void graf_matrice::matr_r1()
{
for (int i = 0; i < nr_noduri; i++)
{
for (int j = 0; j < i; j++)
{
if (matr[i][j] != Infinit)
{
cout << "Intre " << i + 1 << " si " << j + 1 <<
"exista drum de cost minim " << matr[i][j] <<
endl;
}
else
{
Cout << "Intre " << i + 1 << " si " << j + 1 <<
"nu exista drum." << endl;
void graf_matrice::drum_minim()
{
for (int i = 0; i < nr_noduri; i++)
{
for (int j = 0; j < nr_noduri; j++)
{
matr[i][j] = matc[i][j];
}
}
void graf_matrice::este_drum()
{
for (int i = 0; i < nr_noduri; i++)
{
for (int j = 0; j < nr_noduri; j++)
{
matr[i][j] = matm[i][j];
}
}
int graf_matrice::valid(int k)
{
if (matc[vect_rez[k-1]][vect_rez[k]] == Infinit)
{
return 0;
}
return 1;
int graf_matrice::suma(int k)
{
int suma = 0;
for (int i=0; i<k; i++)
{
suma += matc[vect_rez[i]][vect_rez[i+1]];
}
}
return suma;
}
else
{
min = lgdrum;
nr_rez = h + 1;
h++;
vect_rez[h] = -1;
}
} // if (valid(h))
}
}
h--;
bool graf_matrice::este_arbore()
{
int b[MaxN], i, j, v, s;
v = 0;
for (i = 0; i < nr_noduri; i++)
{
for(j = i + 1; j < nr_noduri; j++)
{
v += (matm[i][j] == 1);
}
}
for (int i = 0; i < nr_noduri; b[i] = 0, i++);
b[0]=1;
for(i=0;i<nr_noduri;i++)
{
for(j=0;j<nr_noduri;j++)
{
if((matm[i][j] == 1) && (b[i] == 1))
{
b[j] = 1;
}
}
}
s=0;
for (i = 0; i < nr_noduri; i++)
{
s += (b[i] == 0);
}
}
bool graf_matrice::este_eulerian()
{
int b[MaxN],i,j,k,v,s;
for (int i = 0; i < nr_noduri; b[i] = 0, i++);
b[0] = 1;
for(i=0;i<nr_noduri;i++)
{
for(j=0;j<nr_noduri;j++)
{
if((matm[i][j] == 1) && (b[i] == 1))
{
b[j] = 1;
s=0;
for (i = 0; i < nr_noduri; i++)
{
s += (b[i] == 0);
}
for(i = 0; i < nr_noduri; i++)
{
k = 0;
for(j = 0; j < nr_noduri; j++)
{
k += (matm[i][j]==1);
v = k / 2;
}
}
if ((k - 2 * v) > 0)
s = 1;
return s <= 0;
void graf_matrice::parcurgere_bf(int i)
{
int j,u,p,v,c[MaxN],vizitat[MaxN];
for (int i = 0; i < nr_noduri; vizitat[i] = 0, i++);
c[1] = i; u = 1; vizitat[i] = 1;
for(p = 1; p <= u; p++)
{
v = c[p];
for(j = 0; j < nr_noduri; j++)
{
if ((matm[v][j] == 1) && (vizitat[j] == 0))
{
u++;
c[u] = j;
vizitat[j] = 1;
}
}
}
cout << "lista vf. parcurse cu metoda BF pornind de la varful "
<< i + 1 << ": " << endl;
void graf_matrice::parcurgere_df(int i)
{
int vizitat[MaxN], urmator[MaxN], s[MaxN], k, v, j, ps;
for (int i=0; i < nr_noduri; urmator[i] = 0, vizitat[i] = 0, i++);
s[1] = i; ps = 1; vizitat[i] = 1;
cout << "ordinea in DF este " << i+1 << " ";
while(ps >= 1)
{
j = s[ps];
k = urmator[j] + 1;
while ((k <= nr_noduri) &&
((matm[j][k]==0) || (matm[j][k]==1)&&(vizitat[k]==1)))
{
k++;
}
urmator[j] = k;
if(k == nr_noduri + 1)
{
ps--;
}
else
{
cout << k + 1 << " ";
vizitat[k] = 1;
ps++;
s[ps] = k;
}
void graf_matrice::prim()
{
int s[MaxN],t[MaxN],p[MaxN];
int min,k,l,c,i,j,v;
cout << "Nodul de pornire: ";
cin >> v;
for (int i = 0; i < nr_noduri; s[i] = t[i] = p[i] = 0, i++);
s[v - 1] = 1;
for(k = 1; k <= nr_noduri - 1; k++)
{
min = Infinit;
for(i = 0; i < nr_noduri; i++)
{
for(j = 0; j < nr_noduri; j++)
{
if ((s[i]==1)&&(s[j]==0) && (min > matc[i][j]))
{
min = matc[i][j];
l = i; c = j;
}
}
}
s[c] = 1;
t[c] = l + 1;
p[c] = matc[l][c];
void graf_matrice::hamiltonian()
{
int x[MaxN], v, k, j, sol, i;
sol = 0;
x[1] = 1; x[2] = 1; k = 2;
while(k > 1)
{
v = 0;
while((x[k] + 1 <= nr_noduri) && (v == 0))
{
x[k]++;
v = 1;
for(i = 1;i <= k - 1; i++)
{
if(x[k] == x[i])
{
v = 0;
break;
}
}
if(matm[x[k - 1] - 1][x[k] - 1] == 0)
{
v = 0;
}
if(v == 0)
{
k--;
}
else
{
if ((k==nr_noduri)&&(matm[x[nr_noduri]-1][x[1]-1]==1))
{
sol++;
if(sol==1)
{
cout << "Cicluri hamiltoniene:" << endl;
}
}
else
if (sol == 0)
cout << "Graful nu este hamiltonian.";
void graf_matrice::componente_conexe()
{
int b[MaxN],k,j,i;
for(i = 0; i < nr_noduri; i++)
{
for(j = 0; j < nr_noduri; j++)
{
matr[i][j] = matm[i][j];
}
}
cout << "Componentele conexe sunt: ";
for(k = 0; k < nr_noduri; k++)
{
for(j = 0; j < nr_noduri; j++)
{
b[j] = -2;
}
b[k] = k;
if(matr[k][k] > -1)
cout << endl << "
";
}
void graf_matrice::toate_drm(int a, int b)
{
int h;
for (int f = 0; f < MaxN; f++)
vect_rez[f] = -1;
vect_rez[0] = a;
h = 1;
while(h >= 1)
{
while(vect_rez[h] < nr_noduri)
{
vect_rez[h]++;
if(valid(h))
{
if(vect_rez[h] == b)
{
cout << endl;
for (int e = 0; e <= h; e++)
cout << vect_rez[e] + 1 << " ";
}
else
{
h++;
vect_rez[h] = -1;
}
}
}
h--;
}
#endif //GRAF_MATRICE_H
La crearea grafului se introduc iniial informaiile nodurilor, crenduse astfel lista lor. Dup aceasta se vor crea listele de arce introducndu-se
informaia nodului surs, a nodului destinaie i greutatea arcului.
Pentru graful
cu greutate din figura 16.6 reprezentarea sa n
memorie prin intermediul listelor de liste este dat n figura 16.8.
&B
&C
&D
NULL
NULL
&C
NULL
&D
NULL
NULL
//informatia nodului;
//referinta catre urmatorul nod;
//capatul listei de arce;
//elementul stivei
//referinta catre urmatorul element;
//elementul listei
//referinta catre urmatorul element;
if(!stk)
{
return NULL;
}
else
{
stiva *t = stk->next;
(*nd) = stk->n;
delete stk;
return t;
q->succ = t;
delete t;
return n;
};
temp->next = nou;
return nou;
return cap;
}
else
{
gasit = 1;
keep = temp;
temp = temp->next_arc;
if(!gasit)
{
temp= new arc();
temp->destinatie=d;
temp->greutate=greutate;
temp->next_arc=NULL;
if(keep == NULL)
{
s->capat=temp;
}
else
{
keep->next_arc=temp;
}
}
else
delete temp;
return 1; // nodul a fost ters
keep = temp;
temp = temp->next_arc;
while(g != NULL)
if(!vizitat[g->info])
{
cout << endl << "Componenta : " <<endl;
stk = push(stk,g);
do
{
stk = pop(stk,nd);
curent = *nd;
vizitare(curent,vizitat);
temp=curent->capat;
while(temp)
{
if(!vizitat[temp->destinatie->info])
stk=push(stk,temp->destinatie);
temp=temp->next_arc;
}
} while(stk != NULL);
}
g=g->next;
while(g != NULL)
{
if(!vizitat[g->info])
{
cout << endl << "Componenta : " << endl;
put(q,g);
do
{
curent = get(q);
if(!vizitat[curent->info])
{
vizitare(curent,vizitat);
temp = curent->capat;
while(temp)
{
if(!vizitat[temp->destinatie-
>info])
put(q,temp->destinatie);
}
temp=temp->next_arc;
}
} while(q->pred != NULL);
g = g->next;
}
}
distanta[tmp->info] = distanta_noua;
precede[tmp->info] = curent;
temp = temp->next_arc;
}
}
k = i;
min = distanta[k];
for(i = k; i < MaxN; i++)
{
if(perm[i] < 0 && distanta[i] < min)
{
min = distanta[i];
k = i;
}
}
curent = k;
perm[k] = 1;
return distanta[dest];
F
D
Noduri
adiacente
C
B
F
A C
D
B
Noduri
adiacente
A C D
Nu are noduri
adiacente
F
E
B
F
A C D F E
Noduri adiacente
A C D F E B
A
C
D
F
E
B
C B
Noduri
adiacente
A B C
Lista nodurilor vizitate
D C F
Noduri
adiacente
A B C F D
Lista nodurilor vizitate
F E
Noduri
adiacente
A B C F D E
Nivel 1
Nivel 2
Nivel 3
A
B
Nivel 4
adiacen, care s arate pentru fiecare nod n parte unde se poate ajunge
plecnd din el.
O modalitate de creare a acesteia este dat de traversarea n
adncime a grafului. Traversnd graful din fiecare nod al su, se obin
attea liste cte noduri sunt, liste care arat n ce noduri se ajunge din
nodul de start. Acestea din urm se transpun ntr-o matrice M[n][n], care
are elementul mij =1 dac exist drum de la nodul Ni la nodul Nj i 0 n rest.
B
F
D
1
0
0
MIT
0
0
1
1
0
0
0
0
1
1
1
1
1
0
1
1
1
1
1
0
1
1
1
1
1
0
1
1
1
.
1
1
(16.2)
B
F
A
E
C
(16.3)
(16.4)
unde:
reprezint valoarea etichetei asociat nodului Ni;
val_etichet(Ni)
greutate_arc(Nk,Ni)) reprezint valoarea arcului dintre nodurile Nk i
Ni ;
este un nod din lista L de la care se ajunge prin
Nk
arc direct la nodul Ni care nu se afl n list.
Se adaug la lista L acel nod Ni care are distana(Ni) obinut minim.
Pentru el ca i pentru celelalte noduri pentru care s-au calculat distanele se
reactualizeaz etichetele:
val_etichet(Ni) = min(val_etichet(Ni), distana(Ni))
(16.5)
Dac nu exist nici un nod de acest tip atunci nu exist nici un drum
pn la destinaie.
Pasul 4. Dac nodul destinaie se afl n lista L, atunci valoarea
etichetei sale reprezint drumul de lungime minim. Pentru gsirea acestui
drum, se pornete napoi de la nodul final i folosind nodurile din L.
Pentru a nu pierde timp la Pasul 4 reconstituind drumul, aa cum s-a
ataat fiecrui nod o etichet, i se asociaz o list n care sunt memorate
nodurile precedente care au dat valoarea etichetei n acel moment. Nodul
nou introdus n lista L, iniializeaz lista drumului deja parcurs cu valorile
din lista predecesorului su direct i apoi l adaug i pe acesta.
4
B
7
A
3
2
20
2
C
E(D)=infinit
4
B
7
E(A)=0
3
2
20
2
C
E(C)=2
L(C)={ A }
E(F)=13
L = { A, C, E, B }
E(E)=4
L(E)={ A, C }
E(D)=9
L(D)={ A, C, B }
4
B
7
E(A)=0
3
2
E
2
E(F)=10
L(F)={ A, C, B, D}
F
2
C
E(C)=2
L(C)={ A }
20
L = { A, C, E, B, D, F}
E(E)=4
L(E)={ A, C }
}
return k;
}
if(aux2->info==aux1->info)
if (verif_arc(p,aux1)!=verif_arc(q,aux2))
{
//dac au greutate diferit atunci
printf("\n Nu se poate face concatenarea !");
k=0;
return k;
}
}
1
9
8
0
5
3
2
Graf 1
Graf 2
1
7
4
10
3
2
6
4
6
2
3
11
3
4
4
Graful rmas
Noul graf
/*funcia verific dac nodul referit prin *s are arc ctre nodul
referit prin *d, i ntoarce ca rezultat greutatea arcului sau 0 dac
nu este arc*/
int graf_liste::verif_arc(nodgraf *s,nodgraf *d)
{
arc * p,*aux;
int gasit=0;
for(p=s->capat;p!=NULL;p=p->next_arc)
if(p->destinatie==d) {
gasit=1;
aux=p;
return aux->weight;
}
if (gasit==0) {
return 0;
}
else return aux->weight;
}
/* funcia primete ca date de intrare pointer la captul grafului i
informaia nodului pe care l caut i va returna adresa nodului
cutat sau NULL*/
nodgraf *cauta_nodgraf(nodgraf * cap,int info)
{
nodgraf *p,*q;
int gasit=0;
for(p=cap;p!=NULL;p=p->next)
if(p->info==info) {
gasit=1;
q=p;
}
if(gasit==0){
return NULL;
}
else return q;
}
nodgraf *p,*z;
int k=0;
int vb=0;
for(p=cap;p!=NULL;p=p->next)
{
if(cauta_nodgraf(cap2,p->info)==NULL)
{
z=cauta_nodgraf(cap,q->info);
if(z!=NULL) k=verif_arc(p,z);
if(k!=0) vb=k;
}
}
return vb;
}
(17.1)
MEM elemente
1450 * 48
*100 =
*100 = 2,6%
MEM
55630 * 48
(17.3)
(17.4)
(17.5)
unde:
s[i] codul ASCII al caracterului i din ir;
n dimensiunea irului de caractere.
Pentru cheia alfanumeric cu valoarea salut aplicarea funciei hash
conduce la obinerea valorii
hash(salut)=115*314+97*313+108*312+117*31+116=109202173 (17.6)
valoarea obinut este introdus din nou ntr-o funcie hash care s
identifice poziia corespondent din mulime pentru aceast valoare
numeric foarte mare.
Dezavantajul tabelelor de dispersie n cadrul proceselor de cutare
este descris de:
- efortul suplimentar de prelucrare dat de funcia hash care poate
avea n unele situaii un nivel de complexitate ridicat;
- apariia n cadrul tabelei a coliziunilor acestea sunt generate de
situaia n care dou valori Xh i YH ce aparin domeniului de
definiie a funcie hash conduc la obinerea de valori identice,
hash(Xh) = hash(Yh); evitarea coliziunilor implic realizarea de
operaii suplimentare prin care s se identifice poziia elementului
n cadrul mulimii; printre cele mai utilizate tehnici de evitare a
coliziunilor se numr chaining, re-hashing, linear probing,
quadratic probing i overflow area, [Will96], [Seng94].
Din aceste puncte de vedere, tabela de dispersie utilizat n procesul
de regsire a informaiei se descrie ca o structur n care datele sunt
stocate n tabele cu adresare direct, iar poziia acestora este determinat
prin prelucrarea cheii de cutare cu o funcie hash, figura 17.1.
Cheie de cutare
Funcie hash
Valoarealfanumeric
Valoarenumeric
Valoare[Elem1, Elemn]
EVITARE COLIZIUNI
Elem1
Elemn
(17.7)
unde:
pozitie_tabela valoarea hash obinut;
val_cheie
valoarea numeric ce identific unic fiecare
nregistrare;
val_baza
valoarea numeric stabilit la definirea modelului;
Valoarea utilizat ca baz n modelul funciei hash este dat de
dimensiunea tabelei de dispersie; obiectivul definirii funciei hash
este de a obine un model care s minimizeze mulimea de chei
diferite ce conduc la aceeai valoare pozitie_tabela; n acest sens
se utilizeaz numere prime apropiate de numrul total de
nregistrri; astfel, dac cheile nregistrrilor definesc o mulime
continu de valori unice, valorile hash determinate vor acoperi
toat mulimea [0..val_baza-1]; pentru a stabili dimensiunea
iniial a tabelei de dispersii sunt alese numere prime particulare;
de exemplu limbajul Java definete o clas HashTable ce descrie o
tabel de dispersie cu dimensiunea iniial egal cu 101; valoarea
nu este aleas la ntmplare deoarece permite redimensionarea
tabelei la o nou valoare prim; pentru cazuri generale, este
indicat s se foloseasc un numr prim determinat prin relaia:
(17.8)
(17.9)
(17.10)
(17.11)
unde:
valoarea hash calculat;
val_hashs1
string_cheie valoarea cheii de cutare;
Relaia anterioar definete un model cu un nivel de complexitate
sczut ce este destinat gestiunii unei colectiviti mici de
elemente; n cazul n care valoarea cheii reprezint numele unei
persoane, modelul este ineficient deoarece genereaz multe
coliziuni pentru nume diferite dar care ncep cu acelai caracter;
rafinarea acestui model se poate face prin preluarea mai multor
caractere din irul respectiv; de exemplu se definete o nou
relaie
val_hashs2=(string_cheie[0]+string_cheie[lungimestring_cheie] )%dim_has
unde:
val_hashs2
string_cheie
lungimestring_cheie
(17.12)
dim_hash
dimensiunea tabelei de dispersie;
ce ia n calcul primul i ultimul caracter; de asemenea, pentru a
nu reduce dimensiunea tabelei la maxim 255 elemente, se
utilizeaz un numr prim, dim_hash suficient de mare; alte funcii
hash de prelucrare a cheilor alfanumerice analizeaz toate
caracterele din ir; de exemplu relaia
lungime _ cheie
val_hashs3 =
% dim_hash
(17.13)
i 1
unde:
valoarea hash calculat;
val_hashs3
string_cheie
valoarea cheii de cutare;
lungime_cheie
dimensiunea irului de caractere;
dim_hash
dimensiunea tabelei de dispersie;
determin valoarea hash pe baza sumei codurilor ASCII asociate
tuturor caracterelor din cheie;
-
m 1
5 1
sau a expresiei
2
5 1
; funcia hash definit pe baza acestui model este
2
f(val_cheie) = [val_cheie * m]
(17.14)
Tabel de dispersie
valoare cheie
hash(x) = k
hash(y) = k
hash(z) = k
NULL
k+1
hash1(x) = k
hash1(y) = k
k+n
hash2(y) = k+n
hash3(y) = k+m
hash1(z) = k+n
k+m
Tabel de dispersie
hash(y) = k
verificare poziii
adiacente
hash(x) = k
k+1
hash(z) = k+1
k+2
(17.15)
unde:
poziie
hash(y) = k
hash(x) = k
hash(y)+2*12
k+2
hash(y)+2*2
hash(z) = k+2
k+8
hash(x) = k
zon principal
hash(y) = k
zon overflow
GU hash
NPO
*100
NTP
unde:
NPO numrul de poziii ocupate;
NTP numrul total de poziii.
(17.16)
care este meninut la o valoarea mai mic de 50%. n ciuda faptului c are
loc o gestiune ineficient a spaiului, eficiena abordrii se bazeaz pe o
vitez de regsire mare. Pentru a menine valoarea indicatorului GUhash sub
limit impus, tabela se redimensioneaz prin dublarea numrului de poziii.
n cazul n care modelul funciei hash este bazat pe mprirea n modul la
dimensiunea acesteia, redimensionarea trebuie s conduc la o nou
dimensiune care s reprezinte tot un numr prim. Avnd n vedere
importana acestor tipuri de numere, lucru evideniat la descrierea tipurilor
de funcii hash, redimensionarea se face prin intermediul relaiei
dimensiune_noua = dimensiune_curenta*2 + 1
(17.17)
(17.18)
17.4 Implementare
n continuare se exemplific printr-un program scris n limbajul de
programare C++ implementarea unei tabele de dispersie pentru nregistrri
de tip Student, cutrile realizndu-se dup numrul matricolei. Ca funcie
de dispersie a fost ales un exemplu simplu cu ajutorul operatorului modulo
(%). Dimensiunea implicit a tabelei a fost aleas 101, o valoare
cuprinztoare pentru exemplul ales.
Tabela de dispersie este implementat sub forma unui masiv
unidimensional alocat dinamic, ale crui elemente sunt liste care conin
datele propriu zise. Acest mod de implementare permite tratarea
coliziunilor, n cazul n care pentru indexul generat exist o nregistrarea n
tabel, noua nregistrare va fi adugat ca element la lista simplu nlnuit
de la nodul respectiv.
#include "stdafx.h"
#include <iostream>
using namespace std;
//structura de date stocata in tabela de dispersie
//pentru simplificarea codului s-a utilizat o structura
struct Student
{
int matricola;
char nume[20];
char adresa[30];
char localitate[20];
char e_mail[20];
char telefon[15];
void Afisare()
{
cout<<"Matricola:
cout<<"Matricola:
cout<<"Matricola:
cout<<"Matricola:
cout<<"Matricola:
cout<<"Matricola:
}
"<<
"<<
"<<
"<<
"<<
"<<
matricola <<endl;
nume <<endl;
adresa<<endl;
localitate<<endl;
e_mail <<endl;
telefon <<endl;
};
//elementele tabelei de dispersie
//pentru simplificarea codului s-a utilizat o structura
struct NodDate
{
NodDate *urm;
Student data;
};
//Cheia este matricola studentului
//
class HashStudent
{
int size;
NodDate ** elem;
//functie simpla de dispersie care utilizeaza operatorul modulo
//pentru a genera pozitia in tabela
int HashFunction(int cheie)
{
return cheie%size;
};
//aloca memorie pentru structura si initializeaza cu null
valorile
void AlocaMemorie()
{
elem = new NodDate*[size];
for (int i=0;i<size;i++)
elem[i] = NULL;
}
void ElibereazaMemorieLista(NodDate *&);
public:
HashStudent():size(101)
{
AlocaMemorie();
}
~HashStudent();
HashStudent(int iSize): size (iSize)
{
AlocaMemorie();
}
int Insereaza(Student data);
Student Cauta(int matricola);
int Sterge(int matricola);
void HashStudent::Afiseaza();
};
if (t==NULL)
return s_negasit;
else
return t->data;
}
}
}
//neinitializat sau nu exista inregistrarea
return s_negasit;
}
//functie recursiva care eliberaza memoria ocupata de nodurile listei
void HashStudent::ElibereazaMemorieLista(NodDate *&inceput)
{
if (inceput == NULL)
return;
else
{
ElibereazaMemorieLista(inceput->urm);
cout<<"Eliminat nodul cu codul: " <<inceput>data.matricola<<endl;
delete inceput;
}
}
//elibereaza memoria ocupa de tabela de dispesie
HashStudent::~HashStudent()
{
if (elem != NULL)
{
for (int i=0;i<size;i++)
ElibereazaMemorieLista(elem[i]);
delete [] elem;
}
}
//Sterge elementul a carui matricola coincide cu matricola trimisa ca
parametru
//returneaza pozitia din tabela de a fost eliminat elementul
//sau -1 in cazul in care nu exista elementul cu cheia data
int HashStudent::Sterge(int matricola)
{
if (matricola<0)
return matricola;
if (elem!=NULL)
{
int index = HashFunction(matricola);
if (elem[index]==NULL)
{
return -1;
}
else
{
//este primul
if (elem[index]->data.matricola ==matricola)
{
if(elem[index]->urm == NULL)
{
delete elem[index];
elem[index]=NULL;
}
else//mai sint si alte elemente in lista
{
NodDate *t = elem[index];
elem[index] = t->urm;
delete t;
}
}
else//coliziune, nu este primul, il cautam
{
NodDate *t = elem[index];
while (t->urm!= NULL && t->urm->data.matricola
!=matricola)
t = t->urm;
if (t->urm==NULL)
return -1;
else//t->urm.data.matricola == matricola
{
NodDate *p = t->urm;
if (p->urm ==NULL)
{
t->urm = NULL;
delete p;
}
else
{
t->urm = p->urm;
delete p;
}
}
}
return index;
}
return -1;
}
}
//Afiseaza continutul tabelei de dispersie
void HashStudent::Afiseaza()
{
if (elem!=NULL)
{
for (int i=0;i<size;i++)
{
if (elem[i]!= NULL)
{
NodDate *t = elem[i];
while (t!=NULL)
{
cout<<"S-a inserat in pozitia: " << i <<
" cheia: "<<t->data.matricola<<endl;
t = t->urm;
}
}
}
}
}
int _tmain(int argc, _TCHAR* argv[])
{
Student grupa[] ={
{1000,"Ion Vlad", "Str. Norilor
20","Cluj","ion@server.ro", "0101010101"},
{204,"Mihai Vlad", "Str. Norilor
20","Cluj","mihai@server.ro", "0101010101"},
{406,"Dan Vlad", "Str. Norilor 20","Cluj","dan@server.ro",
"0101010101"},
{305,"Lili Vlad", "Str. Norilor
20","Cluj","lili@server.ro", "0101010101"},
{1022,"Silviu Vlad", "Str. Norilor
20","Cluj","silviu@server.ro", "0101010101"},
{1021,"Alina Vlad", "Str. Norilor
20","Cluj","alina@server.ro", "0101010101"},
{1030,"Sorin Vlad", "Str. Norilor
20","Cluj","sorin@server.ro", "0101010101"},
{1032,"Titi Vlad", "Str. Norilor
20","Cluj","titi@server.ro", "0101010101"},
{1200,"Gigel Vlad", "Str. Norilor
20","Cluj","gigel@server.ro", "0101010101"},
{2021,"Anca Vlad", "Str. Norilor
20","Cluj","ioanca@server.ro", "0101010101"},
{1230,"Maria Vlad", "Str. Norilor
20","Cluj","maria@server.ro", "0101010101"},
{1008,"Elena Vlad", "Str. Norilor
20","Cluj","elena@server.ro", "0101010101"}
};
HashStudent hs;
for (int i=0;i<sizeof(grupa)/sizeof(Student);i++)
{
hs.Insereaza(grupa[i]);
}
hs.Afiseaza();
int m;
cout<<"Matricola: ";
cin>>m;
while (m!=-1)
{
Student rez = hs.Cauta(m);
if (rez.matricola != -1)
rez.Afisare();
cout<<"Matricola: ";
cin>>m;
}
hs.Sterge(1008);
hs.Sterge(406);
hs.Sterge(305);
hs.Afiseaza();
cin.get();
return 0;
18. FIIERE
18.1 Structuri de date externe
Masivele, listele i arborii binari, sunt structuri de date interne, prin
faptul c se afl n memoria intern a unui sistem de calcul. n momentul n
care aceste structuri sunt stocate n memoria extern pe discuri, benzi
magnetice, dischete, compact-discuri acestea sunt numite structuri de date
externe.
Memoria intern a unui calculator este imaginat ca un ir ordonat de
baii. Fiecare bait se definete prin adres i prin coninut. Memoria extern
este imaginat, de asemenea, ca un ir de baii, cu deosebirea c pentru
calculul adresei sunt luate n considerare elementele specifice modului de
structurare a suportului.
Astfel, atunci cnd suportul este organizat n piste, cilindri i
problematica accesului este rezolvat prin poziionarea pe aceste uniti de
acces, adresarea efectundu-se lund n calcul elemente structurale.
n plus, particularitile de desfurare n plan fizic a operaiilor de
intrare/ieire determin analiza distinct a raportului dintre semnificaia
instruciunilor I/O din programe i operaiile efective de citire/scriere de pe
suportul extern.
Presupunnd c pentru un sistem de calcul modulele care realizeaz
citiri/scrieri opereaz cu coninutul unor buffere de lungime L, tot timpul
aceste funcii furnizeaz informaii asupra nceputului zonei ce este
explorat, lungimea acesteia fiind rezultatul logicii de organizare a datelor.
Programatorul are acces direct sau indirect la zona de memorie
tampon prin intermediul adresei sale de nceput sau prin intermediul unei
alte zone de memorie definit n programul su, zon n care este copiat
coninutul bufferului.
2
5
Memoria
extern
6
1
adresa de nceput
buffer
Operaii de
citire / scriere
4
zona de memorie
definit de
utilizator
5 CR
algoritm
conversie
alfanumeri
c- ntreg
variabila A
0 CR
algoritm
conversie
alfanumericntreg
variabila B
CR
algoritm
conversie
alfanumeric
-ntreg
CR
algoritm
conversie
alfanumeric
-real
variabila C variabila D
L
k
L'
(18.2)
256
k
3,2 3
80
(18.3)
g1
n 80
10
100 100 30%
n 256
32
(18.4)
n cazul n care k = 2:
g2
n / 2 m160 100
n 256
(18.5)
unde:
n 3 m 240 100
n 256
(18.6)
Se observ c:
g 3 g 2 g1
(18.7)
Lf
cf
L
citiri
(18.8)
fizice, unde:
cd - citiri fizice din fiier;
Lf - lungimea fiierului, dat n baii;
L
- lungimea unei nregistrri fizice la o citire;
m - variabila boolean ce este 0, dac Lf este divizibil prin L i 1 n
caz contrar.
h) Criteriul privind modul de efectuare a operaiilor de intrare/ieire
grupeaz fiierele n:
- fiiere de tip stream n care datele la scriere sau la citire sunt
cmpuri elementare sau alte tipuri structuri de date, constituite
ntr-un ir, cu indicarea formatului dup care se fac mai nti
conveniile i apoi se stabilesc lungimile irurilor care vor fi
scrise pe suport; fiierul apare ca o succesiune de elemente
oarecare ale cror poziii sunt deduse, dac se iau n calcul
informaiile pe care le ofer descriptorii de format i locul pe
care fiecare element l ocup n lista de parametri ai funciei
apelate la scriere; este de dorit ca aceleai liste de variabile de
la scriere s fie utilizate i la apelul funciilor de citire, iar
descriptorii de format s se menin aceiai pentru a oferi
succes prelucrrilor;
- fiiere de tip record n care datele sunt caracterizate prin
lungime i adres de nceput; articolele au lungime fix sau
variabilitatea lungimilor este n cadrul unei mulimi formate din
cteva elemente; operaiile de lucru cu fiierele de acest tip nu
lgSDi lg
(18.9)
L f n lg lgSDi
i 1
(18.10)
De obicei, lg() = 2. Cei doi baii ataai fiecrui element vor conine
lungimea articolului:
cont lgSDi
(18.11)
adr E1 A lg
(18.12)
unde, A reprezint adresa fizic a primului bait a primului articol cruia i s-a
ataat n fa lg() baii pentru a memora lungimea articolului respectiv:
i 1
adr Ei A cont j lg i
j 1
(18.13)
sau:
i 1
adr Ei A lgSDi i lg
j 1
(18.14)
(18.15)
atunci:
(18.16)
adr Ei A lgSD j
j 1
(18.17)
(18.18)
(18.19)
(18.20)
(18.21)
(18.22)
lim suc m Ei E n
(18.23)
lim pred m Ei E1
(18.24)
(18.25)
deci, irul elementelor este sortat cresctor dup cmpul x, care joac rol
de cheie a articolelor n structura SD de generare.
Elementele de sortare vor fi memorate, fiecare ocupnd o zon de
lungime:
lgSD lg
(18.26)
L f n lg lgSD
(18.27)
(18.28)
cont E x x
n
i.
i 1
(18.29)
j= 1, 2, 3, 4; k = 1, 2, , n
(18.30)
unde k1 k2 k3 k4.
Perechile de delimitare ale nceputului de subir, se obin astfel:
- pentru primul subir:
Q1 cont E1 .x , a1
(18.31)
Q2 cont E1 m .x , a m1
(18.32)
Q3 cont E1 2 m .x , a2 m1
(18.33)
(18.34)
P1 cont E m .x , a m
P2 cont E 2 m .x , a 2 m
P3 cont E3m .x , a3m
P4 cont E n .x , a n
(18.35)
(Q1, P4)
(Q1, P2)
(Q1, P1)
(Q3, P4)
(Q2, P2)
(Q3, P3)
(Q4, P4)
(18.36)
ntruct:
7233
(18.37)
7233
(18.38)
(18.39)
cont k adr E j
cont j adr E k 1
(18.40)
(18.41)
(18.42)
(18.43)
(18.44)
sau:
poz E j
(18.45)
Cu aceste definiii:
adr(Ej) = A + (poz(Ej) 1) * lg(Ej)
(18.46)
(18.47)
(18.48)
PRODUSE
MATERIALE
Cod mat.1 ..
Cod mat. 2 ..
Cod mat. 3. ..
Cod mat. 4 ..
Produsul x
Cod
Denumire UM
produs produs
Pre
Nr.
mat.
4
Cod
mat.
1
Cod
mat.
2
Cod
mat.
3
Cod
mat.
4
MATERIALE
x1
y1
PRODUSE
y1
x2
y2
x3
y3
x4
y4
NULL | G1
Gama de
operaii
G1
Gama de
operaii
Gn
O11
G1
O12
G1
O13
G1
O1k
NULL | Gn
On1
Gn
Okn
M Ki
i 1
(18.49)
cod B
adr (articol A)
adr (articol B)
este
este
este
este
este
vecin cu y
fiul lui y
tatl lui y
soia lui y
soul lui y
persoana x
vecini
familie
soie
copilul Y1
copii
vecinul
din fa
vecinul
din spate
vecinul
din stnga
vecinul
din dreapta
copilul Y10
Productor
Model
Marca 1
Marca 2
Culoare
An fabric.
Marca n
(18.50)
(18.51)
(18.52)
ceea ce nseamn c persoanele ale cror nregistrri ocup poziiile k1, k2,
km cu maini de culoare z i afiarea:
cont (ref (ki) . nume), i = 1, 2, , m
(18.53)
(18.54)
(18.55)
(18.56)
(18.57)
[2, 2]
(18.58)
(18.59)
de regul p < e.
Se construiete irul de adrese:
(18.60)
u = 1, 2, , w
(18.61)
(18.62)
(18.63)
cont ( i) = Bi lg (SDi)
(18.64)
(18.65)
unde nrr( ) este o funcie care definete numrul de articole existent ntr-un
fiier:
nrr : F1, F2, Fk N
(18.66)
unde F este mulimea fiierelor, date prin valoarea iniial a pointerilor lor
externi:
m = mi cont (mj-> capacitate) [1, 1] U [2, 2]
(18.67)
::=
::=
::=
::=
<termen> |
<termen><operator binar><termen> |
<operator unar><termen> |
<termen><operator unar>
termen
expresie
expresie definire
articole
termen
expresie definire
cmpuri
unde:
tip
nume_mat
expresie1,
expresie2
unde:
tip
nume_m
expresie1,
expresie2,,
expresien
La definirea masivelor, se remarc faptul c expresiile care specific
numrul maxim de elemente ale masivului pe fiecare dimensiune trebuie s
fie constant. Acesta este un neajuns atunci cnd se urmrete realizarea
unei aplicaii flexibile i eficiente din punctul de vedere al gestionrii
memoriei.
Soluia la aceast problem o constituie alocarea dinamic a
masivelor, folosindu-se fie funciile malloc, respectiv free, fie operatorii new,
respectiv delete.
Pentru definirea tipului articol se construiete urmtoarea expresie:
struct nume_art {
tip1 cmp1;
tip2 cmp2;
tipn cmpn;
};
unde:
struct
tipn cmpn;
nume_auto *pcmp;
};
Definirea structurii de tip fiier se realizeaz cu ajutorul structurii
standard FILE astfel:
FILE *f;
unde:
FILE structura standard care permite definirea identificatorilor de fiier
n limbajul C++;
f
identificatorul de fiier folosit n cadrul programului, care se
declar ca pointer ctre structura standard FILE.
Lista simplu nlnuit este o structur de date secvenial, fiecare
element al listei, denumit nod, coninnd informaia propriu-zis i adresa
de legtur cu un alt nod. Definirea unui nod al listei se realizeaz astfel:
struct nods {
tip1 cmp1;
tip2 cmp2;
tipn cmpn;
nods *urm;
};
unde:
nods
tip1, tip2, , tipn
cmp1,
, cmpn
urm
reine adresa urmtorului nod n list.
Lista dublu nlnuit este o structur de date secvenial, fiecare
element al listei, denumit nod, coninnd informaia propriu-zis i adresele
de legtur cu nodul anterior, respectiv nodul urmtor n list. Definirea
unui nod al listei se realizeaz astfel:
struct nodd {
tip1 cmp1;
tip2 cmp2;
tipn cmpn;
nodd *pred, *urm;
};
unde semnificaia cmpurilor este aceeai ca la lista simplu nlnuit, cu
meniunea c pred reine adresa nodului predecesor n list.
Stiva este, de asemenea, o structur liniar, de tip list simplu
nlnuit, cu deosebirea c inserrile i extragerile de elemente ale liste se
face ntotdeauna la un acelai capt al listei, respectnd disciplina LIFO
Last Input First Output.
Definirea structurii de tip stiv se realizeaz la fel cu cea a unei liste
simplu nlnuite.
Pointerul la stiv prin care se manipuleaz structura n ansamblu se
numete vrful stivei. Definirea acestuia are loc astfel:
nods *stiva;
unde:
coada
nods
prim, ultim
struct arb_bin{
tip inf;
arb_bin *st, *dr;
};
unde:
arb_bin
unde:
pf
nume
...
nume[0]
nume[1]
nume[2]
zona de memorie
nume[n-1]
nume[0][0]
...
vector de pointeri
nume[0][n-1]
nume[m-1][0]
...
nume[m-1][n-1]
nume.cmp;
Reprezentarea i referirea cmpurilor unei structuri de tip articol:
nume
cmp 1
cmp 2
cmp i
cmp n
nume.cmp i
listad->inf;
listad->urm;
listad->pred;
listad->urm->urm->->urm;
listad->pred->pred->->pred;
stiva->inf;
stiva->urm;
..
stiva ->urm->urm->->urm;
q.prim->inf;
q.ultim->inf;
q.prim->urm;
q.ultim->ultim;
arbore->inf;
arbore->st;
arbore->dr;
i
elementul de rang i care se refer;
cmp un cmp din cadrul elementului de rang i.
Definirea unei structuri de vectori:
struct struct_vect {
tip1 v1[exp1];
tipn vn[expn];
};
unde:
struct_vect
tip1, , tipn
v1, , vn
exp1, , expn
Exemplu:
s.v1[i];
ps->vn[j];
unde:
s
variabile de tip articol;
ps variabil de tip pointer spre articol;
i,j rangul elementelor care au fost referite.
Definirea vectorilor de pointeri spre structuri se realizeaz conform
urmtorului ablon:
nume_art *v[exp];
unde:
nume_art denumire structur de tip articol;
v
identificator variabil de tip masiv unidimensional cu
elemente pointeri spre structuri de tip nume_art;
exp
dimensiune maxim a vectorului.
Referirea unui cmp a vectorului de pointeri:
v[i]->cmp;
unde:
v
i
matrix::matrix(int k, int l)
{
n=k;
m=l;
a=aloc_mat(n,m);
for(int i=0; i<n; i++)
for (int j=0; j<m; j++) a[i][j]=0;
}
int** matrix::aloc_mat(int, int){
int **pmat;
pmat=new int*[n];
for (int i=0; i<n; i++)
pmat[i]=new int[m];
return pmat;
}
void main(){
matrix A(2,3);
matrix *B=new matrix(3,2);
matrix *C=new matrix[3];
Coninut
Descriere
B->a
(*B).a
B->a[0]
(*B).a[0]
B->a[0][0]
(*B).a[0][0]
&B
&B->n
&(*B).n
&B->m
&(*B).m
&B->a
&(*B).a
C[0].n
C[1].m
*(C+i)
C[2].a
C[1].a[0]
C[0].a[0][0]
unde:
pf vectorul de pointeri spre funcii;
i
rangul n vectorul de pointeri a funciei care se apeleaz.
Construirea expresiilor n limbajele de programare, conform
specificaiilor prevzute de fiecare limbaj, prezint o importan deosebit
n dezvoltarea corect din punct de vedere sintactic i mai ales semantic a
programelor surs. Expresiile trebuie s conduc la atingerea obiectivelor
stabilite n etapa de proiectare a aplicaiei.
Construirea expresiilor este o condiie necesar, dar nu i suficient
pentru a obine rezultate corecte din punct de vedere semantic. Se impune,
deci, i o referire corect a variabilelor i expresiilor definite, respectiv
construite ntr-un program surs pentru ca rezultatele obinute s fie n
concordan cu cerinele utilizatorilor.
Containere
Secveniale
set
Adaptive
Asociative
multiset
Iteratori
map
multimap
stack
queue
priority_queue
Acces aleatoriu
Bidirecionali
nainte
De intrare
De ieire
Algoritmi
Implementeaz
vectori
alocai dinamic.
Lista liniar dublu nlnuit
Asemntor
containerului
vector, operaiile putnduse realiza la ambele capete.
Mulime
sortat
de
elemente unice.
Mulime
sortat
de
elemente.
Stocheaz perechi sortate
de tip <cheie, valoare> n
care o cheie identific n
mod unic o valoare.
Stocheaz perechi sortate
de tip <cheie, valoare> n
care o cheie identific una
sau mai multe valori.
Structur de tip stiv.
Structur de tip coad
Structur de tip coad n
care elementelor le sunt
asociate prioriti.
#include <vector>
#include < list >
#include < deque >
#include <algorithm>
<iostream>
<vector>
<list>
<deque>
}
void setNume(char* n)
{
strcpy(this->nume,n);
}
Student(const Student& s)
{
this->nrMat = s.nrMat;
strcpy(this->nume, s.nume);
cout<<"Constructor de copiere clasa Student"<<endl;
}
bool operator<(Student& s)
{
return (this->nrMat < s.nrMat);
}
friend ostream& operator<<(ostream& o, Student s)
{
o<<s.getNrMat()<<" "<<s.getNume()<<endl;
return o;
}
};
void main()
{
Student s1(1, "Gigel");
Student s2(2, "Ionel");
Student s3(3, "Balanel");
//////////////////////////////////////////////////////////////////
//vector de tip de data predefinit
vector<int> vectInt;
vectInt.push_back(10);
vectInt.push_back(1);
vectInt.push_back(25);
vectInt.push_back(12);
for(int i=0; i<vectInt.size(); i++)
cout<<vectInt[i]<<" ";
cout<<endl;
//--------------------------------------------------//vector de tip de data definit de programator
vector<Student> vectStud;
vectStud.push_back(s3);
vectStud.push_back(s2);
vectStud.push_back(s1);
for(int i=0; i<vectStud.size(); i++)
cout<<vectStud[i]<<" ";
cout<<endl;
////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////
//deque pentru tipuri de date predefinite
deque<int> deqInt;
deqInt.push_front(10);
deqInt.push_back(1);
deqInt.push_front(25);
deqInt.push_back(12);
deque<int>::iterator iInt;
for(iInt = deqInt.begin(); iInt!= deqInt.end(); iInt++)
cout<<*iInt<<" ";
cout<<endl;
//----------------------------------------------------------//deque pentru tipuri de date definite de programator
deque<Student> deqStud;
deqStud.push_front(s1);
deqStud.push_back(s3);
deqStud.push_front(s2);
deque<Student>::iterator iStud;
for(iStud = deqStud.begin(); iStud!= deqStud.end(); iStud++)
cout<<*iStud<<" ";
cout<<endl;
}
Pentru tipul de date int i tipul definit Student sunt construite cte
un container de tip vector, unul de tip list i unul de tip deque. In fiecare
dintre acestea sunt adugate elemente de tip int sau Student, dup caz,
utiliznd metode specifice acestor abloane.
Clasa vector permite adugarea elementelor pe la un singur capt,
pe cnd clasele list i deque permit operaii pe la ambele capete. Metoda
push_back() pentru toate cele trei clase i metoda push_front() pentru list
i deque copiaz obiectul ntr-unul dintre elementele clasei. Dac pentru
tipurile predefinite de date copierea valorii obiectului nu pune nici o
problem, copierea unui tip definit de programator necesit suprancrcarea
constructorului de copiere, n special n cazul n care obiectul conine
atribute cu extensie n memoria dinamic. Clasa Student suprancarc
constructorul de copiere i operatorul >>, pentru tiprirea pe ecran a unui
obiect de tip Student. Vectorul de elemente int i cel de elemente Student
pot fi parcuri cu ajutorul unui contor ce ia valori de la 0 la dimensiunea
masivului, dimensiune dat de metoda size() a vectorului. Aceast
parcurgere se datoreaz faptului c vectorul ocup un spaiu contiguu de
memorie dinamic, ceea ce permite calculul deplasrii unui element fa de
nceputul vectorului. Operatorul [] nu este definit i pentru clasele list i
deque, de aceea este necesar definirea unui iterator pentru a realiza
accesul la date. Acest iterator poate parcurge masivul de la nceput dat de
metoda begin() pn la sfrit, dat de metoda end().
Clasa list permite sortarea elementelor containerului (sortare
cresctoare implementat de metoda sort() sau sortare descresctoare,
implementat de metoda reverse()), motiv pentru care, n moment ce
containerul este utilizat pentru stocarea unor obiecte de tip definit de
programator, trebuie suprancrcat operatorul<. Pe baza acestuia este
stabilit relaia de ordine n clasa respectiv.
ablonul deque combin facilitile oferite de vector cu cele oferite de
list. Acesta este proiectat ca un vector ce poate crete n ambele direcii,
deci metodele push_back()/pop_back() i push_front()/pop_front() sunt
valide. Adugarea de elemente n interiorul unui deque este mai lent dect
s1(1,
s2(2,
s3(3,
s4(4,
19,
20,
19,
19,
"Gigel");
"Ionel");
"Balanel");
"Ilie");
/////////////////////////
//sablon set //
/////////////////////////
set<Student> setStud;
setStud.insert(s4);
setStud.insert(s2);
setStud.insert(s3);
setStud.insert(s1);
cout<<"Comparatie dupa cheie:";
cout<<s4.getNume()<<" este"<<(setStud.key_comp()(s4,s2)?" inaintea ":"
dupa ")<<s2.getNume()<<endl;
cout<<"Comparatie dupa valoarea elementului:";
cout<<s4.getNume()<<" este"<<(setStud.value_comp()(s4,s2)?" inaintea
":" dupa ")<<s2.getNume()<<endl;
cout<<"Comparatie dupa cheie:";
cout<<s3.getNume()<<" este"<<(setStud.key_comp()(s3,s1)?" inaintea ":"
dupa ")<<s1.getNume()<<endl;
cout<<"Comparatie dupa valoarea elementului:";
cout<<s3.getNume()<<" este"<<(setStud.value_comp()(s3,s1)?" inaintea
":" dupa ")<<s1.getNume()<<endl;
cout<<"Comparatie dupa cheie:";
cout<<s1.getNume()<<" este"<<(setStud.key_comp()(s1,s4)?" inaintea ":"
dupa ")<<s4.getNume()<<endl;
cout<<"Comparatie dupa valoarea elementului:";
cout<<s1.getNume()<<" este"<<(setStud.value_comp()(s1,s4)?" inaintea
":" dupa ")<<s4.getNume()<<endl;
set<Student>::iterator itStud;
itStud = setStud.find(2);
while(itStud!=setStud.end())
{
cout<<itStud->getNume()<<" ";
itStud++;
}
}
class Student
{
...
//supraincarcare operator< a clasei Student modificata
bool operator<(const Student& s)const{
return (this->varsta < s.varsta);
}
...
}; //sfarsit clasa Student
//////////////
void main()
{
Student
Student
Student
Student
Student
Student
s1(1,
s2(2,
s3(3,
s4(4,
s5(5,
s6(6,
19,
20,
19,
19,
20,
20,
"Gigel");
"Ionel");
"Balanel");
"Ilie");
"Maricica");
"Lenuta");
Numele persoanei, care este cheie, este prima valoare stocat din
cadrul perechii i poate fi referit ca (*numeIterator).first. Numrul de
telefon este a doua valoare memorat i poate fi referit cu ajutorul
iteratorului astfel: (*numeIterator).second. Cutarea unui numr de telefon
dup
numele
persoanei
este
realizat
cu
ajutorul
metodei
find(valoare_cheie) a ablonului map. Aceast funcie returneaz un
iterator, a crui valoare indic fie elementul pentru care valoarea cheii este
egal cu valoarea cutat, fie o adres egal cu cea furnizat de metoda
end() a clasei map, n cazul n care nu exist nici un element n container
pentru care valoarea cheii s fie egal cu valoarea dorit.
Containerul asociativ multimap permite identificarea unei sau mai
multor valori pe baza unei valori a cheii. Mai exact, cheia nu este unic, pot
exista oricte perechi pentru care cheia s fie egal.
Modul de lucru cu containere adaptive este pus n eviden de
exemplul urmtor.
#include
#include
#include
#include
#include
#include
<iostream>
<stack>
<queue>
<vector>
<deque>
<list>
"stdafx.h"
<map>
<string>
<iostream>
agenda.insert(pair<string,string>("Alina","0311111111"));
agenda.insert(pair<string,string>("Dragos","0711111112"));
agenda.insert(pair<string,string>("Dragos","0311111112"));
agenda.insert(pair<string,string>("Vlad","0711111112"));
agenda.insert(pair<string,string>("Ionut","0711111114"));
agenda.insert(pair<string,string>("Marian","0711111115"));
multimap<string, string>::iterator it;
//Parcurgere intreaga agenda
for (it = agenda.begin(); it != agenda.end(); it++)
cout << "Persoana de contact " << (*it).first << ", are
numarul: " << (*it).second<< endl;
while(!Q.empty())
{
cout<<Q.top()<<" ";
Q.pop();
}
//iesire: F E D C B A
}
/* while(*inIterator)
{
vect.push_back(*inIterator);
inIterator++;
} */
//varianta a - stream iesire
copy(vect.begin(),
vect.end(), ostream_iterator<char>(cout, "\n"));
//varianta b - stream iesire
/* while(!vect.empty())
{
*outIterator = vect.back();
vect.pop_back();
} */
}
#include
#include
#include
#include
#include
<iostream>
<list>
<vector>
<iterator>
<algorithm>
#include
#include
#include
#include
#include
<iostream>
<list>
<vector>
<iterator>
<algorithm>
<iostream>
<vector>
<iterator>
<algorithm>
"<<b<<"
si
"<<c<<"
este:
este:
"<<
"<<
cout<<"Maximul
dintre
"<<a<<"
si
max(a,b)<<endl;
cout<<"Maximul dintre "<<a<<", "<<b<<"
max(max(a,b),c)<<endl;
}
"<<b<<"
si
"<<c<<"
este:
este:
"<<
"<<
Conve rsie
NULL
temp=cap;
while (temp->next) temp=temp->next;
temp->next=nou;
return cap;
}
Conve rsie
NULL
1
NULL
21.3
Conversie
unidimensional
masiv
bidimensional
masiv
1 2 3
M 4 5 6
7 8 9
(21.1)
Vector rezultat
1
NULL
Conversie
Date aflate n fiier
1234567
Arbore binar
1243567
Conversie
6
7
0
5
0
2
}
}
Funcia int ** alocmatr(int n,int m), dup cum s-a observat, este
folosit pentru a aloca dinamic spaiu matricei de adiacen, ea ntorcnd un
pointer la matrice. Este un mod economic de a lucra cu matrice mai ales n
cazul n care nu se tie de la nceput dimensiunile ei.
int ** alocmatr(int n,int m)
{
int **x;
int i,j;
x=(int **)malloc(n * sizeof(int));
for(i=0;i<n;i++) x[i]=(int *)malloc(m * sizeof(int));
return x;
}
0 7 5 0
0 0 8 1
M1
0 0 0 3
0 0 0 0
0 1 1 0
0 0 1 1
(21.2) i M 2
0 0 0 1
0 0 0 0
(21.3)
float pret_vanzare;
Se construiesc expresiile:
f.y[i].pret = f.y[i].cantitate * f.y[i].pret_unitar;
f.y[i].tva_calculat = f.y[i].pret * f.y[i].tva / 100;
f.y[i].pret_vanzare = f.y[i].pret + f.y[i].tva_calculat;
cantitate
conversie ntreg
spre float
*
produsul cu
reprezentare
float
conversie float
spre double
pre
pret
tva
conversie ntreg
spre double
float
*
100
conversie float
spre double
rezultat intermediar
conversie
double spre float
tva_calculat
figura
tva
pret
conversie float
spre double
rezultat intermediar
pret_vanzare
conversie
double spre float
struct
struct
double
double
data_emiterii dat;
rand_omogen y[10];
total_tva;
total;
} g;
sizeof ( factura )
*100
G 1
sizeof ( factura _ omogena)
(21.4)
instruciunea:
MOVE
x1 TO x2
x2
0
generat
Figura 21.10 Conversie pe lungime date numerice zecimal despachetat
n cazul n care tipul de dat este alfanumeric la conversia de lungime
se genereaz configuraia de bii asociat caracterului spaiu 32h.
Pentru definirea n limbajul COBOL:
77 y1 PIC X(4) VALUE 'ABCD'.
77 y2 PIC X(7).
instruciunea:
MOVE y1 TO y2
y2
A
25
0019
-25
FFE7
1
0001
-1
FFFF
0
0000
00000000
000000000
0000000
0205
S0205
01
S01
00
0025
S0025
01
S01
00
3235
2D3235
31
2D31
30
'9'
'2'
'4'
'a'
'b'
'c'
'4'
'2'
'9'
'x'
'8'
'1'
'\0
sir[ ]
'x'
'y'
'z'
'a'
'b'
'd'
'+'
'\0
y
00
00
&&
if(nstrlen(sir)>4)
if(nstrlen(sir)==4
if(nstrlen(sir)==4
if(nstrlen(sir)==4
if(nstrlen(sir)==4
if(nstrlen(sir)==4
return 0;
&& sir[i]-'0'>3)
&& sir[i]-'0'>2)
&& sir[i]-'0'>7)
&& sir[i]-'0'>6)
&& sir[i]-'0'>7)
return
return
return
return
return
0;
0;
0;
0;
0;
}
sir[i]='\0';
return i;
}
k++;
i++;
}
}
return k;
}
Tipi
Tipn
Tip1
Tip2
Tipj
Tipk
Tipn
nume
timp_lucrat
salariu_orar retineri
sal
salariat
0
marca
nume
varsta
0
timp
salariu_orar
retineri
sporuri
Pentru calculul valorilor medii ale celor patru serii se impun conversii.
Cel mai simplu este s se efectueze conversiile cmpurilor din articole,
ajungndu-se la structura:
struct art {
int anul;
float t[4];
};
medii[3]=media(T4,N);
for(i=0;i<4;i++)
printf("\n media seriei %d este %f",i+1,medii[i]);
}
(22.1)
dac:
(22.2)
(22.3)
J1
min( Li , L j )
max( Li , L j )
(22.4)
unde:
Li lungimea n octei a procedurii Pi;
Lj lungimea n octei a procedurii Pj;
Aceasta se realizeaz pentru a determina un grad de asemnare
relevant a crui valoare s fie cuprins n intervalul [0; 1].
J2
nca
i 1
(22.5)
NTC
unde:
NTC
ncai
J3
ncv
i 1
(22.6)
NCV
unde:
NCV
J4
unde:
NTCV
ncvf
i 1
NTCV
(22.7)
NESC
NMES
J5
(22.8)
unde:
NESC
J6
(22.9)
unde:
NCIi numrul de cuvinte interschimbabile din procedura Pi;
NCIj numrul de cuvinte interschimbabile din procedura Pj;
Aceasta se realizeaz pentru a determina un grad de asemnare
relevant a crui valoare s fie cuprins n intervalul [0; 1].
Ultimul indicator, J7, are n vedere determinarea gradului de
asemnare a celor dou elemente din punctul de vedere al complexitii
acestora.
Gradul de complexitate se determin conform relaiei:
cmplx = n*ln(n)
(22.10)
J7
min(cmplxi , cmplx j )
max(cmplxi , cmplx j )
(22.11)
J 7
(22.12)
i 1
Jn
C n2
J
i 1
ni
i
(22.13)
unde:
Cn 2 numrul de combinaii posibile de proceduri luate dou cte dou;
Ji
valori indicatori calculate pentru fiecare dou proceduri
considerate;
frecvena de apariie a valorii respectivului indicator.
Ni
De exemplu, se consider procedurile:
P1 destinat calculului sumei ptratelor elementelor unui masiv
unidimensional al crui text surs este:
int sume(int x[],int n)
{
int S;
S=0;
for(int j=0; j<n; j++)
S=S+x[j]*x[j];
return S;
}
este:
conduc
la
obinerea
P1
5
1
1
2
2
3
1
0
3
3
6
1
1
0
1
0
0
0
1
1
Frecvene de apariie
P2
P3
6
5
1
1
1
1
2
3
2
3
3
3
1
0
0
0
4
0
4
0
6
5
1
0
1
1
0
0
1
0
0
0
0
2
0
2
2
2
1
0
P4
5
1
1
3
3
3
0
0
0
0
5
0
1
0
0
2
0
2
2
0
sume
x
n
S
0
prod_sc
y
min
a
b
c
max
Frecvene de apariie
P2
P3
0
0
2
0
2
0
5
0
2
0
1
0
2
0
0
8
0
2
0
3
0
3
0
0
P4
0
0
0
0
0
0
0
0
2
3
3
8
(22.14)
i ntre P3 i P4 i se obine:
I = 0,8(3) * 0,9 = 0,75 (22.15)
Din aceste dou comparaii rezult c gradele de ortogonalitate dintre
P1 i P2, respectiv dintre P3 i P4 sunt foarte sczute.
Se studiaz ortogonalitatea ntre P1 i P3 i se obine:
I = I1 * I2 = 0,68(3) * 0,6916 = 0,4769
(22.16)
i ntre P2 i P4 i se obine:
I = 0,75 * 0,6875 = 0,515
(22.17)
float gr;
h=fopen("GrPartLg.txt","w+");
for(i=0; i<NrFis; i++){
for(j=0; j<NrFis; j++){
f=fopen(F[i],"r");
g=fopen(F[j],"r");
if(f&&g){
fseek(f,0,SEEK_END);
fseek(g,0,SEEK_END);
if(ftell(f)<ftell(g)){
gr=(float)ftell(f)/ftell(g);
fprintf(h,"%5.3f ",gr);
}
else{
gr=(float)ftell(g)/ftell(f);
fprintf(h,"%5.3f ",gr);
}
}
else
if(!f)
cout<<"Fisierul "<<F[i]<<" nu se
deschide!"<<endl;
else
cout<<"Fisierul "<<F[j]<<" nu se
deschide!"<<endl;
fclose(f);
fclose(g);
}
fprintf(h,"\n");
}
//DETERMINAREA GRADULUI DE ASEMANARE A LOTULUI DE FISIERE
fseek(h,0,SEEK_SET);
long double produs=1;
unsigned int NrComp=0;
for(i=0; i<NrFis; i++){
for(j=0; j<NrFis; j++){
fscanf(h,"%f",&gr);
if(i<j){
if(gr){
produs*=gr;
NrComp++;
}
}
}
}
fclose(h);
return pow(produs,1./NrComp);
}
float gr;
gr=(float)nca/52;
fprintf(h,"%5.3f ",gr);
}
else
if(!f)
cout<<"Fisierul
"<<F[i]<<"
nu
se
"<<F[j]<<"
nu
se
deschide!"<<endl;
else
cout<<"Fisierul
deschide!"<<endl;
fclose(f);
fclose(g);
}
fprintf(h,"\n");
}
//DETERMINAREA GRADULUI DE ASEMANARE A LOTULUI DE FISIERE
fseek(h,0,SEEK_SET);
long double produs=1;
unsigned int NrComp=0;
for(i=0; i<NrFis; i++){
for(j=0; j<NrFis; j++){
fscanf(h,"%f",&gr);
if(i<j){
if(gr){
produs*=gr;
NrComp++;
}
}
}
}
fclose(h);
return pow(produs,1./NrComp);
}
str.fr=0;
fwrite(&str,sizeof(FA),1,h1);
cout<<"Continuati?(0/1) ";
cin>>opt;
}
h=fopen("GrPartUserVoc.txt","w+");
for(i=0; i<NrFis; i++){
for(j=0; j<NrFis; j++){
f=fopen(F[i],"r");
g=fopen(F[j],"r");
if(f&&g){
f1=fopen("FrecvF.dat","wb+");
g1=fopen("FrecvG.dat","wb+");
fseek(h1,0,SEEK_SET);
fread(&str,sizeof(str),1,h1);
int nrc=0;
while(!feof(h1)){
nrc++;
fwrite(&str,sizeof(str),1,f1);
fwrite(&str,sizeof(str),1,g1);
fread(&str,sizeof(str),1,h1);
}
//DETERMINARE FRECVENTE DE APARITIE PENTRU
// PRIMUL FISIER
char CuvF[30];
char size=sizeof(FA);
fseek(f1,0,SEEK_END);
long int dim=ftell(f1)/size;
fscanf(f,"%s",CuvF);
while(!feof(f)){
fseek(f1,0,SEEK_SET);
for(k=1;k<=dim;k++){
fread(&str,sizeof(FA),1,f1);
if(strcmp(CuvF,str.cuv)==0){
str.fr++;
fseek(f1,-size,SEEK_CUR);
fwrite(&str,sizeof(FA),1,f1);
}
}
fscanf(f,"%s",CuvF);
}
//DETERMINARE FRECVENTE DE APARITIE PENTRU
//AL DOILEA FISIER
fseek(g1,0,SEEK_END);
dim=ftell(g1)/size;
fscanf(g,"%s",CuvF);
while(!feof(g)){
fseek(g1,0,SEEK_SET);
for(k=1;k<=dim;k++){
fread(&str,sizeof(FA),1,g1);
if(strcmp(CuvF,str.cuv)==0){
str.fr++;
char size=sizeof(FA);
fseek(g1,-size,SEEK_CUR);
fwrite(&str,sizeof(FA),1,g1);
}
}
fscanf(g,"%s",CuvF);
}
int nfa=0;
fseek(f1,0,SEEK_SET);
fseek(g1,0,SEEK_SET);
FA strf,strg;
for(k=1;k<=dim;k++){
fread(&strf,sizeof(FA),1,f1);
fread(&strg,sizeof(FA),1,g1);
if(strf.fr==strg.fr){
if(strf.fr) nfa++;
else nrc--;
}
}
float gr;
gr=(float)nfa/nrc;
fprintf(h,"%5.3f ",gr);
fclose(f1);
fclose(g1);
}
else
if(!f)
cout<<"Fisierul
"<<F[i]<<"
nu
se
"<<F[j]<<"
nu
se
deschide!"<<endl;
else
cout<<"Fisierul
deschide!"<<endl;
fclose(f);
fclose(g);
}
fprintf(h,"\n");
}
fclose(h1);
//DETERMINAREA GRADULUI DE ASEMANARE A LOTULUI DE FISIERE
fseek(h,0,SEEK_SET);
long double produs=1;
unsigned int NrComp=0;
for(i=0; i<NrFis; i++){
for(j=0; j<NrFis; j++){
fscanf(h,"%f",&gr);
if(i<j){
if(gr){
produs*=gr;
NrComp++;
}
}
}
}
fclose(h);
return pow(produs,1./NrComp);
}
while(!feof(g)){
fseek(g1,0,SEEK_END);
dim=ftell(g1)/size;
fseek(g1,0,SEEK_SET);
char vb=0;
for(k=1;k<=dim&&(!vb);k++){
fread(&str,sizeof(FA),1,g1);
if(strcmp(CuvF,str.cuv)==0){
str.fr++;
char size=sizeof(FA);
fseek(g1,-size,SEEK_CUR);
fwrite(&str,sizeof(FA),1,g1);
vb=1;
}
}
if(!vb){
str.fr=1;
strcpy(str.cuv,CuvF);
fseek(g1,0,SEEK_END);
fwrite(&str,sizeof(str),1,g1);
}
fscanf(g,"%s",CuvF);
}
unsigned int nci=0,ncvf=0;
fseek(f1,0,SEEK_END);
dim=ftell(f1)/size;
fseek(g1,0,SEEK_END);
long int dim1=ftell(g1)/size;
FA strf,strg;
fseek(f1,0,SEEK_SET);
for(k=1;k<=dim;k++){
fread(&strf,sizeof(FA),1,f1);
fseek(g1,0,SEEK_SET);
for(int k1=1;k1<=dim1;k1++){
fread(&strg,sizeof(FA),1,g1);
if(strcmp(strf.cuv,strg.cuv)==0){
nci++;
if(strf.fr==strg.fr) ncvf++;
}
}
}
float gr;
gr=(float)ncvf/(dim+dim1-nci);
fprintf(h,"%5.3f ",gr);
fclose(f1);
fclose(g1);
}
else
if(!f)
cout<<"Fisierul
"<<F[i]<<"
nu
se
"<<F[j]<<"
nu
se
deschide!"<<endl;
else
cout<<"Fisierul
deschide!"<<endl;
fclose(f);
fclose(g);
}
fprintf(h,"\n");
}
//DETERMINAREA GRADULUI DE ASEMANARE A LOTULUI DE FISIERE
fseek(h,0,SEEK_SET);
long double produs=1;
unsigned int NrComp=0;
for(i=0; i<NrFis; i++){
for(j=0; j<NrFis; j++){
fscanf(h,"%f",&gr);
if(i<j){
if(gr){
produs*=gr;
NrComp++;
}
}
}
}
fclose(h);
return pow(produs,1./NrComp);
}
fseek(f1,0,SEEK_SET);
char vb=0;
fscanf(f1,"%s",str.cuv);
while(!feof(f1)){
if(strcmp(CuvF,str.cuv)==0)
fscanf(f1,"%s",str.cuv);
vb=1;
}
if(!vb){
fprintf(f1,"%s ",CuvF);
nrcF++;
}
fscanf(f,"%s",CuvF);
}
str.fr=new unsigned int[nrcF];
fseek(f1,0,SEEK_SET);
fscanf(f1,"%s",str.cuv);
unsigned int nri=0;
while(!feof(f1)){
nri++;
for(l=0;l<nrcF;l++) str.fr[l]=0;
fseek(f,0,SEEK_SET);
fscanf(f,"%s",CuvF);
while(!feof(f)){
if(strcmp(str.cuv,CuvF)==0){
fscanf(f,"%s",CuvF);
if(!feof(f)){
fseek(f1,0,SEEK_SET);
for(unsigned int l=0;l<nrcF;l++){
fscanf(f1,"%s",CuvD);
if(strcmp(CuvF,CuvD)==0)
str.fr[l]++;
}
}
}
else fscanf(f,"%s",CuvF);
}
//SCRIEREA IN FISIERUL TEXT A LINIEI k CU
// FRECVENTELE PERECHILOR
fprintf(f2,"%s ",str.cuv);
for(int unsigned l=0;l<nrcF;l++)
fprintf(f2,"%i ",str.fr[l]);
fprintf(f2,"\n");
fseek(f1,0,SEEK_SET);
for(l=0;l<=nri;l++)
fscanf(f1,"%s",str.cuv);
}
//CONSTRUIRE VOCABULAR AL DOILEA FISIER
unsigned int nrcG=0;
fscanf(g,"%s",CuvF);
while(!feof(g)){
fseek(g1,0,SEEK_SET);
char vb=0;
fscanf(g1,"%s",str.cuv);
while(!feof(g1)){
if(strcmp(CuvF,str.cuv)==0)
fscanf(g1,"%s",str.cuv);
}
if(!vb){
fprintf(g1,"%s ",CuvF);
nrcG++;
}
fscanf(g,"%s",CuvF);
vb=1;
}
str.fr=new unsigned int[nrcG];
fseek(g1,0,SEEK_SET);
fscanf(g1,"%s",str.cuv);
nri=0;
while(!feof(g1)){
nri++;
for(l=0;l<nrcF;l++) str.fr[l]=0;
fseek(g,0,SEEK_SET);
fscanf(g,"%s",CuvF);
while(!feof(g)){
if(strcmp(str.cuv,CuvF)==0){
fscanf(g,"%s",CuvF);
if(!feof(g)){
fseek(g1,0,SEEK_SET);
for(unsigned int l=0;l<nrcF;l++){
fscanf(g1,"%s",CuvD);
if(strcmp(CuvF,CuvD)==0)
str.fr[l]++;
}
}
}
else fscanf(g,"%s",CuvF);
}
//SCRIEREA IN FISIERUL TEXT A LINIEI k CU
// FRECVENTELE PERECHILOR
fprintf(g2,"%s ",str.cuv);
for(unsigned int l=0;l<nrcG;l++)
fprintf(g2,"%i ",str.fr[l]);
fprintf(g2,"\n");
fseek(g1,0,SEEK_SET);
for(l=0;l<=nri;l++)
fscanf(g1,"%s",str.cuv);
}
fseek(f2,0,SEEK_SET);
for(l=0;l<k;l++){
fscanf(f2,"%s",CuvF);
for(unsigned int m=0;m<nrcG;m++){
fscanf(f2,"%i",&frc);
str1.fr[m]=frc;
}
}
fscanf(f2,"%s",CuvF);
strcpy(str.cuv,CuvF);
for(l=0;l<nrcF;l++){
fscanf(f2,"%i",&frc);
str.fr[l]=frc;
}
fseek(g2,0,SEEK_SET);
fscanf(g2,"%s",CuvD);
char vb=0;
while(!feof(g2)&&!vb){
if(strcmp(CuvF,CuvD)==0){
ntcc++;
strcpy(str1.cuv,CuvD);
for(l=0;l<nrcG;l++){
fscanf(g2,"%i",&frc);
str1.fr[l]=frc;
}
vb=1;
}
else{
for(l=0;l<nrcG;l++){
fscanf(g2,"%i",&frc);
str1.fr[l]=frc;
}
}
fscanf(g2,"%s",CuvD);
}
if(vb){
unsigned int pozF=0;
fseek(f2,0,SEEK_SET);
fscanf(f2,"%s",CuvF);
while(!feof(f2)){
fseek(g2,0,SEEK_SET);
fscanf(g2,"%s",CuvD);
unsigned int pozG=0;
while(!feof(g2)){
if(strcmp(CuvF,CuvD)==0){
if(str.fr[pozF]==str1.fr[pozG])
nfm++;
}
for(l=0;l<nrcG;l++){
fscanf(g2,"%i",&frc);
str1.fr[l]=frc;
}
fscanf(g2,"%s",CuvD);
pozG++;
}
for(l=0;l<nrcG;l++){
fscanf(f2,"%i",&frc);
str.fr[l]=frc;
}
fscanf(f2,"%s",CuvF);
pozF++;
}
}
}
//DETERMINAREA GRADULUI DE ASEMANARE
float gr;
gr=(float)nfm/(ntcc*ntcc);
fprintf(h,"%5.3f ",gr);
fclose(f1);
fclose(g1);
fclose(f2);
fclose(g2);
}
else
if(!f)
cout<<"Fisierul
"<<F[i]<<"
nu
se
"<<F[j]<<"
nu
se
deschide!"<<endl;
else
cout<<"Fisierul
deschide!"<<endl;
fclose(f);
fclose(g);
}
fprintf(h,"\n");
}
//DETERMINAREA GRADULUI DE ASEMANARE A LOTULUI DE FISIERE
fseek(h,0,SEEK_SET);
long double produs=1;
unsigned int NrComp=0;
for(i=0; i<NrFis; i++){
for(j=0; j<NrFis; j++){
fscanf(h,"%f",&gr);
if(i<j){
produs*=gr;
NrComp++;
}
}
}
fclose(h);
return pow(produs,1./NrComp);
}
vfi); unde vdi este un element din vectorul VD, iar vfi este un
element din vectorul VF;
- reprezentarea prin arbore de cutare cheia din arbore este dat
de un cuvnt; ca informaie util, nodul are ataat numrul de
apariii ale cuvntului n titlul proiectului;
- reprezentarea prin tabele gestionate de un SGBD se definete o
tabel destinat memorrii textelor entitilor software, n care
cheia primar este un cod unic de identificare asociat fiecrei
entiti; aceasta devine cheie extern ntr-o tabel, care conine
coloanele: nr_proiect, cuvnt i apariii; n aceast tabel se
stocheaz cuvintele, mpreun cu numrul de apariii.
Analiza ortogonalitii programelor surs din anexele proiectelor din
baza de proiecte presupune construirea unei matrice ale indicatorilor de
ortogonalitate agregai pentru perechile de programe surs (PRGi, PRGj).
Indicatorul agregat de ortogonalitate asociat perechii (PRGi, PRGj) se obine
prin determinarea ortogonalitii urmtoarelor metrici primare, [Popa02]:
- lungimea programelor presupune determinarea mrimii pe disc
a fiierelor n care sunt stocate codurile surs ale aplicaiilor din
baza de proiecte;
- frecvenele de apariie a caracterelor alfabetice const n
ncrcarea elementelor masivelor unidimensionale cu numrul de
apariii al caracterelor utilizate n construirea programelor;
- vocabularul utilizator utilizatorul introduce cuvinte, rezervate
sau definite, pe care le urmrete n programele analizate din
punctul de vedere al frecvenelor de apariie;
- vocabularul programelor se identific cuvintele diferite din
textele surs i se determin frecvena lor de apariie;
- vocabularul comun const n identificarea cuvintelor comune din
vocabularele textelor surs i determinarea frecvenelor de
apariie;
- structura entitilor const n mprirea n paragrafe a
programelor surs i determinarea de frecvene de apariie pentru
fiecare paragraf;
- variabilele definite pe baza sintaxei limbajului se identific
variabilele utilizate i se determin frecvenele de apariie;
- matrice de preceden a variabilelor presupune specificarea
ordinii de folosire a variabilelor printr-o structur de tip masiv
bidimensional; compararea valorilor din matricea de preceden
conduce
la
determinarea
indicatorului
de
ortogonalitate
corespunztor acestui criteriu;
- poziia variabilelor presupune identificarea variabilelor i
reinerea poziiilor acestora n funcie de instruciunile asociate n
utilizare.
Modul n care este proiectat permite includerea de noi indicatori i
implementarea de noi mecanisme de analiz comparata a datelor.
(23.1)
pi
V
100
Ci
(23.2)
V C
j1
(23.3)
[min] C i Vj
j1
(23.4)
De exemplu, se consider:
Ci = 1000, V1 = 200, V2 = 500, V3 = 400, V4 = 300
(23.5)
Se calculeaz sumele:
S1 = V1 + V2 + V3 + V4 = 1400 > Ci
S2 = 200 + 500 + 400 = 1100 > Ci
S3 = 200 + 500 + 300 = 1000 = Ci
S4 = 500 + 400 = 900 < Ci
S5 = 500 + 400 + 300 = 1200 > Ci
S6 = 200 + 500 = 700 < Ci
S7 = 500 + 300 = 800 < Ci
S8 = 200 + 300 = 500 < Ci
S9 = 200 + 400 = 600 < Ci
S10 = 400 + 300 = 700 < Ci
(23.6)
(23.7)
(23.8)
(23.9)
(23.10)
(23.11)
(23.12)
(23.13)
(23.14)
(23.15)
(23.16)
g : KA
(23.17)
unde:
k = { k1, k2, . . . , km}
(23.18)
este mulimea cuvintelor compactate, aa fel nct exist o pereche (i, j),
pentru care:
kj = f (ai)
ai = g (kj)
(23.19)
(23.20)
(23.21)
(23.22)
de lungime iniial:
L1 = 1g(a1 a2 a3 a3 a3 a3 a3) = 1g (a1) + 1g (a2) + 4*1g (a3)
(23.23)
(23.24)
de lungime:
L2 = 1g (k1) + 1g (k2) + 4*1g (k3)
(23.25)
L1 - L 2
100
L1
(23.26)
(23.27)
(23.28)
Li - Lf
100 25%
Lf
(23.29)
L i - f i *1g(c j ) f j
j1
j1
Li
*100
(23.30)
L i - f j * [1g(C j ) 1g j )]
j1
Li
* 100
(23.31)
g2,
. . .,
30
DENUMIRE
15
VALOARE
1
CUIE
TABLA
VAR
2
100
200
600
900
1480 523
* 100 64%
1480
(23.32)
VALOARE
!**
!**
p'
(23.33)
pentru
pentru
pentru
pentru
pentru
pentru
forjor
strungar
frezor
economist
mecanic
supraveghetor
L m 2 * (n 1 n 2 n 3 n 4 n 5 n 6 )
L s n1 n 2 n 3 n 4 n 5 n 6
(23.36)
1
101
1001
10001
10101
100001
L B n 1 *1 n 2 * 3 n 3 * 4 n 4 * 5 n 5 * 5 n 6 * 6
Observm c:
8 * L b 8 * Ls L B
(23.38)
(23.37)
L F 8 13 (n 1 n 2 n 3 n 4 n 5 n 6 )
(23.39)
(23.40)
(23.41)
Lb=100*6+300*8+100*6+100*9+300*7+100*13=7900 baii
LB=100+300*3+100*4+100*5+300*5+100*6=4000 bii
(23.42)
(23.43)
p1
104000 3000
*100 97%
104000
(23.45)
p2
7900 * 8 3000
*100 95%
7900 * 8
(23.46)
p3
23.6
repetitive
4000 3000
*100 25%
4000
Compactarea
prin
(23.44)
(23.47)
identificarea
de
subiruri
(23.48)
1000
1001
1010
1011
1100
1101
1110
1111
1000
u1
lor
it
am
cr
sa
nstr
asera
1001
1e
se
la
ar
sc
ma
eau
res
1010
pr
ut
ea
ei
st
ne
eam
tit
1011
mb
re
ta
ra
os
tre
esti
ros
1100
mp
tr
ti
ne
ti
ist
ndu
oasa
1101
ni
te
ca
un
at
tri
u-se
isem
1110
in
ta
oi
ns
ri
urile
ati
tit
1111
lui
nu
au
nt
oa
ind
nul
art
x
17
x
26 24
sux
64
de
26
aga
12
x
rge
36 27
x lux x
62
57 12
Cix
x
26
Vix
A
x
x
vor spx ge
58 24 12
42
ux x
, valux x
48 57 12
57 12
fox odat ca-n povex
53
73
A fox
x
53
Dx
x
26
rude x
17
ciodat
16
x
ix aratx
62 57 15
74
o x x
fata
13 33
85
177 137
* 100 22%
177
(23.49)
177 116
* 100 34%
177
(23.50)
177 * 8 116 * 6
* 100 52%
177 * 8
(23.51)
CICLU:
BETA:
ORG
MOV
PUSH
XRA
LDAX
ADC
DCR
JZ
STAX
INX
INX
JMP
MOV
420 H
D , E
B
A
B
M
E
BETA
B
B
H
CICLU
LOAX B
XRA M
MOV A , E
STAX B
STC
JM GAMA
MOV A , M
XRA E
STC
JM DELTA
GAMA: CMC
DELTA:
POP
MOV
RET
END
B
E , D
53
C5
AF
OA
8E
1D
CA
02
03
23
C3
5F
OA
AE
7B
02
37
FA
7E
AB
37
FA
C1
5A
C9
2F
04
23
04
3F
04
3F
04
Frecvena
8
2
4
9
4
4
4
1
1
6
1
3
1
4
6
53
C5
AF
OA
0004
8E
0005
1D
0006
CA
0009
000A
02
03
000B
23
000C
C3
000F
5F
0010
0A
0011
AE
0012
7B
0013
02
0014
0015
37
FA
0018
7E
0019
AB
001A
37
001B
FA
001F
C1
00
OF
00
03
00
1F
00
1F
0020
5A
0021
C9
Frecvena
0
1
2
3
4
5
6
7
8
9
A
B
C
D
E
F
5
1
2
2
2
1
2
5
2
Frecvena
1
2
4
1
2
1
A
B
C
D
E
F
6
2
1
3
2
11120
11170
11121
11130
11135
11122
11131
11131
11120
11136
11109
11104
(23.52)
iar:
60
D
0,005
Xmin 11108
(23.53)
(23.54)
26
5
27
17
32
18
66
16
51
0
84 2 * 8
100
100
100 52%
24 * 8
192
(23.55)
111
113
111
111
112
112
112
112
112
112
3 7 12 2
45
100
100 46%
12 8
96
(23.56)
Nr. de apariii
simbol
0
1
2
3
4
5
6
7
Total
12
8
6
5
4
3
2
0
40
30%
0
0
20%
10
1
100 %
15%
12%
10%
110
2
3
35 %
0
5%
23%
13 %
5%
1
1110
50 %
8%
0%
70 %
11110
111110
1
1111110
1
1111111
30%
20%
15%
12%
110
100%
27%
70%
43%
8%
5%
6
7
11110
23%
13%
5%
101
1110
0
0
10%
100
0%
111110
111111
Nr. de
apariii
simbol
12
8
6
5
4
3
2
0
40
Etape ale
ciclului de
dezvoltare
Inspecie
DA
Produsul
respect
specificaiile?
Integrare
NU
NU
Continuare proces
dezvoltare
Costuri
mai
mari?
Testare
DA
Abandonare
34.3 Locul
informatic
inspeciei
software
cadrul
auditului
C
c) Programul realizeaz mai multe funcii dect au fost prevzute
n specificaii
x 2 daca x 0
1
a = 2 daca x 0
x
1 daca x 0
(34.1)
n program:
if (b > 0) a = x * x;
else
if (b < 0) a = 1 / (x * x);
else
a = 1;
Produsul
inspectat
Etapa de
planificare
Pachet de
inspecie
Etapa de
prezentare
Lista de
defecte
Etapa de
pregtire
Nota de
ntlnire
Etapa de
ntlniri
Raport
intermediar
de inspecie
Etapa de
refacere
Etapa de
verificare
Produsul
revizuit
Produsul
verificat
Raport final
de inspecie
Scop
INSPECIE
Criterii
de intrare
Liste verificare
Participani
Proceduri
Criterii
de ieire
Clasificarea
defectelor
Descriere
Identificarea produsului de inspectat i stabilirea
planului de inspecie
Etap opional n care membrii echipei care nu
sunt familiarizai cu produsul de inspectat se
familiarizeaz cu problema
Membrii echipei inspecteaz individual produsul
pentru gsirea defectelor
Membrii echipei se ntlnesc pentru a discuta
posibilele defecte gsite
Produsul este revizuit conform cerinelor i
specificaiilor
Produsul refcut este verificat, datele finale ale
inspeciei sunt colectate i centralizate i procesul
de inspecie este nchis
Sarcini
Msurtori
Planificarea efortului;
Dimensiunea produsului;
Definitivarea i distribuirea pachetului de inspecie
Planificarea unei prezentri (opional).
Moderatorul:
verific ndeplinirea criteriilor de demarare;
selecteaz membrii echipei de inspecie;
decide dac este necesar organizarea unei
prezentri;
planific ntlnirile i ntocmete notele de
ntlnire;
Autorul:
revede produsul cu moderatorul;
propune membrii echipei;
recomand, dac este cazul, o ntlnire de
prezentare;
Ieiri
Roluri
Informare;
Produsul de inspectat;
Prezentarea materialului;
Sarcini
Msurtori
Ieiri
Roluri
Moderatorul:
conduce ntlnirea astfel nct s maximizeze
schimbul de informaii;
dac este necesar, atribuie responsabiliti (teste,
standarde, claritate) pentru fiecare inspector;
Autorul:
pregtete ntlnirea;
prezint materialul;
rspunde la ntrebri;
Inspectorul:
pune ntrebri pentru o mai bun nelegere a
produsului;
nu revizuiete i nu discut alternative de
proiectare/implementare;
Performan
Testabilitate
Fezabilitate
Maleabilitate
Capacitate de
modificare
ntrebri
Cerinele sunt clare si neambigue?
Toate cerinele au standarde ce trebuie
urmrite?
Toate cerinele sunt complete?
Cerinele sunt independente de proiectare?
Cerinele sunt consistente?
Datele sunt structurate i funciile au nume i
sunt folosite consistent?
Funciile sunt corect specificate?
Intrrile i ieirile sunt specificate clar?
Funciile sunt logic independente i formeaz
o structur bine organizat?
Sunt clar definite cerinele de performan
pentru sincronizare, folosirea memoriei i a
resurselor?
Exist cerine pentru testare i verificare?
Fiecare component poate fi implementat cu
tehnicile,
instrumentele,
resursele
i
personalul disponibil i cu restriciile de
costuri i planificare specificate?
Cerinele sunt unic identificate?
Cerinele sunt unic structurate astfel nct
orice modificare necesar s poat fi fcut
uor, complet i consistent?
Msurtori
Ieiri
Roluri
Inspectorul:
studiaz produsul;
identific defectele;
nregistreaz timpul de pregtire;
Moderatorul:
realizeaz toate sarcinile de pregtire
inspeciei;
Lectorul:
stabilete cum s prezinte produsul;
Msurtori
Ieiri
Introducere;
Citirea produsului;
Identificarea i nregistrarea defectelor;
Rezumatul revizuirii defectelor;
Determinarea dispoziiei produsului;
Gradul de corectitudine a datelor;
Datele defecte;
Dispoziia produsului;
Lista complet de defecte;
Sumarul complet al defectelor;
Nota complet a ntlnirii de inspecie;
Raportul parial de inspecie;
Roluri
Autorul:
rmne un asculttor obiectiv i activ, ia
notie;
nu adopt o atitudine defensiv;
Inspectorii:
obiectivi i impersonali;
bine pregtii i participani activi;
nu trebuie s ridice probleme de stil i soluii
de dezvoltare;
Moderatorul:
ncepe i termin edina la timp, meninnd o
atmosfer adecvat;
urmrete meninerea sinergiei ntlnirii;
se asigur c defectele ntrunesc consensul
echipei;
Lectorul:
stabilete cea mai bun strategie de
prezentare a produsului;
rspunde la ntrebrile puse de membrii
echipei;
nregistratorul:
trebuie s fie familiarizat cu schema de
clasificare a defectelor;
nregistreaz toate datele n lista principal de
defecte;
sintetizeaz datele defecte n sumarul de
inspecie;
Sarcini
Msurtori
Ieiri
Roluri
Autorul:
rezolv toate defectele;
notific moderatorului terminarea refacerii;
raporteaz
managerului
de
proiect
defectele
nerezolvate;
Numrul de defecte;
Efortul de refacere;
Defecte rezolvate;
nregistrarea timpului de refacere n lista principal de
defecte;
Notificarea ctre moderator a terminrii refacerii;
Produsul revizuit;
Autorul:
rezolv defectele;
raporteaz
managerului
de
proiect
defectele
nerezolvate;
notific moderatorului terminarea refacerii;
Msurtori
Ieiri
Roluri
INSPECIE
Lista de
defecte
Rezumatul
defectelor
Raportul de
management
x Liu
x ( Lgp Liu ) Lgcpl
(32.1)
struct element{
info * inf;
element * urm;
};
rezult:
x
Liu
142 78
=0.9748
142 (78 2) 2
(32.2)
x Liu
x (2 Lgp Liu ) 2 Lgcpl
(32.3)
rezult:
x
Liu
Lgp
Lgcpl
142 78
=0.9508
142 (78 4) 4
(32.4)
C++:
x Liu
x (2 Lgp Liu ) Lgcpl
(32.5)
Pentru arborele binar ale crui noduri sunt definite prin secvena
struct element{
info * inf;
element * fius;
element * fiud;
};
142 78
=0.9510
142 (4 78) 2
(32.6)
NrN ni
(32.7)
i 1
NrN Liu
NrN ( Liu 2 Lgp ) Lgcpl
(32.8)
Gru=
NrN Liu
NrN ( Liu 2 Lgp) Lgcpl
(32.9)
7 78
=0.9479
7 (78 2 2) 2
(32.10)
Informaie
util 2
Informaie
util 2*m
descendent
stng
descendent
drept
Gru=
x 2 m Liu
x (2 m Liu 2 Lgp) Lgp
(32.10)
struct element{
info * inf[2*m];
element * desc[2*m+1];
};
x 2 m Liu
x 2 m Liu x (2 m 1) Lgp Lgcpl
(32.11)
Gru=
9 2 1 78
= 0.9499
9 2 1 78 9 (2 1 1) 2 2
(32.12)
pb
x Liu
x ( Liu Lgpp Lgps ) Lgpd
GruLS=
Narc L gcd
Narc ( L gcd Lgspu )
(32.13)
(32.14)
Gru=
GruLP GruLS
2
(32.15)
Pentru graful din figura 32.3 ale crui noduri sunt definite n lista de
baz prin secvena C++:
struct elemente_Lista_Baz{
info * inf;
elementLS * arc;
elementLP * urm;
};
rezult:
x
Liu
Lgps
Lgpb
Lgpp
Lgspu
Lgcd
Narc
6 78
=0.9473
6 (78 2 2) 2
GruLS=
Gru=
10 4
=0.6667
10 (4 2)
0.9473 0.6667
=0.807
2
(32.16)
(32.17)
(32.18)
PVEC
GruLS=
x Lgve
x Lgve Lgpv
(32.19)
Narc L gcd
Narc ( L gcd Lgspu )
Gru=
GruVP GruLS
2
(32.20)
(32.21)
struct elementLS{
info * inf;
elementLS * urm;
};
rezult ca pentru:
x
- numarul de elemente din vectorul de pointeri egal cu 6;
Lgve
- lungimea unui element din vectorul de pointeri care se obine
din lungimea informaiei utile Liu la care se adaug pointerul spre
capul de lista a arcelor incidente spre exterior nodului, adic
Lgve=Liu + Lgp = 80 de baii;
Lgpv
- lungimea variabilei pointer de 2 baii ctre vectorul de baz;
Lgspu - lungimea pointer-ului spre elementul urmtor din lista
secundar de 2 baii;
Lgcod - lungimea zonei de memorie n care se stocheaz codul nodului
destinaie egal cu 4 baii;
Lgpa
- lungimea pointerului din lista de arce de 2 baii;
Narc
6 80
=0.9958
6 80 2
(32.22)
GruLS=
10 4
=0.6667
10 (4 2)
(32.23)
0.9958 0.6667
=0.8312
2
(32.24)
Gru=
<6,5>
<1,3>
<1,2>
<6,1>
cpl
NULL
NULL
NULL
<4,2>
NULL
<3,4>
<3,5>
NULL
NULL
<2,3>
<2,6>
<6,4>
GruLP=
x Liu
x ( Liu Lgpp Lgps ) Lgpb
GruLS=
Narc Lgpd
Narc ( Lgpd Lgspu )
(32.25)
(32.26)
rezult c pentru:
- numrul de noduri din graf este 6;
x
Liu
- lungimea zonei de memorie ocupat de informaia util din
fiecare nod i care se memoreaza n lista de baz; informaia util
conine obligatoriu codul nodului n raport cu care se realizeaz
identificarea arcelor incidente spre exterior este 78;
- lungimea zonei de memorie din lista de baz ocupat de
Lgps
variabila pointer de 2 baii ce reprezint pointer spre primul
element al listei secundare asociat arcelor descendente spre
exterior nodului;
Lgpb
- lungimea variabilei pointer de 2 baii care refer primul element
din lista de baz;
Lgpp
- lungimea asociat spre urmatorul element din lista principal de
2 baii;
Lgspu - lungimea pointer-ului spre elementul urmtor din lista
secundar este de 2 baii;
Lgcd
- lungimea pointerului pentru identificarea nodului destnaie; este
de 2 baii;
Narc
- numarul total de arce din graf este 10.
gradul de utilizare este:
GruLP=
6 78
=0.9473
6 (78 2 2) 2
10 2
= 0.5
10 (2 2)
(32.28)
0.9473 0.5
=0.7236
2
(32.29)
GruLS=
Gru=
(32.27)
x Liu
(32.30)
x ( Liu 3 Lgp ) 3 Lgcpl
x Liu
=1
x Liu
(32.31)
x Liu
x Liu Lgcpl
(32.32)
142
142 4
=0.9965 (32.33)
142 4 2
prin
int ** matrice;
m n Liu
m n Liu n Lgpvc Lgpm
(32.34)
1
2
3
142
2 71 4
=0.7977
2 71 4 71 2 2
(32.35)