Você está na página 1de 51

-- 7.

1 --
E.Kalisz - Structuri de date
Colectii cu disciplina de prelucrare
dictata de ordinea inserarii elementelor
Coada: primul venit primul servit
(First In First Out FIFO)
Analogii: cereri rezolvate in ordinea inregistrarii

Inceput
- extragere

< Coada <
Sfarsit
- introducere
-- 7. 2 --
E.Kalisz - Structuri de date
Stiva: ultimul venit primul servit
(Last In First Out LIFO)
Analogii: tub de medicamente, dosare puse
teanc in ordinea primirii si parcurse la finalul
zilei in ordinea in care sunt asezate etc.

Varf
- introducere
- extragere


Stiva
Baza
Colectii cu disciplina de prelucrare
dictata de ordinea inserarii elementelor
-- 7. 3 --
E.Kalisz - Structuri de date
Coada Operatie Stiva
< 1, 2 , 3 < E | 1, 2 , 3 :
< 2, 3 < I4 | 1, 2 :
< 2, 3, 4 < I8 | 1, 2, 4 :
< 2, 3, 4, 8 < E | 1, 2, 4, 8 :
< 3, 4, 8 < I5 | 1, 2, 4 :
< 3, 4, 8, 5 < E | 1, 2, 4, 5 :
< 4, 8, 5 < E | 1, 2, 4 :
< 8, 5 < | 1, 2 :
Efectul operatiilor de Inserare / Extragere
-- 7. 4 --
E.Kalisz - Structuri de date
Pentru ca intr-o aplicatie sa se poata lucra cu
mai multe cozi si/sau stive, ale caror elemente sunt
de tipuri diferite, este necesar ca acestea sa fie
definite ca tipuri generice (coada / stiva de orice).
Deoarece, asa cum vom discuta mai tarziu, exista
diverse variante de implementare pentru aceste
tipuri de date, este indicat sa definim operatiile
specifice independent de implementarea aleasa
pentru o anumita aplicatie.
In acest context, pentru a lucra cu o coada/ stiva
vom utiliza un pointer generic (void*), reprezentand
adresa structurii care incapsuleaza elemente de un
anumit tip.
Coada si Stiva generice
-- 7. 5 --
E.Kalisz - Structuri de date

Inserare / extragere element

(void*)
(void*)
structura
generica
element de
dimensiune d
Coada si Stiva generice
-- 7. 6 --
E.Kalisz - Structuri de date
Initializare structura cu elemente de dimensiune d:
void* InitQ(size_t d,...);
void* InitS(size_t d,...);
Rezultat: NULL sau adresa structura
Inserare:
int IntrQ(void* a, void* ae);
int Push(void* a, void* ae);
Rezultat: 1 succes / 0 - esec
Coada si Stiva generice - operatii standard
-- 7. 7 --
E.Kalisz - Structuri de date
Extragere
int ExtrQ(void* a, void* ae);
int Pop(void* a, void* ae);
Rezultat: 1 succes / 0 - esec
Eliberarea intregului spatiu ocupat de structura:
void DistrQ(void** aa);
void DistrS(void** aa);
Test structura vida:
int VidaQ(void* a);
int VidaS(void* a);
Coada si Stiva generice - operatii standard
-- 7. 8 --
E.Kalisz - Structuri de date
Copiere element accesibil:
int PrimQ(void* a, void* ae);
int Top(void* a, void* ae);
Numar elemente:
size_t NrEQ(void* a);
size_t NrES(void* a);
Dimensiune elemente:
size_t DimEQ(void* a);
size_t DimES(void* a);
Coada si Stiva generice - operatii standard
-- 7. 9 --
E.Kalisz - Structuri de date
Transformare in structura vida:
void ResetQ(void* a);
void ResetS(void* a);
Coada si Stiva generice alte operatii
-- 7. 10 --
E.Kalisz - Structuri de date
Coada: int MutaQ(void* ad, void* as);
Destinatie Sursa
< 1, 2, 3 < < 20, 13, 8, 5 <

< 1, 2, 3, 20 < < 13, 8, 5 <


Stiva: int MutaS(void* ad, void* as);
Destinatie Sursa
| 1, 2, 3 : | 20, 13, 8, 5 :

| 1, 2, 3, 5 : | 20, 13, 8 :
Echivalenta cu extragere urmata de introducere.
Mutarea unui element
-- 7. 11 --
E.Kalisz - Structuri de date
Concatenare cozi
int ConcatQ(void* ad, void* as);
Destinatie Sursa
< 1, 2, 3 < < 13, 8, 5 <

< 1, 2, 3, 13, 8, 5 < <<


Rastoarna stiva sursa in stiva destinatie
int Rastoarna(void* ad, void* as);
Destinatie Sursa
| 11, 22 : | 21, 22, 23 :

| 11, 22, 23, 22, 21 : |:


Pot fi realizate prin mutari repetate.
Transfer continut Coada / Stiva
-- 7. 12 --
E.Kalisz - Structuri de date
int Suprapune (void* ad, void* as);
Destinatie Sursa
| 11, 22 : | 21, 22, 23 :

| 11, 22, 21, 22, 23 : |:


Poate fi realizata prin mutari repetate, folosind o
stiva auxiliara:
{ initializeaza stiva aux;
cat timp sursa nevida
{ muta element din sursa in aux;}
cat timp aux nevida
{ muta element din aux in destinatie;}
distruge stiva aux;
}
Suprapunere Stive
-- 7. 13 --
E.Kalisz - Structuri de date
int InvS(void* a);
| 1, 2, 3, 4, 5 : | 5, 4, 3, 2, 1 :
Poate fi realizata prin mutari repetate, folosind
o coada auxiliara:
{ initializeaza coada;
cat timp stiva nevida
{ extrage element din stiva;
introduce elementul in coada;
}
cat timp coada nevida
{ extrage element din coada;
introduce elementul in stiva;
}
distruge coada;
}
Inversare Stiva
-- 7. 14 --
E.Kalisz - Structuri de date
A. Folosind un vector de elemente de dimensiune d
Implementare stiva generica A [1]

a maxe dime b sv vf
p . . . . y z / / / / / /
typedef struct
{ size_t maxe, dime; /* nr.maxim elemente,
dimensiune element */
char *b, *sv, *vf; /* baza, sfarsit vector,
varf stiva */
} TStiva, *ASt;
Stiva vida: a->vf == a->b
-- 7. 15 --
E.Kalisz - Structuri de date
/*- macrodefinitii utile -*/
/*- acces la campuri -*/
#define DIME(a) (((ASt)(a))->dime)
#define BS(a) (((ASt)(a))->b)
#define SV(a) (((ASt)(a))->sv)
#define VF(a) (((ASt)(a))->vf)
/*- teste -*/
#define DIMDIF(s,d) (DIME(s) != DIME(d))
#define VIDA(a) (VF(a) == BS(a))
#define PLINA(a) (VF(a) == SV(a))
Implementare stiva generica A [2]

a maxe dime b sv vf
p . . . . y z / / / / / /
-- 7. 16 --
E.Kalisz - Structuri de date
Initializare
a = InitS(sizeof(tip_element), maxim);
In cazul unei initializari reusite
a->maxe == maxim
a->dime == sizeof(tip_element)
a->sv == a->b + a->maxe * a->dime
Implementare stiva generica A [3]

a maxe dime b sv vf

-- 7. 17 --
E.Kalisz - Structuri de date
void* InitS(size_t d,...)
{ ASt a = (ASt)malloc(sizeof (TStiva));
va_list ap;
if (!a) return NULL;
/* preia param.2 = nr.max.elemente */
va_start(ap,d);
a->maxe = va_arg(ap,size_t);
va_end(ap);
a->dime = d;
/* aloca spatiu pentru vector si test esec */
a->b = (char*)calloc(a->maxe, d);
if(!a->b) { free(a); return NULL; }
/* actualizeaza adrese din descriptor */
a->vf = a->b;
a->sv = a->b + d * a->maxe;
return (void*)a;
}
Implementare stiva generica A [4]
-- 7. 18 --
E.Kalisz - Structuri de date
Inserare
int Push(void* a, void* ae)
/* pune in varful stivei element de la adresa ae */
{ if(PLINA(a)) return 0;
memcpy(VF(a), ae, DIME(a)); /* copiaza element */
VF(a) += DIME(a); /* deplaseaza varful stivei */
return 1;
}
Implementare stiva generica A [5]

ae
w
a maxe dime b sv vf
p . . . . y w / / / / /
-- 7. 19 --
E.Kalisz - Structuri de date
Extragere

ae
z
a maxe dime b sv vf
p . . . . y z / / / / / /
int Pop(void* a, void* ae)
/* extrage elem.din varful stivei la adresa ae */
{ if(VIDA(a)) return 0;
VF(a) -= DIME(a); /* deplaseaza varful stivei */
memcpy(ae, VF(a), DIME(a)); /* copiaza elementul */
return 1;
}
Implementare stiva generica A [6]
-- 7. 20 --
E.Kalisz - Structuri de date
Top
int Top(void* a, void* ae)
/* copiaza elementul din varful stivei la adresa ae */
{ if(VIDA(a)) return 0;
memcpy(ae, VF(a)-DIME(a), ae, DIME(a));
/* copiaza elementul din varful stivei */
return 1;
}
Implementare stiva generica A [7]

a maxe dime b sv vf
p . . . . y z / / / / / /
-- 7. 21 --
E.Kalisz - Structuri de date
Numar elemente
int NrES(void* a)
/* numarul de elemente din stiva */
{
return (VF(a) BS(a)) / DIME(a);
}
Implementare stiva generica A [8]

a maxe dime b sv vf
p . . . . y z / / / / / /
-- 7. 22 --
E.Kalisz - Structuri de date
Reset
void ResetS(void* a)
/* transforma stiva in stiva vida*/
{
VF(a) = BS(a);
}
Implementare stiva generica A [9]

a maxe dime b sv vf
p . . . . y z / / / / / /
-- 7. 23 --
E.Kalisz - Structuri de date
Distrugere stiva
void DistrS(void** aa)
/* elibereaza intregul spatiu ocupat de stiva*/
{
free(BS(*aa));
free((ASt)(*aa));
*aa = NULL;
}
Implementare stiva generica A [10]

a maxe dime b sv vf
p . . . . y z / / / / / /
-- 7. 24 --
E.Kalisz - Structuri de date
int MutaS(void *ad, void *as)
/* muta elementul din varful stivei sursa */
{ /* teste dim.diferite, sursa vida, lipsa spatiu
in stiva destinatie */
if(DIMDIF(as,ad)) return -1;
if(VIDA(as)) return 0;
if(PLINA(ad)) return -2;
/* mutare element */
VF(as) -= DIME(as);
memcpy(VF(ad), VF(as), DIME(as));
VF(ad) += DIME(ad);
return 1;
}
Implementare stiva generica A [11]
-- 7. 25 --
E.Kalisz - Structuri de date
int Suprapune(void *ad, void *as)
/* muta stiva sursa peste destinatie */
{ size_t n = VF(as) BS(as); / *numar oct et i mut at i */
if(DIMDIF(as,ad)) return -1;
if(VIDA(as)) return 0;
if(VF(ad) + n > SV(ad)) return -2;
/* transfer elemente */
memcpy(VF(ad), BS(as), n);
VF(ad) += n; VF(as) = BS(as);
return 1;
}
Implementare stiva generica A [12]
-- 7. 26 --
E.Kalisz - Structuri de date
int Rastoarna (void *ad, void *as)
/* suprapune inversul sursei peste destinatie */
{
size_t n = VF(as) BS(as);
if(DIMDIF(as,ad)) return -1;
if(VIDA(as)) return 0;
if(VF(ad) + n > SV(ad)) return -2;
while(VF(as) > BS(as))
{
VF(as) -= DIME(as);
memcpy(VF(ad), VF(as), DIME(as));
VF(ad) += DIME(ad);
}
return 1;
}
Implementare stiva generica A [13]
-- 7. 27 --
E.Kalisz - Structuri de date
int InvS(void *a)
/* inverseaza continutul stivei */
{
char* temp, *p, *q;
temp=(char*)malloc(DIME(a));
if(!temp) return 0;
/* inverseaza perechi de elemente: p, q pornesc
de la baza, respectiv varful stivei */
for(p = BS(a), q = VF(a)-DIME(a);
p < q; p += DIME(a), q -=DIME(a))
{
memcpy(temp, p, DIME(a));
memcpy(p, q, DIME(a));
memcpy(q, temp, DIME(a));
}
return 1;
}
Implementare stiva generica A [14]
-- 7. 28 --
E.Kalisz - Structuri de date
Implementare coada generica A [1]
A. Folosind un vector prelucrat circular, cu santinela
typedef struct
{ size_t maxe, dime; /* nr.maxim elemente,
dimensiune element */
char *v, *sv, /* inceput, sfarsit vector */
*ic, *sc; /* inceput, sfarsit coada */
} TCoadaV, *AQV;

a
maxe dime v sv ic sc
/ / / / p . . . . . . . u / / / / /
-- 7. 29 --
E.Kalisz - Structuri de date
Implementare coada generica A [2]

a maxe dime v sv ic sc
/ / / . . . / /
Coada vida: a->ic == a->sc
- dupa initializare

a maxe dime v sv ic sc
/ / / / / / /
- dupa numar egal de inserari si eliminari
-- 7. 30 --
E.Kalisz - Structuri de date
Implementare coada generica A [3]
/*- macrodefinitii utile -*/
/*- acces la campuri -*/
#define V(a) (((AQV)(a))->v)
#define SV(a) (((AQV)(a))->sv)
#define IC(a) (((AQV)(a))->ic)
#define SC(a) (((AQV)(a))->sc)
#define DIME(a) (((AQV)(a))->dime)
/*- teste si operatii simple -*/
#define DIMDIF(s,d) (DIME(s) != DIME(d))
#define VIDA(a) (IC(a) == SC(a))
#define Avans(a,p) ((p) = ((p)+= DIME(a)) < SV(a)? (p) : V(a))

a
maxe dime v sv ic sc
/ / / / p . . . . . . . u / / / / /
-- 7. 31 --
E.Kalisz - Structuri de date
Implementare coada generica A [4]

a
maxe dime v sv ic sc
/ / / / p . . . . . . . u / / / / /
Spatiu ocupat, exprimat in octeti:
- cazul IC(a) <= SC(a): SC(a)-IC(a)
- cazul IC(a) > SC(a): SC(a)-V(a)+SV(a)-IC(a)

a maxe dime v sv ic sc
. . . . . u / / / / / / / / p . . . . .
#define Ocupat(a)((SC(a)-IC(a))+(IC(a)<=SC(a)?0: SV(a)-V(a)))
-- 7. 32 --
E.Kalisz - Structuri de date
Implementare coada generica A [5]

a
maxe dime v sv ic sc
p . . . . . u /
Coada plina:
- cazul IC(a) == V(a): SC(a)+DIME(a)== SV(a)

a
maxe dime v sv ic sc
. . u / p . . .
- cazul IC(a) > V(a): SC(a)+DIME(a)== IC(a)
#define PLINA(a)((SC(a)+DIME(a))==(IC(a)== V(a)? SV(a):IC(a)))
-- 7. 33 --
E.Kalisz - Structuri de date
Initializare
Implementare coada generica A [6]
void* InitQ(size_t d,...)
/* creeaza coada vida cu elemente de dimensiune d;
este necesar si un al doilea parametru = numar
maxim elemente in coada */
{ AQV a = (AQV)malloc (sizeof (TCoadaV));
va_list ap;
if(!a) return NULL;
/* preia param.2 = nr.max.elemente */
va_start(ap,d);
a->maxe = va_arg(ap,size_t);
va_end(ap);
a->dime = d;

a maxe dime v sv ic sc
/ / / . . . / /
-- 7. 34 --
E.Kalisz - Structuri de date
Initializare
Implementare coada generica A [7]
/* aloca spatiu pentru vector si test esec */
a->v = (char*)calloc(a->maxe+1,d);
if(!a->v) { free(a); return NULL; }
/* actualizeaza adrese din descriptor */
a->sv = a->v + (a->maxe+1) * d;
a->ic = a->sc = a->v;
return (void*)a;
}

a maxe dime v sv ic sc
/ / / . . . / /
-- 7. 35 --
E.Kalisz - Structuri de date
Inserare
Implementare coada generica A [8]
maxe dime v sv ic sc
/ / / / / / / / . . . . . . . u w
ae
w
a
int IntrQ(void* a, void* ae)
/* adauga element la sfarsitul cozii */
{ if (PLINA(a)) return 0;
memcpy(SC(a), ae, DIME(a)); /* copiaza elementul */
Avans(a,SC(a)); /* sfarsitul cozii avanseaza */
return 1;
}
-- 7. 36 --
E.Kalisz - Structuri de date
Extragere
Implementare coada generica A [9]

maxe dime v sv ic sc
/ / / / / / / p . . . . . . . u /
ae
p
a
int ExtrQ(void* a, void* ae)
/* extrage primul element din coada la adresa ae */
{ if (VIDA(a)) return 0;
memcpy(ae, IC(a), DIME(a)); /* copiaza elementul */
Avans(a,IC(a)); /* inceputul cozii avanseaza */
return 1;
}
-- 7. 37 --
E.Kalisz - Structuri de date
Primul element
Implementare coada generica A [10]
maxe dime v sv ic sc
/ / / / / / / / . . . . . . . u w
ae
w
a
int PrimQ(void *a, void *ae) /* copiaza primul
element din coada la adresa ae */
{ if(VIDA(a)) return 0;
memcpy(ae, IC(a), DIME(a));
return 1;
}
-- 7. 38 --
E.Kalisz - Structuri de date
Numar elemente
Implementare coada generica A [12]
size_t NrEQ(void *a)
/* numarul de elemente din coada */
{ return Ocupat(a) / DIME(a); }

a
maxe dime v sv ic sc
/ / / . . . / /
-- 7. 39 --
E.Kalisz - Structuri de date
Reset
Implementare coada generica A [13]
void ResetQ(void *a)
/* transforma coada in coada vida */
{
/* inceput si sfarsit coada = inceput vector */
SC(a) = IC(a) = V(a);
}

a
maxe dime v sv ic sc
/ / / . . . / /
-- 7. 40 --
E.Kalisz - Structuri de date
Distruge coada
Implementare coada generica A [14]
void DistrQ(void *a)
/* elibereaza intregul spatiu ocupat de coada */
{ free(V(*aa));
free(*aa);
*aa = NULL;
}

a
maxe dime v sv ic sc
/ / / . . . / /
-- 7. 41 --
E.Kalisz - Structuri de date
Implementare coada generica A [15]
int MutaQ (void *ad, void *as)
/* muta in destinatie primul element din sursa */
{
if(DIMDIF(as,ad)) return -1; /* dimensiuni diferite */
if(VIDA(as)) return 0; /* sursa vida */
/* nu exista spatiu pentru mutarea in destinatie */
if(PLINA(ad)) return -2;
memcpy(SC(ad), IC(as), DIME(as)); /* muta element */
/* actualizeaza adrese */
Avans(ad,SC(ad));
Avans (as,IC(as));
return 1;
}
-- 7. 42 --
E.Kalisz - Structuri de date
Implementare coada generica A [16]
int ConcatQ(void *ad, void *as)
/* concatenare (muta toate elem.din sursa) */
{ if(DIMDIF(as,ad)) return -1;
if(VIDA(as)) return 0;
if(Liber(ad) < Ocupat(as)) return -2;
for(; IC(as) != SC(as);
Avans(ad,SC(ad)), Avans(as,IC(as)))
memcpy(SC(ad), IC(as), DIME(as));
return 1;
}
-- 7. 43 --
E.Kalisz - Structuri de date
Implementare stiva generica B [1]
B. Folosind o lista
typedef struct celst
{ struct celst *urm; /* adr.urmatoarei celule */
void* info; /* adresa informatie */
} TCelSt, *ACelSt;
typedef struct stiva
{ size_t dime, dimc; /* dim.element,celula */
ACelSt vf; /* adresa celulei din varf */
} TStiva, *ASt;
a dime dimc vf
. . . .
z y p
-- 7. 44 --
E.Kalisz - Structuri de date
#define VF(a) (((ASt)(a))->vf)
#define DIME(a) (((ASt)(a))->dime)
#define DIMC(a) (((ASt)(a))->dimc)
Initializare
a = InitS(sizeof(tip_element));
Implementare stiva generica B [2]

a
dime dimc vf
Stiva vida: VF(a) == NULL
-- 7. 45 --
E.Kalisz - Structuri de date
Implementare stiva generica B [3]
Inserare
ae
z
a dime dimc vf
. . . .
z y p
ae
w
a dime dimc vf
. . . .
w
y p
Extragere
-- 7. 46 --
E.Kalisz - Structuri de date
Implementare coada generica B [4]
B. Folosind o lista deschisa, fara santinela
typedef struct cel /* dimensiune variabila */
{ struct cel * urm;
void* info;
} TCel, *ACel;
typedef struct coada
{ size_t dime, dimc; /* dim.element,celula */
ACel ic, sc; /* adr.prima, ultima celula */
} TCoada, *AQ;
a dime dimc ic sc
. . . .
p q u
-- 7. 47 --
E.Kalisz - Structuri de date
Implementare coada generica B [5]
Coada vida: a->ic == NULL && a->sc == NULL
Inserare

ae
w
a
. . . .

w p

u
dime dimc ic sc

ae p
a
p
dime dimc ic sc
- in coada vida
- in coada nevida
-- 7. 48 --
E.Kalisz - Structuri de date
Implementare coada generica B [6]
Extragere

ae
p
a
. . . .
p

q

u
dime dimc ic sc

ae
x
a
dime dimc ic sc
x
- din coada cu mai
multe elemente
- din coada cu un
singur element
-- 7. 49 --
E.Kalisz - Structuri de date
Aflarea numarului de elemente pare dintr-o coada cu
elemente de tip intreg
int NumarPareCoada(void *acp)
{ void *acx; /* adresa coada auxiliara */
int x, np = 0;
acx = InitQ(DimEQ(acp), MAX);
if (!acx) return -1;
while (PrimQ(acp, &x))
{ if (x % 2 == 0) np++;
MutaQ(acx, acp);
}
ConcatQ(acp, acx);
DistrQ(&acx);
return np;
}
Apel:
npare = NumarPareCoada(a1);
Exemple prelucrari
-- 7. 50 --
E.Kalisz - Structuri de date
Transfer intr-o noua stiva a elementelor mai mici decat
o valoare de referinta, pastrand ordinea relativa a
elementelor.
Exemplu:
sursa | 5, 10, 27, 3, 8, 21, 4 :

mici | 4, 8, 3, 5 : (ordine inversa!)


mari | 21, 27, 10 :

sursa | 10, 27, 21 :


mici | 5, 3, 8, 4 :
Exemple prelucrari
-- 7. 51 --
E.Kalisz - Structuri de date
void* TransferMaiMici(int ref, void* as)
{ void * mici, * mari; /* adrese stive de lucru */
int x; /* valoare element */
/*- initializare stive de lucru -*/
mici = InitS(DimES(as), MAX);
if (!mici) return NULL;
mari = InitS(DimES(as), MAX);
if (!mari){ DistrS(&mici); return NULL; }
/*- transfer din stiva sursa in stivele de lucru -*/
while (Top(as, &x))
MutaS((x < ref ? mici : mari), as);
/* elementele mari raman in stiva sursa */
Rastoarna(as, mari);
DistrS(&mari);/* este vida si nu mai este necesara */
/* stiva elementelor mici -> rezultat */
InvS(mici);
return mici;
}
Exemple prelucrari

Você também pode gostar