Sunteți pe pagina 1din 56

Subiectul 1. Noiuni generale despre liste, stive, cozi, cozi complete.

Subiectul 2. Liste simplu nlnuite. Creare i acces.


Subiectul 3. Liste simplu nlnuite. Inserarea unui nod ntr-o list simplu nlnuit
Subiectul 4. Liste simplu nlnuite. tergerea unui nod dintr-o list simplu nlnuit i tergerea
listei
Subiectul 5. Stive i cozi
Subiectul 6. Liste circulare simplu nlnuite. Creare i acces la un nod.
Subiectul 7. Liste circulare simplu nlnuite. Inserare i tergere nod i list.
Subiectul 8. Liste dublu nlnuite. Creare i acces la nod.
Subiectul 9. Liste dublu nlnuite. Inserare i tergere nod i list.
Subiectul 10. Arbori. noiuni teoretice
Subiectul 11. Arbori. Drumul ntr-un arbore
Subiectul 12. Traversarea arborilor binari. Generaliti i exemple
Subiectul 13. Traversarea arborilor binari. Algoritmi de traversare
Subiectul 14. Reprezentarea arborilor prin arbori binari
Subiectul 15 Parcurgerea grafurilor n adncime
Subiectul 16 Sortarea topologic. Parcurgerea grafurilor n lime
Subiectul 17 Grafuri AND/OR
Subiectul 19 Sortarea prin numrare
Subiectul 20 Sortarea prin inserie
Subiectul 21 Metoda lui Shell
Subiectul 22 Sortarea prin interschimbare
Subiectul 23 Sortarea prin selecie
Subiectul 24 Sortarea prin interclasare
Subiectul25Cutarea ntr-un tabel ordonat
Subiectul 26 Cutarea de tip Fibonacci
Subiectul 27 Cutarea prin interpolare
Subiectul 28 METODA GREEDY
//Subiectul 29 Exemple de aplicare a metodei Greedy
Subiectul 30 Algoritmul Greedy pentru colorarea unui graf
Subiectul 31 ...?
Subiectul 31 Algoritmul lui Kruskal
Subiectul 32Algoritmul lui Prim
Subiectul 1.
Noiuni generale despre liste, stive, cozi, cozi complete.
Este important ca n cele ce urmeaz s se defineasc termeni i noiuni care vor fi n
continuare frecvent utilizate, i anume:
- informaiile coninute ntr-un tabel constau dint-un set de noduri (nregistrri sau
articole); se mai numesc i elemente;
- fiecare nod se compune din unul sau mai multe cuvinte consecutive din memoria
calculatorului, fiind mprite n subpri componente denumite cmpuri;
- n cazul cel mai simplu un nod este un singur cuvnt din memorie i are un singur cmp de
lungime egal cu lungimea acestui cmp ntreg din memorie;
1

- adresa unui nod, denumit i pointerul sau referina acelui nod, reprezint locaia din
memorie a primului cuvnt aparinnd nodului;
- coninutul oricrui cmp al unui nod poate reprezenta numere, caractere alfabetice,
referine la alte noduri sau orice altceva dup necesitile de programare;
- pentru reprezentarea referinei nule se va folosi, n cele ce urmeaz, litera ;
- n memoria calculatorului va fi reprezentat printr-o valoare uor de recunoscut, care
nu poate reprezenta adresa unui nod;
- introducerea de referine ctre alte elemente de date reprezint o idee deosebit de
valoroas pentru programarea calculatoarelor; acesta constituie cheia reprezentrilor complexe;
- la ilustrarea reprezentrii n calculator a nodurilor este deseori convenabil ca referinele
s fie reprezentate prin sgei:

Figura

NCEPU
T

2.1.

Reprezentarea intuitiv a referinelor


- o referin nul poate fi ilustrat ca o punere la pmnt din schemele electrice.
NCEPUT este o variabil tip referin numit i variabil pointer, adic o variabil n cadrul
programului a crei valoare este o referin.
Definiia 2.2.1. O list linear este o colecie de n 0 noduri x(1), x( 2),..., x( n) ale
crei proprieti structurale se reduc n principal la poziiile relative lineare (unidimensionale) ale
acestor noduri;
Dac n 0, x (1) este primul nod, pentru 1 k n nodul k , x( k ) este precedat de nodul
x( k 1) i este urmat de x (k 1); x( n) este ultimul nod.
Principalele operaii care se execut asupra listelor lineare sunt urmtoarele:
- accesul la nodul k din list pentru a examina sau modifica cmpurile sale;
- inserarea unui nod naintea nodului k;
- tergerea nodului k;
- combinarea a dou sau mai multe liste n una singur;
- desprirea unei liste lineare n una sau mai multe liste;
- copierea unei liste lineare;
- determinarea numrului de noduri ntr-o list;
- sortarea nodurilor unei liste ntr-o ordine corespunztoare a coninuturilor
anumitor cmpuri ale nodurilor;
- cutarea n list a nodului cu o valoare particular a unui anumit cmp.
Listele lineare n care inserrile, tergerile i accesul la valori au loc aproape ntotdeauna
la primul sau la ultimul nod sunt foarte frecvent ntlnite, purtnd i denumiri particulare
(speciale).
Definiia 2.2.2. O stiv (stack) este o list linear n care toate inserrile sau tergerile
sunt fcute la unul din capetele listei.

inserar
e
sau
terger
e

nceput

nodul II
nodul III
sfrit
Figura 2.2. Exemplu de stiv
Definiia 2.2.3. O coad (queue) este o list linear pentru care toate inserrile sunt
fcute la unul din capetele listei; toate tergerile (i, de obicei, orice acces) sunt fcute la cellalt
capt.
tergere

fa

inserare

nod 2

nod 3

spate

Figura 2.3. Exemplu de coad


Definiia 2.2.4. O coad complet (cu duble capete) este o list linear pentru care toate
inserrile i tergerile (i, de obicei, orice acces) sunt fcute la ambele capete ale listei.
cel mai din
stnga

nod 2
stnga

nod 3
stnga

inserare
sau
tergere

cel mai din


dreapta

inserare
sau
tergere
Figura 2.4. Exemplu de coad complet.

Subiectul 2.
Liste simplu nlnuite. Creare i acces.
Lista este o mulime finit i ordonat de elemente de acelai tip. Elementele listei se
numesc noduri.
Listele pot fi organizate sub form static, de tablou, caz n care ordinea este implicit dat
de tipul tablou unidimensional, sau cel mai des, sub form de liste dinamice, n care ordinea
nodurilor este stabilit prin pointeri. Nodurile listelor dinamice sunt alocate n memoria heap.
Listele dinamice se numesc liste nlnuite, putnd fi simplu sau dublu nlnuite.
n continuare se vor prezenta principalele operaii asupra listelor simplu nlnuite.
Structura unui nod este urmtoarea:
3

typedef struct tip_nod


{
int cheie;
/* cmp neobligatoriu */
// alte cmpuri de date utile;
struct tip_nod *urm;
/* legtura spre urmtorul nod */
} TIP_NOD;
Modelul listei simplu nlnuite este prezentat n fig. 2.5.

Fig. 2.5. Model de list simplu nlnuit


Pointerii prim i ultim vor fi declarai astfel:
TIP_NOD *prim, *ultim;
1. Crearea unei liste simplu nlnuite
Crearea unei liste simplu nlnuite se va face astfel:
a)

Iniial lista este vid:


prim = 0; ultim = 0;

b)

Se genereaz nodul de introdus:


n=sizeof(TIP_NOD);
p=(TIP_NOD *) malloc(n);
/* rezervare spaiu de memorie n heap*/
/* citire date n nodul de adres p; */

c)

Se fac legturile corespunztoare:


p->urm = 0;
/* nodul este ultimul n list */
if(ultim != 0) ultim->urm = p;
/* lista nu este vid */
else prim = p;
/* nodul p este primul introdus n list */
ultim=p;
4

2. Accesul la un nod al unei liste simplu nlnuite


n funcie de cerine, nodurile listei pot fi accesate secvenial, extrgnd informaia util
din ele. O problem mai deosebit este gsirea unui nod de o cheie dat i apoi extragerea
informaiei din nodul respectiv. Cutarea nodului dup cheie se face liniar, el putnd fi prezent
sau nu n list.
O funcie de cutare a unui nod de cheie key va conine secvena de program de mai
jos; ea returneaz adresa nodului respectiv n caz de gsire sau pointerul NULL n caz contrar:
TIP_NOD *p;
p=prim;
while( p != 0 )
if (p->cheie == key)
{
/* s-a gsit nodul de cheie dat */
/* el are adresa p */
return p;
}
else
p=p->urm;
return 0;
/* nu exist nod de cheie = key */
Subiectul 3.
Liste simplu nlnuite. Inserarea unui nod ntr-o list simplu nlnuit
Nodul de inserat va fi generat dup structura urmtoarea:
typedef struct tip_nod
{
int cheie;
/* cmp neobligatoriu */
// alte cmpuri de date utile;
struct tip_nod *urm;
/* legtura spre urmtorul nod */
} TIP_NOD;
Pointerii prim i ultim vor fi declarai astfel:
TIP_NOD *prim, *ultim;
ca la paragraful 2.2.1.1; se presupune c are pointerul p.
Dac lista este vid, acest nod va fi singur n list:
if (prim == 0)
{
prim=p; ultim=p; p->urm=0;
}
5

Dac lista nu este vid, inserarea se poate face astfel:


a)

naintea primului nod


if(prim != 0)
{
p->urm = prim; prim = p;
}

b)

dup ultimul nod:


if (ultim != 0)
{
p -> urm = 0; ultim -> urm = p; ultim = p;
}

c)

naintea unui nod precizat printr-o cheie key:


c1)
se caut nodul de cheie key:
TIP_NOD *q, *q1;
q1=0; q=prim;
while(q!=0)
{
if(q->cheie==key) break;
q1=q; q=q->urm;
}
c2)

se insereaz nodul de pointer p, fcnd legturile corespunztoare:

if(q!=0)
{/*nodul de cheie key are adresa q */
if (q==prim)
{
p->urm=prim; prim=p;
}
else
{
q1->urm=p; p->urm=q;
}
}
d)

dup un nod precizat printr-o cheie key:


d1)
se caut nodul avnd cheia key:
TIP_NOD *q;
q=prim;
while(q!=0)
{
6

if(q->cheie==key) break;
q=q->urm;
}
d2) se insereaz nodul de adres p, fcnd legturile corespunztoare:
if (q !=)0)
{ /* nodul de cheie key are adresa q */
p -> urm = q -> urm;
q -> urm=p;
if (q == ultim) ultim = p;
}
Subiectul 4.
Liste simplu nlnuite. tergerea unui nod dintr-o list simplu nlnuit i tergerea
listei
Structura unui nod este urmtoarea:
typedef struct tip_nod
{
int cheie;
/* cmp neobligatoriu */
// alte cmpuri de date utile;
struct tip_nod *urm;
/* legtura spre urmtorul nod */
} TIP_NOD;
Pointerii prim i ultim vor fi declarai astfel:
TIP_NOD *prim, *ultim;
1. tergerea unui nod.
La tergerea unui nod se vor avea n vedere urmtoarele probleme: lista poate fi vid, lista
poate conine un singur nod sau lista poate conine mai multe noduri.
De asemenea se poate cere tergerea primului nod, a ultimului nod sau a unui nod dat
printr-o cheie key.
a) tergerea primului nod
TIP_NOD *p;
if(prim!=0)
{
/* lista nu este vid */
p=prim; prim=prim->urm;
elib_nod(p);
/*eliberarea spaiului de memorie */
if(prim==0) ultim=0;
/* lista a devenit vid */
}
7

b) tergerea ultimului nod


TIP_NOD *q, *q1;
q1=0; q=prim;
if(q!=0)
{
/* lista nu este vid */
while(q!=ultim)
{
q1=q; q=q->urm;
}
if(q==prim)
{
prim=0; ultim=0;
}
else
{
q1->urm=0; ultim=q1;
}
elib_nod(q);
}
c) tergerea unui nod de cheie key
TIP_NOD *q, *q1;
/* cutare nod */
q1=0; q=prim;
while (q!=0)
{
if(q->cheie == key) break;
/* s-a gsit nodul */
q1=q; q=q->urm;
}
if(q != 0)
/*exist un nod de cheie key */
if (q == prim)
{
prim=prim_>urm;
elib_nod(q);
/*eliberare spaiu */
if( prim==0) ultim=0;
}
else
{
q1->urm=q->urm;
if(q==ultim) ultim=q1;
elib_nod(q);
/*eliberare spaiu */
}
8

2. tergerea unei liste simplu nlnuite


n acest caz, se terge n mod secvenial fiecare nod:
TIP_NOD *p;
while( prim != 0)
{
p=prim; prim=prim->ultim;
elib_nod(p);
/*eliberare spaiu de memorie */
}
ultim=0;
Subiectul 5. Stive i cozi
Stive.
Stiva este o list simplu nlnuit bazat pe algoritmul LIFO (Last In First Out), adic
ultimul nod introdus este primul scos. Modelul stivei, este prezentat n fig.2.6.

Fig. 2.6. Model de stiv


Fiind o structur particular a unei liste simplu nlnuite, operaiile principale asupra unei
stive sunt:
- push - pune un element pe stiv; funcia se realizeaz prin inserarea unui nod naintea
primului;
if(prim != 0)
{
p->urm = prim; prim = p;
}
- pop - scoate elementul din vrful stivei; funcia se realizeaz prin tergerea primului
nod;
TIP_NOD *p;
if(prim!=0)
{
/* lista nu este vid */
p=prim; prim=prim->urm;
elib_nod(p);
/*eliberarea spaiului de memorie */
9

if(prim==0) ultim=0;
/* lista a devenit vid */
}
-

clear - tergerea stivei; funcia se realizeaz conform


TIP_NOD *p;
while( prim != 0)
{
p=prim; prim=prim->ultim;
elib_nod(p);
/*eliberare spaiu de memorie */
}
ultim=0;
n concluzie, accesul la o stiv se face numai pe la un capt al su.
Cozi

Coada este o list simplu nlnuit, bazat pe algoritmul FIFO (First In First Out), adic
primul element introdus este primul scos. Modelul cozii care se are n vedere n consideraiile
urmtoare, este prezentat n fig.2.7.

Se introduce
un element
nou

Fig.2.7. Model de coad


Deci coada are dou capete, pe la unul se introduce un element, iar de la celalalt capt se
scoate un element.
Operaiile importante sunt:
- introducerea unui element n coad - funcia se realizeaz prin inserarea dup ultimul
nod,
if (ultim != 0)
{
p -> urm = 0; ultim -> urm = p; ultim = p;
}
- scoaterea unui element din coad funcia se realizeaz prin tergerea primului nod,
TIP_NOD *p;
if(prim!=0)
{
/* lista nu este vid */
10

p=prim; prim=prim->urm;
elib_nod(p);
/*eliberarea spaiului de memorie */
if(prim==0) ultim=0;
/* lista a devenit vid */
}
tergerea cozii funcia se realizeaz conform
TIP_NOD *p;
while( prim != 0)
{
p=prim; prim=prim->ultim;
elib_nod(p);
/*eliberare spaiu de memorie */
}
ultim=0;
Subiectul 6.
Liste circulare simplu nlnuite. Creare i acces la un nod.
Lista circular simplu nlnuit este lista simplu nlnuit a crei ultim element este legat
de primul element; adic ultim -> urm = prim.
n cadrul listei circulare simplu nlnuite nu exist capete. Pentru gestionarea ei se va folosi
un pointer ptr_nod, care adreseaz un nod oarecare al listei, mai precis ultimul introdus
(fig.2.8).
Ca i la lista simplu nlnuit, principalele operaii sunt:

Fig. 2.8.Modelul listei circulare simplu nlnuite

crearea;
accesul la un nod;
inserarea unui nod;
tergerea unui nod,
tergerea listei.

Structura unui nod este urmtoarea:


typedef struct tip_nod
{
11

int cheie;
/* nu este obligatoriu acest cmp */
/*cmpuri;*/
struct tip_nod *urm;
} TIP_NOD;
Crearea listei circulare simplu nlnuite
Iniial lista este vid:
ptr_nod = 0;
Introducerea n list a cte unui nod se va face astfel:
/* crearea nodului */
n = sizeof(TIP_NOD); /* dimensiunea nodului */
p = (TIP_NOD *)malloc(n); /* rezervarea memorie n heap
*/
citire date n nod la adresa p;
if (ptr_nod = = 0)
{ /* lista este vid */
ptr_nod = p;
ptr_nod -> urm = p;
}
else
{ /* lista nu este vid */
p -> urm = ptr_nod -> urm;
ptr_nod -> urm = p;
ptr_nod=p;
/* ptr_nod pointeaz la
ultimul nod inserat */
}
Accesul la un nod
Nodurile pot fi accesate secvenial plecnd de la nodul de pointer ptr_nod:
p=ptr_nod;
if(p! = 0)/* lista nu este vid */
do
{
acceseaaz nodul i preia informaia;
p = p -> urm;
}
while (p! = ptr_nod);
sau cutnd un nod de cheie dat key; n acest caz o funcie care va returna pointerul la nodul
gsit va conine urmtoarea secven de program:
p = ptr_nod;
if (p! = 0)
do

/* lista nu este vid */


12

{
if ( p -> cheie == key)
{
/* s-a gsit nodul */
/* nodul are adresa p */
return p;
}
p = p -> urm;
}
while (p! = ptr_nod);
return 0;
Subiectul 7.
Liste circulare simplu nlnuite. Inserare i tergere nod i list.
Inserarea unui nod
Se pun urmtoarele probleme:
- inserarea naintea unui nod de cheie dat;
- inserarea dup un nod de cheie dat.
n ambele cazuri se caut nodul de cheie dat avnd adresa q; dac exist un astfel de nod,
se creeaz nodul de inserat de adres p i se fac legturile corespunztoare.
a) Inserarea naintea unui nod de cheie dat
- se caut nodul de cheie dat (adresa sa va fi q):
TIP_NOD *p,*q,*q1;
q = ptr_nod;
do
{
q1 = q; q = q -> urm;
if(q -> cheie == key ) break;
/* s-a gsit nodul */
}
while (q! = ptr_nod);
- se insereaz nodul de adres p;
if (q -> cheie == key)
{
q1 -> urm = p; p -> urm = q;
}
b) Inserarea dup un nod de cheie dat
- se caut nodul de cheie dat:
13

TIP_NOD *p,*q;
q = ptr_nod;
do
{
if (q -> cheie == key ) break;
q = q -> urm;
}
while(q!=ptr_nod);
- se insereaz nodul de adres p:
if (q -> cheie == key)
{
p -> urm =q -> urm;
q -> urm = p;
}
tergerea unui nod de cheie dat
tergerea unui nod de cheie dat key se va face astfel:
- se caut nodul de cheie dat:
q = ptr_nod;
do
{
q1 = q; q = q -> urm;
if (q -> cheie == key ) break;
/* s-a gsit nodul */
}
while (q! = ptr_nod);
- se terge nodul, cu meniunea c dac se terge nodul de pointer ptr_nod,
atunci ptr_nod va pointa spre nodul precedent q1:
if (q-> cheie == key)
{
if (q==q -> urm) ptr_nod==0;
/* lista a devenit vid */
else
{
q1 -> urm = q -> urm;
if (q == ptr_nod) ptr_nod = q1;
}
elib_nod(q);
}

14

tergerea listei
tergerea listei circulare simplu nlnuite se va face astfel:
p = ptr_nod;
do
{
p1 =p; p = p -> urm;
elib_nod(p1);
}
while (p! = ptr_nod);
ptr_nod = 0;
Subiectul 8.
Liste dublu nlnuite. Creare i acces la nod.
Lista dublu nlnuit este lista dinamic ntre nodurile creia s-a definit o dubl relaie:
de succesor si de predecesor. Modelul listei dublu nlnuite, pentru care se vor da explicaiile n
continuare, este prezentat n figura 2.10.
Figura 2.10. Modelul listei circulare dublu nlnuite

Tipul unui nod dintr-o list dublu nlnuit este definit astfel:
typedef struct tip_nod
{
cheie; /* nu este obligatoriu */
date;
struct tip_nod *urm;
/* adresa urmtorului nod */
struct tip_nod * prec;
/* adresa precedentului nod */
} TIP_NOD;
Ca i la lista simplu nlnuit, principalele operaii sunt:
crearea;
accesul la un nod;
inserarea unui nod;
tergerea unui nod,
15

tergerea listei.
Lista dublu nlnuit va fi gestionat prin pointerii prim i ultim:
TIP_NOD *prim, *ultim;
prim -> prec = 0;
ultim -> urm = 0;
Crearea unei liste dublu nlnuite
Iniial lista este vid:
prim = 0; ultim = 0;
Dup alocarea de memorie i citirea datelor n nod, introducerea nodului de pointer n
list se va face astfel:
if(prim= =0)
{ /* este primul nod n list */
prim = p; ultim = p;
p -> urm = 0; p -> prec = 0;
}
else
{
/* lista nu este vid */
ultim -> urm = p; p -> prec = ultim;
p -> urm = 0; p -> prec = ultim;
ultim = p;
}
Accesul la un nod
Accesul la un nod se poate face:
- secvenial nainte (de la prim spre ultim):
p = prim;
while (p != 0)
{
vizitare nod de pointer p;
p = p -> urm;
}
- secvenial napoi ( de la ultim spre prim):
p = ultim;
while (p != 0)
{
vizitare nod de pointer p;
p = p -> prec;
}
16

- pe baza unei chei; cutarea unui nod de cheie dat key se va face identic ca la lista
simplu nlnuit
TIP_NOD *p;
p=prim;
while( p != 0 )
if (p->cheie == key)
{
/* s-a gsit nodul de cheie dat el are adresa p */
return p;
}
else
p=p->urm;
return 0; /* nu exist nod de cheie = key */
Subiectul 9.
Liste dublu nlnuite. Inserare i tergere nod i list.
Inserarea unui nod ntr-o list dublu nlnuit se poate face astfel:
- naintea primului nod:
if (prim == 0)
{ /* lista este vid */
prim = p; ultim = p;
p -> urm = 0; p -> prec = 0;
}
else
{ /* lista nu este vid /*
p -> urm =prim; p -> prec = 0;
prim -> prec = p; prim = p;
}
- dup ultimul nod:
if (prim == 0)
{ /* lista este vid */
prim = p; ultim = p;
p -> urm = 0; p -> prec = 0;
}
else
{ /* lista nu este vid /*
p -> urm =0; p -> prec = ultim;
utim -> urm = p;
ultim = p;
}
- naintea unui nod de cheie dat key: dup cutarea nodului de cheie key,
presupunnd c acesta exist i are adresa q, nodul de adres p va fi inserat astfel:
p -> prec = q -> prec; p -> urm = q;
if (q -> prec != 0) q -> prec -> urm = p;
q -> prec = p;
if (q == prim) prim = p;
17

- dup un nod de cheie dat key: dup cutarea nodului de cheie key,
presupunnd c acesta exist i are adresa q, nodul de adres p va fi inserat astfel:
p -> prec = q; p -> urm = q -> urm;
if (q -> urm != 0) q -> urm -> prec = p;
q -> urm = p;
if (ultim == q) ultim = p;
tergerea unui nod
Exist urmtoarele cazuri de tergere a unui nod din list:
a) tergerea primului nod; acest lucru se poate face cu secvena de program:
p = prim;
prim = prim -> urm;
/* se consider list nevid */
elib_nod(p); /* eliberarea nodului */
if (prim == 0) ultim = 0;
/* lista a devenit vid */
else prim -> prec = 0;
b) tergerea ultimului nod:
p = ultim;
ultim = ultim -> prec;
/* se consider c lista nu este vid */
if (ultim == 0) prim = 0;
/* lista a devenit vid */
else ultim -> urm = 0;
elib_nod(p); /* tergerea nodului */
c) tergerea unui nod precizat printr-o cheie key. Presupunem c nodul de
cheie key exist i are adresa p (rezult din cutarea sa):
if ((prim == p) && (ultim = =p))
{ /* lista are un singur nod */
prim = 0;ultim = 0;
/*lista devine vid*/
elib_nod(p);/*tergere nod*
}
else if(p == prim)
{ /* se terge primul nod */
prim = prim -> urm; prim -> prec =0;
elib_nod(p);
}
else if (p == ultim)
{ /* se terge ultimul nod */
ultim = ultim -> prec;
ultim -> urm = 0;
elib_nod(p)
}
else
{/*nodul de ters este diferit de
capete */
p -> urm -> prec = p -> prec;
18

p -> prec -> urm = p -> urm;


elib_nod(p);
}
tergerea listei
tergerea ntregii liste se realizeaz tergnd nod cu nod astfel:
TIP_NOD *p;
while (prim != 0)
{
p = prim; prim = prim -> urm;
elib_nod(p);
}
ultim = 0;
Subiectul 10.
ARBORI. NOIUNI TEORETICE
Structurile arborescente sunt cele mai importante structuri nelineare ce intervin n
algoritmii de prelucrare.
Definiia 4.1.1. Un arbore este o mulime TT de noduri n care:
a) unul din noduri (de obicei, notat T) se numete tulpin (rdcina) i are o destinaie
special;
b) restul nodurilor se mpart ntr-un numr m N , m 0 de clase disjuncte, iar fiecare
asemenea clas este un arbore.
Observaii:
1. Aceast definiie este recursiv, adic s-a definit un arbore n funcie de un arbore.
2. Aici nu se pune problema de circularitate, deoarece arborii cu un singur nod vor consta
numai din tulpin.
3. Definiia recursiv pare cea mai potrivit, deoarece recursivitatea reprezint o
caracteristic normal a structurilor arborescente.
Definiia 4.1.2. Numrul ramurilor aparinnd unui nod reprezint gradul acelui nod.
Definiia 4.1.3. Un nod de gradul 0 se numete nod terminal sau frunz.
Definiia 4.1.4. Un nod neterminal se numete nod de ramificare.
Definia 4.1.5. Nivelul unui nod n raport cu tulpina (T) se definete prin convenia c
tulpina are nivelul 1, iar celelalte noduri au nivelele cu 1 mai mari dect nivelul lor n raport cu
subarborele tulpinei T j , care le conine.
Fie un drum de la x la y. Exist un drum simplu de la x la y. S reamintim c dac G este
un graf cu

n0

vrfuri i dac x i y sunt vrfuri n G, se spune c

drum de lungime n de la x la y, dac

y xn .
Drumul este simplu dac

x x0 , xk

x0 , x1 ,..., xn1

este adiacentul lui

sunt distincte.

19

x , x ,..., x

xk 1

pentru

este un

0k n

A
C

nivelul 1
nivelul 2

F
G

nivelul 3

nivelul 4

Figura 4.1 Exemplu de arbore


Din punct de vedere al echivalenei a doi arbori este de mare importan caracterul
ordonat sau neordonat al celor doi arbori.
Astfel, arborii din figura 4.2 sunt echivaleni n cazul n care A1 i A2 sunt neordonai i
nu sunt echivaleni n cazul n care cei doi arbori sunt ordonai.

A1

A2

Figura 4.2 Arbori echivaleni sau nu


O deosebit importan o au arborii ordonai de ordinul doi, denumii arbori binari.
EXEMPLE DE UTILIZRI ALE ARBORILOR
a) Formulele algebrice constituie un exemplu de structur arborescent. Astfel, formulelor
c e

f
d

a b

i (a b c) d

li se pot ascocia arborii reprezentai mai jos:

e
f

(1)

20

/
d

Figura 4.3 Arbori asociai formulelor (1)


Subiectul 11.
ARBORI. DRUMUL NTR-UN ARBORE
Definiia 4.4.1. Prin drum ntr-un arbore de la nodul p la nodul q vom nelege o
succesiune de sgei care au pe p ca domeniu al primei sgei i pe q codomeniu al ultimei
sgei a succesiunii.
Fiind dat un arbore a i nodurile p i q n acest arbore, un drum de la p la q se poate
construi dup urmtorul algoritm:
Algoritmul 4.4.1:
Pasul P1:

Fie

a1 ,..., am

subarborii arborelui care are nodul p drept rdcin. Atunci

q este un nod ntr-unul dintre arborii

a1 ,..., am

sau q nu aparine nici unuia dintre aceti arbori.

n acest ultim caz nu exist nici un drum de la p la q n arborele dat. n primul caz, fie
subarborele care conine nodul q.
Pasul P2:

Dac q este rdcin a arborelui

Dac q nu este rdcin a arborelui

ai , atunci fie p i

ai j .

ai1 ,..., ain

p q.

subarborii lui

ai

ai j . Dac q este rdcina lui ai j , atunci

p pi q .

Dac q nu este rdcina lui


subarborii lui

atunci drumul cutat este

rdcina lui i

. Nodul q se gsete ntr-unul din aceti arbori, fie el


drumul cutat este

ai ,

ai

ai j , atunci fie pi j rdcina lui ai j , i ai j ,..., ai j


1
n

Nodul q este o rdcin sau un nod diferit de rdcin ntr-unul din aceti

arbori.
Pasul P3:
Dup un numr finit de pai P1 i P2, avnd n vedere c arborele este o mulime
finit de puncte, se ajunge la situaia n care q este rdcina unui subarbore i atunci drumul de la
p la q este

p p1 pi j pi j L q .
k

Observaie.
Din algoritmul de construire a drumului de la nodul p la nodul q n arborele a rezult c
ntre cele dou noduri p i q ale unui arbore a exist cel mult un drum n subarborele respectiv.
21

Lungimea drumului, precum i nodurile lui p pot fi deduse cu ajutorul algoritmului matriceal,
asociind fiecrui arc lungimea 1.
Legenda variabilelor folosite n pseudocodul corespunztor algoritmului:
a = arborele n care se caut drumul;
p,q = cele dou noduri;
rad = nodul pentru care se determin subarborii;
drum[i] = ir care conine nodurile ce compun drumul;
nrnod = numrul de noduri ale drumului;
nod[i] = subarborele i al nodului rad;
T(nod[i]) = nodul rdcin al subarborelui i;
S(nod[i]) = mulimea tuturor nodurilor subarborelui i.
Pseudocodul corespunztor algoritmului precedent este urmtorul:
* citete

a, p, q;
rad = p;
nrnod = 1;
drum[nrnod] = p;
repet
*determin nod[1],,nod[m];
indice = 0;
pentru i = 1,m execut
dac q S (nod[i ]) atunci
indice = i

dac indice = 0 atunci


* tiprte drum inexistent;

nrnod = nrnod + 1;
drum[nrnod] = T(nod[indice]);
rad = T(nod[indice]);
pn cnd q = rad

* scrie drum[i], i = 1, nrnod;

sfrit.
Subiectul 12.
Traversarea arborilor binari. Generaliti i exemple
Definiia 4.5.1. Un arbore binar poate fi definit ca fiind o mulime finit de noduri care
este fie vid, fie este format dintr-o tulpin (rdcin) i doi arbori binari.
Aceast definiie sugereaz o cale natural de a reprezenta arborii binari n codul
calculatoarelor.
22

Pot exista dou referine LLINK i RLINK n cadrul fiecrui nod i o variabil de tip
referin T care este un pointer de arbore. Dac un arbore este vid, atunci T ; n caz
contrar, T este adresa tulpinei arborelui, iar LLINK(T) i RLINK(T) sunt pointeri la arborele din
stnga, respectiv din dreapta tulpinei.
Aceste reguli definesc recursiv reprezentarea n memorie a oricrui arbore binar.
Traversarea unui arbore binar reprezint o metod de a examina nodurile unui arbore n
mod sistematic, astfel nct fiecare nod s fie vizitat o singur dat.
Exemplu:

A
C

B
D

--

----Figura 4.4 Reprezentarea unui arbore binar

--

F
--

Observaie. O traversare complet a arborelui va conduce la o aranjare linear a nodurilor.


Se pot folosi trei ci principale de traversare a arborilor binari:
n preordine denumit TSD;
n inordine denumit STD;
n postordine denumit SDT.
Traversarea n preordine:
se viziteaz tulpina;
se viziteaz subarborele din stnga;
se viziteaz subarborele din dreapta.
Traversarea n inordine:
se traverseaz subarborele din stnga;
se viziteaz tulpina;
se traverseaz subarborele din dreapta.
Traversarea n postordine:
se traverseaz subarborele din stnga;
se traverseaz subarborele din dreapta;
se viziteaz tulpina.
Dac se aplic cele trei ci de traversare a arborelui reprezentat anterior, se obine:
pentru traversare n preordine: A B C D E F;
pentru traversare n inordine: D B A E C F;
pentru traversare n postordine: D B E F C A.
Regula mnemonic presupune folosirea notaiilor cu paranteze n reprezentarea arborilor.
Fie arborele urmtor:

A
23

Figura 4.5 Un exemplu de arbore folosit pentru exemplificarea unei traversri


Folosim urmtoarea notaie pentru a exprima structuri de arbori folosind paranteze n
paranteze:
(A (B, C(K)), D ( E (H), F (J), G)).
n acest caz dac se efectueaz o traversare n preordine, se vor vizita nodurile n
ordinea lor natural, nlturnd parantezele i virgulele: A B C K D E H F J G.
Fie acum arborele binar din figura 4.6.

/
e

Figura 4.6. Arbore binar


n notaia cu paranteze, acest arbore binar poate fi reprezentat astfel:
*((*(a, b), c), (d , /(e, f ))) .
* *a bc-d /ef .
Traversare n preordine:
Traversare n postordine:
- se scrie reprezentarea anterioar astfel: (((a, b)*, c), (d , (e, f ) /) )*
i se obine: a b * c + d e f / - *
Traversare n inordine:
a * b + c * d e / f.
Subiectul 13.
Traversarea arborilor binari. Algoritmi de traversare
Algoritmul 4.5.3: Travesarea n inordine a unui arbore binar.
Fie T un pointer spre un arbore binar. Algoritmul urmtor realizeaz parcurgerea tuturor
nodurilor arborelui binar n inordine, folosind o stiv A.
24

Pasul 1

Pasul 2
Pasul 3

Pasul 4:

Pasul 5

(iniializare):
A (stabilire A vid)
P T.
(testeaz dac P ):
Dac P treci la Pasul 4 altfel treci la Pasul 3.
( P A ):
Se stabilete:
P A (se insereaz nodul P n stiva A)
LLINK(P) P
i se revine la Pasul 2.
Dac stiva este vid ( A ) atunci STOP.
Dac nu, se stabilete:
A P (nodul din vrful stivei trece n P).
(vizitarea lui P):
Se viziteaz NOD(P)
Se stabilete
RLINK(P) P
i se revine la Pasul 2.

Pseudocodul algorirmului 4.5.3 este:


codsf 0; va 1; A(va
) 1; P
T;
repet
dac P 1 atunci
dac A(va ) 1 atunci

codsf 1

altfel
*extrage (P,A);
*viziteaz (P);
P RLINK(P);

altfel
*insereaz (P,A);
P LLINK(P);

pn cnd codsf 1 ;

sfrit.
Traversarea unui arbore binar n preordine
Pentru a realiza un algoritm de treversare a unui arbore binar n preordine, se va face
urmtoarea modificare n algoritmul anterior: vizitarea nodului P se va face ntre paii P2 i P3,
i nu ntre paii P4 i P2.
25

Astfel, algoritmul scris n pseudocod pentru traversarea arborilor binari n preordine arat
astfel:

codsf 0;
va 1;
A(va) 1;
P T;
repet
dac

P 1 atunci
dac A(va ) 1 atunci
codsf 1
altfel

*extrage (P, A);


P RLINK(P);

altfel

pn cnd

sfrit.

*insereaz (P, A);


*viziteaz (P);
P LLINK(P);

codsf 1 ;

Legenda variabilelor folosite n cei doi algoritmi este urmtoarea:


- codsf = variabila care indic terminarea procesului de parcurgere, atunci cnd are
valoarea 1;
- va = vrful stivei A;
- A = stiva (simulat printr+un vector);
- P = variabila de lucru, care face referirea la nodul curent;
- T = variabila care reprezint un pointer la rdcina arborelui.
O valoare -1 n stiv sau ntr-o alt variabil semnific faptul c stiva este vid,
respectiv arborele care are ca pointer variabila cu valoarea -1 este vid.
Subiectul 14.
REPREZENTAREA ARBORILOR PRIN ARBORI BINARi
Diferenele dintre arbori i arborii binari sunt:
1) un arbore nu este niciodat vid, adic el are cel puin un nod; fiecare nod al unui arbore
poate avea 0, 1, .... , n fii;
2) un arbore binar poate fi vid i fiecare nod al su poate avea 0, 1 sau 2 fii; se face
distincie ntre un fiu din stnga i un fiu din dreapta.
Se reamintete c o pdure reprezint o mulime ordonat de zero sau mai muli arbori.
26

Subarborii existeni imediat sub un nod oarecare al unui arbore formeaz un arbore.
Exist o cale naural de reprezentare a unei pduri ca un arbore binar; arborele binar se
obine prin legarea mpreun a fiilor fiecrei familii i se nltur legturile verticale, cu excepia
legturii de la tat la primul su fiu.
De exemplu, fie pdurea:

A
C

Figura 4.7 Exemplu de pdure


Conform regulii de mai sus, arborele binar corespunztor este:

D
C

Figura 4.8 Arbore binar corespunztor pdurii anterioare


Transformarea de mai sus este foarte important; ea poart denumirea de coresponden
natural ntre pduri i arbori binari.
27

Prin nclinarea diagramei de mai sus cu 45 0 se obine:

Figura 4.9 Arbore binar nclinat


Subiectul 15
Parcurgerea grafurilor n adncime
Fie G = <V, M> un graf orientat sau neorientat, ale crui vrfuri dorim s le
consultm. Presupunem c avem posibilitatea s marcm vrfurile deja vizitate n tabloul global
marca. Iniial, nici un vrf nu este marcat.
Pentru a efectua o parcurgere n adncime, alegem un vrf oarecare, vV, ca punct de
plecare i l marcm. Dac exist un vrf w adiacent lui v (adic, dac exist muchia (v,w) n
graful orientat G, sau muchia {v,w} n graful neorientat) care nu a fost vizitat, alegem vrful w
ca noul punct de plecare i apelm recursiv procedura de parcurgere n adncime. La ntoarcerea
din apelul recursiv, dac exist un alt vrf adiacent lui v care nu a fost vizitat, apelm din nou
procedura etc. Cnd toate vrfurile adiacente lui v au fost marcate, se ncheie consultarea
nceput n v. Dac au rmas vrfuri n V care nu au fost vizitate, alegem unul din aceste vrfuri
i apelm procedura de parcurgere. Continum astfel, pn cnd toate vrfurile din V au fost
marcate. Iat algoritmul:
procedure parcurge(G)
for fiecare vV do marca[v] nevizitat
for fiecare vV do
28

if marca[v]= nevizitat then ad(v)


procedure ad(v)
{virful v nu a fost vizitat}
marca[v] nevizitat
for fiecare virf w adiacent lui v do
if marca[w]= nevizitat then ad(w)
Acest mod de parcurgere se numete n adncime, deoarece ncearc s iniieze ct mai
multe apeluri recursive nainte de a se ntoarce dintr-un apel. Parcurgerea n adncime a fost
formulat cu mult timp n urm, ca o tehnic de explorare a unui labirint. O persoan care caut
ceva ntr-un labirint i aplic aceasta tehnic are avantajul c urmtorul loc n care caut este
mereu foarte aproape.
1

(a)
(b)
Figura 9.1 Un graf neorientat i unul din arborii si pariali
Pentru graful din figura 9.1(a), presupunnd c pornim din vrful 1 i c vizitm vecinii
unui vrf n ordine numeric, parcurgerea vrfurilor n adncime se face n ordinea: 1, 2, 3, 6, 5,
4, 7, 8.
Desigur, parcurgerea n adncime a unui graf nu este unic; ea depinde att de alegerea
vrfului iniial, ct i de ordinea de vizitare a vrfurilor adiacente. Ct timp este necesar pentru a
parcurge un graf cu n vrfuri i m muchii?
Deoarece fiecare vrf este vizitat exact o dat, avem n apeluri ale procedurii ad. n
procedura ad, cnd vizitm un vrf, testm marcajul fiecrui vecin al su. Dac reprezentm
graful prin liste de adiacen, adic prin ataarea la fiecare vrf a listei de vrfuri adiacente lui,
atunci numrul total al acestor testri este: m, dac graful este orientat, i 2m, dac graful este
neorientat. Algoritmul necesit un timp n (n) pentru apelurile procedurii ad i un timp n
(m) pentru inspectarea mrcilor. Timpul de execuie este deci n (max(m,n))=(m+n).
Dac reprezentm graful printr-o matrice de adiacen, se obine un timp de execuie n
2
(n ).
Parcurgerea n adncime a unui graf G, neorientat i conex, asociaz lui G un arbore
parial. Muchiile arborelui corespund muchiilor parcurse n G, iar vrful ales ca punct de plecare
devine rdcina arborelui. Pentru graful din figura 9.1(a), un astfel de arbore este reprezentat n
figura 9.1(b) prin muchiile continue; muchiile din G care nu corespund unor muchii ale
arborelui sunt ntrerupte. Dac graful G nu este conex, atunci parcurgerea n adncime asociaz
lui G o pdure de arbori, cte unul pentru fiecare component conex a lui G.
Dac dorim s i marcm numeric vrfurile n ordinea parcurgerii lor, adugm n
procedura ad, la nceput:
29

num
num + 1
preord[v] num
unde num este o variabil global iniializat cu zero, iar preord[1,..,n] este un tablou
care va conine n final ordinea de parcurgere a vfurilor. Pentru parcurgerea din exemplul
precedent, acest tablou devine:
1

Subiectul 16
Sortarea topologic. Parcurgerea grafurilor n lime
n aceast seciune, vom arta cum putem aplica parcurgerea n adncime a unui graf, ntrun procedeu de sortare esenial diferit fa de sortrile ntlnite pn acum. S presupunem c
reprezentm diferitele stagii ale unui proiect complex printr-un graf orientat aciclic: vrfurile sunt
strile posibile ale proiectului, iar muchiile corespund activitilor care se cer efectuate pentru a
trece de la o stare la alta.
Figura 9.2 d un exemplu al acestui mod de reprezentare. O sortare topologic a vrfurilor
unui graf orientat aciclic este o operaie de ordonare liniar a vrfurilor, astfel nct, dac exist o
muchie (i,j), atunci i apare naintea lui j n aceast ordonare.
C
preparat
cafea
A
trezire

B
duul

but
cafea
E
mbrcare

D
plecare

Figura 9.2 Un graf orientat aciclic


Pentru graful din figura 9.2, o sortare topologic este A,B,C,E,D,F, iar o alta este
A,B,E,C,D,F. n schimb, secvena A,B,C,D,E,F nu este n ordine topologic.
Dac adugm la sfritul procedurii ad linia:
write v
atunci procedura de parcurgere n adncime va afia vrfurile n ordine topologic invers. Pentru
a nelege de ce se ntmpl acest lucru, s observm c vrful v este afiat dup ce toate vrfurile
ctre care exist o muchie din v au fost deja afiate.
Parcurgerea grafurilor n lime
Procedura de parcurgere n adncime, atunci cnd se ajunge la un vrf v oarecare,
exploreaz prima dat un vrf w adiacent lui v, apoi un vrf adiacent lui w etc.
Pentru a efectua o parcurgere n lime a unui graf (orientat sau neorientat), aplicm
urmtorul principiu: atunci cnd ajungem ntr-un vrf oarecare v nevizitat, l marcm i vizitm
apoi toate vrfurile nevizitate adiacente lui v, apoi toate vfurile nevizitate adiacente vrfurilor
30

adiacente lui v etc. Spre deosebire de parcurgerea n adncime, parcurgerea n lime nu este n
mod natural recursiv.
Pentru a putea compara aceste dou tehnici de parcurgere, vom da pentru nceput o
versiune nerecursiv pentru procedura ad. Versiunea se bazeaz pe utilizarea unei stive.
Presupunem c avem funcia ftop care returneaz ultimul vrf inserat n stiv, fr s l tearg.
Presupunem date i funciile push (care adaug nodul v n stiva S) i pop (care terge ultimul
nod din stiv i l returneaz).
procedure iterad(v)
S stiva vida
marca[v] vizitat
push(v,S)
while S nu este vida do
while exista un varf w adiacent lui ftop(S)
astfel incat marca[w] = nevizitat do
marca[w] vizitat
push(w,S)
pop(S)
Pentru parcurgerea n lime, vom utiliza o coad i funciile insert-queue (adaug
nodul v n capul cozii C), delete-queue (terge nodul din coada listei i l returneaz).
Iat acum algoritmul de parcurgere n lime:
procedure lat(v)
C
coada vida
marca[v] vizitat
insert-queue(v,C)
while C nu este vida do
u delete-queue(C)
for fiecare vrf w adiacent lui u do
if marca[w] = nevizitat then
marca[w]
vizitat
insert-queue(w, C)
Procedurile iterad i lat trebuie apelate din procedura:
procedure parcurge(G)
for fiecare vV do marca[v] nevizitat
for fiecare vV do
if marca[v]=nevizitat then
{iterad sau lat}(v)
De exemplu, pentru graful din figura 9.1, ordinea de parcurgere n lime a vrfurilor este:
1,2,3,4,5,6,7,8.
Ca i n cazul parcurgerii n adncime, parcurgerea n lime a unui graf G conex asociaz
lui G un arbore parial. Dac G nu este conex, atunci obinem o pdure de arbori, cte unul pentru
fiecare component conex.
Analiza eficienei algoritmului de parcurgere n lime se face la fel ca pentru parcurgerea
n adncime. Pentru a parcurge un graf cu n vrfuri i m muchii timpul este n:
i)
(m+n), dac reprezentm graful prin liste de adiacen;
ii)
(n2), dac reprezentm graful printr-o matrice de adiacen.
Parcurgerea n lime este folosit de obicei atunci cnd se exploareaz parial anumite
grafuri infinite, sau cnd se caut cel mai scurt drum dintre dou vrfuri.
31

Subiectul 17
Grafuri AND/OR
Multe probleme se pot descompune ntr-o serie de subprobleme, astfel nct rezolvarea
tuturor acestor subprobleme, sau a unora din ele, s duc la rezolvarea problemei iniiale.
Descompunerea unei probleme complexe, n mod recursiv, n subprobleme mai simple poate fi
reprezentat printr-un graf orientat. Aceast descompunere se numete reducerea problemei i
este folosit n demonstrarea automat, integrarea simbolic i, n general, n inteligena
artificial. ntr-un graf orientat de acest tip vom permite unui vrf oarecare neterminal v dou
alternative.
Vrful v este de tip AND dac reprezint o problem care este rezolvat doar dac toate
subproblemele reprezentate de vrfurile adiacente lui v sunt rezolvate. Vrful v este de tip OR
dac reprezinta o problem care este rezolvat doar dac cel puin o subproblem reprezentat de
vrfurile adiacente lui v este rezolvat. Un astfel de graf este de tip AND/OR.
De exemplu, arborele AND/OR din figura 9.5 reprezint reducerea problemei A. Vrfurile
terminale reprezint probleme primitive, marcate ca rezolvabile (vrfurile albe), sau
nerezolvabile (vrfurile galbene). Vrfurile neterminale reprezint probleme despre care nu se
tie a priori dac sunt rezolvabile sau nerezolvabile.

A
a

C
E

D
F

Figura 9.5 Un arbore AND/OR


Vrful A este un vrf AND (marcm aceasta prin unirea muchiilor care pleac din A),
vrfurile C i D sunt vrfuri OR. S presupunem acum c dorim s aflm dac problema A este
rezolvabil. Deducem succesiv c problemele C, D i A sunt rezolvabile.
ntr-un arbore oarecare AND/OR, urmtorul algoritm determin dac problema
reprezentat de un vrf oarecare u este rezolvabil sau nu. Un apel sol(u) are ca efect
parcurgerea n postordine a subarborelui cu rdcina n u i returnarea valorii true, dac i
numai dac problema este rezolvabil.
function sol(v)
case
v este terminal:

if v este rezolvabil
32

v este un virf AND:

v este un virf OR:

then return true


else return false
for fiecare virf w
adiacent lui v do
if not sol(w)
then return false
return true
for fiecare virf w
adiacent lui v do
if sol(w)
then return true
return false

Dac n timpul explorrii se poate deduce c un vrf este rezolvabil sau nerezolvabil, se
abandoneaz explorarea descendenilor si. Printr-o modificare simpl, algoritmul sol poate afia
strategia de rezolvare a problemei reprezentate de u, adic subproblemele rezolvabile care
conduc la rezolvarea problemei din u.
Cu anumite modificri, algoritmul se poate aplica asupra grafurilor AND/OR oarecare.
Similar cu tehnica backtracking, explorarea se poate face att n adncime (ca n algoritmul sol),
ct i n lime.
Subiectul 19
Sortarea prin numrare
Aceast metod se bazeaz pe ideea c, n secvena final sortat a " j " a cheie este mai
mare dect a " j 1" a din celelalte chei. Metoda const n compararea fiecrei perechi de chei,
numrnd cte vor fi mai mici dect fiecare cheie particular. Calea evident de a face
comparaiile const n: compar K j cu K i , pentru j 1,i
N
1,i N .
Se observ ns c peste jumtate din aceste comparaii sunt redundante, nefiind necesar a
Kb
Ka .
se compara o cheie cu ea nsi i apoi nu e necesar s se compare K a cuiK b cu
Vom avea nevoie numai de a compara K j cu K i , pentru j 1, N
conduce la urmtorul algoritm:

i i 1, N . Aceasta

Algoritmul 5.1.3.1. Sortarea prin numrare


Acest algoritm va sorta R1 , R2 ,..., RN dup cheile K1 , K 2 ,..., K N , prin intermediul
unui tabel auxiliar COUNT(1),..., COUNT(n), pentru a numra cte chei sunt mai mici dect o
cheie dat.
Dup terminarea algoritmului, COUNT(j)+1 va specifica poziia final a nregistrrii

R j .

Pasul P1: (terge COUNT-urile): pune COUNT(1) pn la COUNT(N) pe zero.


Pasul P2: (cicleaz dup i):
execut pasul P3 pentru i N , N 1,...,2 apoi
termin algoritmul.
Pasul P3: (cicleaz dup j):
execut pasul P4 pentru j i 1,...,2,1 .
Pasul P4: (compar K j cu K i ): Dac K i K j incrementeaz COUNT(j) cu 1;
33

altfel incrementeaz COUNT(i) cu 1.


Algoritmul este similar cu o sortare prin tabel de adrese i nu compar nici o deplasare de
nregistrri. Acest algoritm furnizeaz rezultatul corect, indiferent de numrul de chei egale care
sunt prezentate. Pseudocodul corespunztor acestui algoritm este:
* procedura SORTNUM (n, k, COUNT) este
pentru i =1,2,, N execut
COUNT(i) = 0

pentru i =N,, 2 execut


pentru j i 1 , ,2,1 execut
dac K i K j atunci
COUNT(j) = COUNT (j) + 1
altfel
COUNT(i) = COUNT (i) + 1

scrie (COUNT(i), i 1, N )
sfrit.
Dac vom considera c pentru execuia fiecrei operaii este necesar o unitate de timp
calculator, atunci timpul total de rulare al acestui program va fi:
T 2 N 2 5N 2 .
Factorul N care apare n relaia de mai sus arat c algoritmul de sortare prin numrare nu
este o cale eficient n cazul n care N este mare.
Deoarece metoda solicit compararea tuturor perechilor de chei distincte

K , K , nu
i

exist aparent nici o posibilitate de a reduce timpul de rulare.


Totui, algoritmul prezint interes prin simplitatea sa, i nu prin eficien.
Numrarea distribuiilor
Algoritmul 5.1.3.2. Numrarea distribuiilor.
considerm c toate cheile sunt ntregi n domeniul u ki v, i 1, N .
Acest algoritm va sorta nregistrrile R1 ,..., RN , utiliznd un tabel auxiliar:
COUNT(u),..., COUNT(v). La terminarea algoritmului nregistrrile sunt deplasate ntr-o zon
de ieire S1 ,..., S N n ordinea dorit.
Pasul P1: (terge COUNT-urile):
pune COUNT(u) pn la COUNT(v) pe zero.
Pasul P2: (cicleaz dup j):
se execut pasul P3 pentru i 1, N apoi se merge la pasul P4.
Pasul P3: (mrete COUNT( K j )):
se mrete valoarea lui COUNT( K j ) cu 1.
Pasul P4: (acumuleaz):
(n acest moment COUNT(i) va fi egal cu numrul de chei ce sunt
34

egale cu i)
pune COUNT(i) COUNT(i)+COUNT i 1 pentru

i u 1,..., v.

Pasul P5: (cicleaz dup j):


(n acest moment COUNT(i) va fi egal cu numrul de chei i ; n particular,
COUNT(v) = N).
execut pasul P6 pentru j N ,...,1 .
Pasul P6: (ieirea R j ):

pune i COUNT K j

Si R j

COUNT K j i 1 .
Subiectul 20
Sortarea prin inserie
nainte de a examina nregistrarea R j vom considera c nregistrrile precedente

R1 ,..., R j 1

R j n locul ce-i
au fost deja sortate, apoi vom insera
revine ntre nregistrrile sortate anterior.
Inseria direct
Sortarea cea mai simpl prin inserie este i cea mai evident. Se consider 1 j N i
nregistrrile precedente R1 ,..., R j 1 aranjate astfel nct:

K1 ... K j 1 .
Vom compara pe rnd noua cheie K j cu K j 1 , K j 2 ,... , pn vom descoperi c K j
trebuie inserat ntre nregistrrile Ri i Ri 1 ; apoi deplasm nregistrrile Ri 1 ,..., R j 1 cu un
spaiu i introducem noua nregistrare n poziia Ri 1 . Din cele descrise anterior obinem:
Algoritmul 5.1.4.1. Sortarea prin inserie direct
nregistrrile R1 ,..., Rn sunt rearanjate pe locurile lor; dup sortare, cheile vor fi n

ordinea K1 ... K n .
Pasul P1: (cicleaz dup j):
Execut paii P2-P5 pentru j = 2,...,N, apoi termin algoritmul.
Pasul P2: (Fixeaz i, k, r):
Pune
i j 1
K Kj
R R j.

n paii urmtori vom ncerca s inserm R


comparnd K cu K i pentru valori descresctoare ale lui i.
Pasul P3: (Compar K, Ki ):
35

poziia

corect,

Dac K Ki mergi la pasul P5 (s-a gsit poziia corespunztoare


pentru R).
Pasul P4: (deplaseaz Ri , descrete i):
Pune
Ri 1 Ri , apoi
i i 1 i mergi la pasul P3.
(Dac i = 0, atunci K va fi cea mai mic cheie gsit pn acum,
deci R va trebui plasat pe poziia 1).
Pasul P5: (R n Ri ):
Pune Ri 1 R .
Pseudocodul corespunztor algoritmului de mai sus este prezentat n continuare:
procedura sortinsdir (N,K) este
pentru j = 2,, N execut

scrie K L , L 1,..., j ;
i j 1;

K K j ;
repet
dac K K i atunci
K i 1 K i ;
i i 1;
pn cnd i = 0 sau K K i ;
K i 1 K ;

sfrit.
Analiza stocastic a algoritmului
Presupunnd c pentru fiecare operaie este necesar o unitate de timp calculator, timpul total de
rulare a acestei rutine este:
T 1 6 N 1 3B B N 1 A 7 N 4 B A 6 u.t., unde:
A = numrul de cazuri n care i descrete la zero;
B = numrul de deplasri ale nregistrrii cu un pas; B este egal cu numrul de inversiuni
ale permutrii:

1
K
1

2 ... N
.
K 2 ... K N

Vom avea deci:

min A 0 ;

n
1
Hn ;
k 1 k

max A N 1 ;

med A H N 1 ;

dis A

HN HN2 ;

min B 0 pentru K1,..., K N ordonate cresctor;

max B C2N
med B

N N 1
pentru K1 ,..., K N ordonate cresctor;
2

N N 1
;
4

dis B

36

N N 1 2 N 5
.
72

Rezult c timpul total T este

T 7N 4

N N 1
H N 1 6 N 2 6N H N 5 .
4

Pentru n suficient de mare putem aproxima: T N 2 6 N 2 ln N .


Dac nregistrrile sunt parial ordonate, crete H N i deci timpul de rulare scade.
Termenul N 2 este ns dominant.
Totui, algoritmul de sortare prin inserie direct este mult mai eficient dect algoritmul
de sortare prin numrare, datorit faptului c nu exist compararea tuturor perechilor diferite de
chei. Algoritmul prezint interes pentru eficiena sa raportat la simplitatea sa deosebit.
Subiectul 21
Metoda lui Shell
Dac vrem s mbuntim substanial inseria direct, avem nevoie de un mecanism prin
intermediul cruia nregistrrile s efectueze salturi lungi, n loc de pai mici. O asemenea
metod a fost propu s de Donald L. Shell n 1959 i va fi denumit sortare cu micorarea
incrementului.
Algoritmul 5.1.4.2. Metoda lui Shell:
- nregistrrile R1 ,..., RN sunt rearanjate pe loc;

- dup terminarea sortrii cheile lor vor fi n ordinea K1 K 2 ... K N ;


- o secven auxiliar de incremeni ht ,..., h1 va fi utilizat pentru controlul procesului de
sortare, unde h1 1 .
Pasul P1: (cicleaz dup s):
Execut pasul P2 pentru s t , t 1,...,1 , apoi termin algoritmul.
Pasul P2: (cicleaz dup j):
Pune h hs i execut paii P3P6 pentru j h,..., N .
(Vom utiliza metoda inseriei directe pentru a sorta elementele ce sunt la distana
de h poziii, astfel nct Ki Ki h , pentru 1 i N h . Paii de la P3 la P6 sunt
aceiai cu paii de la P2 la P5 din algoritmul anterior).
Pasul P3: (fixeaz i, K, R):
i j h; K K j ; R R j
Atribuie
Pasul P4: (compar K , K i ):
Dac K Ki , atunci mergi la pasul P6.
Pasul P5: (deplaseaz Ri , descrete i):
Ri 1 Ri ; i i h .
Atribuie
Dac i 0 , mergi la P4.
Pasul P6: (R n Ri h ):
Pune Ri h R .
Inserii prin liste
Aceasta este o metod de mbuntire a inseriei directe. Inseria direct implic dou
operaii de baz:
37

1) parcurgerea unui fiier ordonat pentru a gsi cea mai mare cheie, mai mare sau egal
cu o cheie dat;
2) inserarea unei nregistrri noi ntr-o anumit parte a fiierului ordonat.
Fiierul este, evident, o list liniar i algoritmul de sortare prin inserie direct
(algoritmul 5.1.4.1) va manipula aceast list utiliznd alocarea secvenial.
n concluzie, structura adecvat de date pentru inserie direct este o list liniar cu
legturi, unidirecional. Este convenabil s revedem algoritmul menionat mai sus, astfel ca lista
s fie parcurs n ordine cresctoare.
Astfel, vom obine algoritmul urmtor:
Algoritmul 5.1.4.3. Inserii de liste
Se consider c nregistrrile R1 ,..., RN conin cheile K1 ,..., K N i cmpurile de
legtur L1,..., LN , capabile de a conine numere de 0 la n. Exist un cmp de legtur L0
ntr-o nregistrare K 0 , artificial, la nceputul fiierului. Algoritmul va fixa cmpurile de
legtur, astfel nct nregistrrile s fie legate n ordine ascendent. Astfel, dac
p 1 ,..., p N este o permutare stabil care ordoneaz K p 1 ,..., K p N , acest algoritm
va da:

L0 p 1

Lp i p i 1 , i 1, N 1

Lp N 0.

Pasul P1: (cicleaz dup j):


L0 N ; LN 0
Atribuie
( L0 acioneaz n calitate de cap al listei, iar 0 n calitate de
legtura zero, deci lista este circular). Execut paii de la P2 la P5 pentru
j N 1,...,1 , apoi termin algoritmul.
Pasul P2: (fixeaz p, q, K):
Atribuie
p L0 ; q 0; K K j
(n paii ce urmeaz vom insera R j la locul potrivit n lista legat,
comparnd K cu cheile anterioare n ordine ascendent. Variabilele p i q au rol de
indicatoare
spre
locul
cunoscut
n
list,
cu p Lq , astfel c variabila q este cu un pas n urma lui p).
Pasul P3: (compar K , K p ):
Dac K K p , mergi la pasul P5.
(Am gsit poziia dorit pentru nregistrarea R, ntre Rq i R p , n
list).
Pasul P4:
Atribuie
q p i p Lq .
Dac p 0 mergi napoi la pasul P3
38

(Dac p 0 , K va fi cheia cea mai mare gsit pn n prezent,


deci nregistrarea R aparine sfritului listei, ntre Rq i R0 ).
Pasul P5: (insereaz n list):
Atribuie
Lq j; j p.
Acest algoritm apare des ca o component a altor algoritmi de
prelucrare a listelor.
Subiectul 22
Sortarea prin interschimbare
Aceast metod interschimb perechea de elemente care nu este n ordine, pn cnd nu mai
exist nici o astfel de pereche. Procesul de inserie direct poate fi vizualizat ca o metod de
interschimbare: vom lua fiecare nregistrare Rj i-o vom interschimba cu vecinii si din stnga,
pn cnd ajunge la locul potrivit.
Probabil c cea mai evident cale de sortare prin interschimbri const n compararea lui
K1 cu K2 i interschimbarea lui R1 cu R2, dac cheile nu sunt n ordine, apoi se va face acelai
lucru pentru nregistrrile R2 i R3, R3 i R4 etc. n timpul acestei secvene de operaii,
nregistrrile cu chei mari tind s se deplaseze spre dreapta, i de fapt nregistrarea cu cheia cea
mai mare va avansa pentru a devenii Rn. Repetarea acestui proces va pune nregistrrile potrivite
n poziiile Rn-1, Rn-2 etc., astfel nct toate nregistrrile vor fi sortate. Algoritmul corespunztor
acestei metode este urmtorul:
Algoritmul 5.1.5.1:
nregistrrile R1 ,..., RN sunt rearanjate dup terminarea sortrii, cheile vor fi n ordine,

K1 ... K N .

Pasul P1: (iniializeaz BOUND):


Stabilete BOUND N
(BOUND este indice).
Pasul P2: (cicleaz dup j):
Stabilete t 0 .
Efectueaz pasul P3 pentru j 1,..., BOUND 1 i apoi mergi la pasul P4.
Pasul P3: (compar/interschimb R j cu R j 1 ):
Dac K j K j 1 interschimb R j cu R j 1 i stabilete t j .
Pasul P4: (sunt interschimbri?):
Dac t = 0, algoritmul se termin.
n caz contrar, stabilete BOUND t i revino la pasul P2.
Iat o schem bloc de funcionare a algoritmului:

39

Organigrama pentru sortare prin metoda bulelor


Algoritmul prezentat mai sus poate fi realizat i ntr-o alt variant, n care la pasul P2
ciclarea se execut pentru j 1,..., N 1 i se schimb variabila BOUND.
Aceast a doua variant consum ns un timp de lucru mai mare dect prima variant,
deoarece necesit efectuarea unor operaii de comparare suplimentare n subiruri deja ordonate.
Desi s-au incercat unele perfectionari ale metodei de mai sus , se observa ca ele nu conduc
la un algoritm mai bun decat insertia directa .
Subiectul 23
Sortarea prin selecie
O alt familie important de tehnici de sortare este bazat pe idea seleciei repetate. Cea mai
simpl metod de selecie este urmtoarea:
i) Aflai cheia cea mai mic; transferai nregistrarea corespunztoare n aria de ieire;
apoi nlocuii cheia prin valoarea infinit (care se presupune c este mai mare dect orice cheie
actual).
ii) Repetai pasul (i). De aceast dat va fi selectat urmtoarea cheie cu valoarea cea mai
mic, deoarece cea mai mic valoare a fost nlocuit prin infinit.
(iii) Continuai repetarea pasului (i) pn cnd cele N nregistrri au fost selectate.
De notat ca o astfel de metod de selecie necesit ca toate elementele de intrare s fie
prezentate nainte ca sortarea s poat ncepe i ea genereaz datele finale de ieire, una dup alta,
n secvene. Aceasta, n esen se deosebete de inserie, unde intrrile se primesc secvenial, dar
nu se tie nimic despre ieiri, pn cnd sortarea este complet.
Metoda de mai sus implic N-1 comparaii de fiecare dat cnd o nou nregistrare este
selectat i de asemenea, necesit un spaiu separat de memorie pentru datele de ieire. Exist un
mod evident pentru ameliorarea acestei situaii, evitnd utilizarea lui infinit. Se poate lua
valoarea selectat i muta ntr-o poziie adecvat ei, prin interschimbarea cu nregistrarea curent
care ocupa acea poziie. Apoi nu mai este necesar s considerm aceast poziie n seleciile
viitoare. Aceast idee conduce la urmtorul algoritm de sortare prin selecie:
Algoritmul 5.1.6.1:
nregistrrile R1, R2 ,..., RN sunt de sortat; dup ce sortarea este complet, cheile acestor
nregistrri vor fi n ordinea K1 K 2 ... K N . Sortarea se bazeaz pe faptul c se selecteaz la
nceput elementul cel mai mare, apoi al 2-lea element cu valoarea cea mai mare etc.
40

Pasul P1: (bucleaz pe j):


Se execut paii P2 i P3 pentru j N , N 1,...,2 .

max ( K1 ,..., K j ) K i ) :

Pasul P2: (gsete:


Se caut pentru
(fie aceasta Ki ).

cheile

K j , K j 1 ,..., K1

cea

mai

mare

dintre

ele

Pasul P3: (interschimb):


Se interschimb nregistrrile Ri i R j
(Acum nregistrrile R j ,..., R N sunt n poziia lor final).

Sortare prin selecie direct


Exemplu numeric

4
4

6
2

5
5

2
6

7
7

8
8

Subiectul 24
Sortarea prin interclasare
Interclasarea (sau colaionarea) nseamn combinarea a dou sau mai multe fiiere ntr-un singur
fiier ordonat.
Observaie. Cnd unul din fiiere este epuizat este necesar ceva mai mult atenie.
De exemplu putem interclasa dou fiiere :

"503 703 765"

"087 512 677"


41

pentru a obine:
087 503

512

677

703

765 .

Observaie. Un mod simplu pentru realizarea acestui deziderat const n a compara


elementele cele mai mici, de a extrage pe cel mai mic etc.
Algoritmul de sortare prin interclasare este prezentat mai jos:
Algoritmul 5.1.7.1:
Acest algoritm interclaseaz fiierele ordonate x1 x2 ... xm i y1 y2 ... yn ntrun singur fiier z1 z2 ... zm n .
Pasul P1: (iniializare):
Stabilete
i 1
j 1
k 1.

Pasul P2: (gsete pe cel mai mic):


Dac xi y j , treci la pasul P3; altfel treci la pasul P5.
Pasul P3: (extrage xi ):
Stabilete
zk xi

K K 1
i i 1.

Dac i m , treci la pasul P2.


Pasul P4: (transmite zk ,..., zm n ):
Stabilete zk ,..., zm n y j ,..., yn i termin algoritmul.
Pasul P5: (extrage y j ):
Stabilete
zk y j

K K 1
j j 1.

Dac j n , treci la pasul P2.


Pasul P6: (transmite xi ,..., xm ):
Stabilete zk ,..., zm n xi ,..., xm i termin algoritmul.
Observaie. Interclasarea necesit o munc mai simpl dect sortarea. Cantitatea total de
munc implicat n acest algoritm este de fapt proporional cu m+n, astfel este clar c
interclasarea este o problem mai simpl dect sortarea. Mai mullt, putem reduce problema de
sortare la interclasare i n acest caz este posibil s se continue interclasarea subfiierelor, din ce
n ce mai lungi pn cnd toate elementele sunt sortate; inseria unui nou element ntr-un fiier
sortat reprezint cazul special de interclasare cnd n=1.

42

Interclasare X1<=<=Xm cu Y1<=<=Yn


Dac dorim s facem procesul de inserie mai rapid, putem considera cteva elemente
inserate la un moment dat, interclasate, i aceasta conduce natural la idea general de sortare prin
interclasare. Din punct de vedere istoric, sortarea prin interclasare este una din primele metode
propuse pentru sortarea cu calculatorul; aceasta a fost sugerat de John von Neumann nainte de
anul 1945.
Subiectul 27
Cutarea ntr-un tabel ordonat
n continuare ne vom ocupa de metode mai adecvate pentru cutarea n tabele ale cror
nregistrri sunt ordonate: K1 K 2 ... K N , presupunnd c se pot efectua accese aleatoare la
poziiile din tabel.
Dup compararea lui K cu Ki , ntr-un asemenea tabel va rezulta:
1) K Ki Ri , Ri 1,..., RN nu sunt luate n considerare;
2) K Ki cutarea este terminat;
3) K Ki R1, R2 ,..., Ri nu sunt luate n considerare.
Cutarea binar
Una din formele cele mai cunoscute ale acestui algoritm folosete dou referine, I i u,
care indic limita inferioar i limita superioar a cutrii, i anume:
Algoritmul 5.2.5.1.1. Cutarea binar
Fiind dat un tabel de nregistrri R1,..., RN ale cror chei sunt n ordine cresctoare
K1 K 2 ... K N , acest algoritm caut nregistrarea cu cheia K.
Pasul P1: (iniializare):
Se stabilete
I 1; u N .
43

Pasul P2: (obine mijloc de tabel):


n acest moment se cunoate c dac se gsete n tabel, el satisface
K K K u . Dac u I , algoritmul se termin fr succes. n caz contrar,
se stabilete i I u / 2 (mijlocul aproximativ al tabelului).
Pasul P3: (comparare):
Dac K Ki , se trece la pasul P4. Dac K Ki , algoritmul se termin cu succes.
Dac K Ki , se trece la pasul P5.
Pasul P4: (ajustare u):
Se stabilete u i 1 i se revine la pasul P2.
Pasul P5: (ajustare I):
Se stabilete I i 1 i se revine la pasul P2.
Reprezentarea arborescent
Pentru a nelege mai bine ce se petrece n algoritmul de mai sus, este mai bine s fie
privit ca un arbore de decizie binar, ca cel din figura 5.6, pentru N=16. Cnd N = 16, prima
comparaie efectuat de algoritm este K = K8; aceasta este reprezentat de nodul rdcin 8 din
figur. Apoi, dac K < K8, algoritmul urmeaz subarborele din stnga, comparnd pe K cu K4;
similar, dac K > K8, se merge pe subarborele din dreapta, comparnd pe K cu K12.
O cutare fr succes va conduce la unul din nodurile extreme. O cutare cu succes se va
opri la un nod intermediar.
Arborele binar corespunztor unei cutri binare se poate construi astfel:
Dac N = 0 arborele este . n caz contrar, nodul rdcin este N / 2 , arborele din
stnga este arborele corespunztor cu N / 2 1 noduri, iar subarborele din dreapta este
subarborele binar corespunztor cu N / 2 noduri, numerele nodurilor fiind crescute cu N / 2 .

Figura 5.6 Arbore de decizie binar


Orice algoritm de cutare ntr-un tabel ordonat de lungime N, folosind comparaiile, poate
fi reprezentat ca un arbore binar n care nodurile sunt etichetate cu numere de la 1 la N. Invers,
orice
arbore
binar
corespunde
unei
metode
corecte
de
cutare
ntr-un tabel ordonat. O variant important a acestui algoritm este urmtoarea: n loc de a utiliza
n cutare 3 indicatori, I, i i u, este tentant s se utilizeze doar doi: poziia curent i i viteza de
modificare ; dup fiecare comparaie de inegalitate se va stabili i i i / 2
(aproximativ).
Algoritmul 5.2.5.1.2. Cutarea binar uniform
Fiind dat un tabel de nregistrri R1 ,..., RN ale cror chei sunt n ordine cresctoare
K1 K 2 ... K N , acest algoritm caut nregistrarea cu cheia K. Dac N este par, algoritmul va
face uneori referire la o cheie inexistent K 0 , care trebuie fcut egal cu ; N 1 .
Pasul P1: (iniializare):
Se stabilete i N / 2 , m N / 2 .
Pasul P2: (comparare):
44

Dac K Ki , se trece la pasul P3. Dac K Ki , se trece la pasul P4.


Dac K Ki , algoritmul se termin cu succes.
Pasul P3: (descrete i):
(S-a ajuns cu cutarea la un interval care conine m sau m 1
nregistrri; i va indica cutarea imediat spre dreapta acestui
interval). Dac m = 0, algoritmul se termin fr succes. n caz contrar se
stabilete: i i m / 2 ; m m / 2 i se revine la pasul P2.
Pasul P4: (crete i):
(S-a ajuns cu cutarea la un interval care conine m sau m 1
nregistrri; i va indica cutarea spre stnga acestui interval).
Dac m = 0, algoritmul se termin fr succes. n caz contrar, se stabilete:
i i m / 2 ; m m / 2 i apoi se revine la pasul P2.
Procesul de cutare poate fi denumit uniform, deoarece diferena dintre un nod de la
nivelul I i numrul ascendentului su de pe nivelul I 1 este o valoare constant pentru toate
nodurile de pe nivelul I. Principalul avantaj al acestui algoritm este c nu necesit memorarea
separat a lui m.
Subiectul 28
Cutarea de tip Fibonacci
Metoda care urmeaz este preferabil pentru implementarea pe calculator, deoarece ea presupune
numai operaii de adunare i scdere, nu i mpriri.
Mai jos este dat arborele Fibonacci de ordinul 6. n general, arborele Fibonacci de ordinul
K are FK 1 1 noduri interne (circulare) i FK 1 noduri externe (ptratice) i este construit
astfel:
dac K = 0 sau K = 1, arborele este pur i simplu ;
dac K 2 , rdcina este FK :
- subarborele din stnga este arborele Fibonacci de ordinul K 1 ;
- subarborele din dreapta este arborele Fibonacci de ordinul K 2
cu toate numerele mrite cu FK .

Figura. 5.7 Arborele Fibonacci de ordinul 6


45

De notat c, cu excepia nodurilor externe, numerele din cei doi descendeni ai fiecrui
nod intern difer de numrul nodului printe prin aceeai valoare i aceast valoare este un numr
Fibonacci.
Astfel, din figur:
5 8i
F11
8 F4 .
4
Cnd diferena este F j , diferena Fibonacci corespunztoare pentru urmtoarea
ramificaie la stnga este F j 1 , n timp ce pentru ramificaia la dreapta este F j 2 . De exemplu:
3 5 F3 , iar 10 11 F2 .
Aceste observaii conduc la urmtorul algoritm:
Algoritmul 5.2.6.1
Fiind dat un tabel de nregistrri R1 ,..., RN ale cror chei sunt n ordine cresctoare
K1 , , K N , acest algoritm caut nregistrarea cu cheia dat K.
Pentru uurina calculelor, vom presupune c N + 1 este un numr
Fibonacci FK 1 . Nu este dificil de observat c metoda lucreaz corect pentru N arbitrar, dac se
realizeaz o iniializare corespunztoare.
Pasul P1: (iniializare):
Se stabilete
i FK

p FK 1

q FK 2

(p i q vor reprezenta numere Fibonacci consecutive).


Pasul P2: (compararea):
Dac K Ki , se trece la pasul P3.
Dac K Ki , se trece la pasul P4.
Dac K Ki , algoritmul se termin cu succes.
Pasul P3: (descrete i):
Dac q = 0, algoritmul se termin fr succes.
n caz contrar, se stabilete:
i iq
p , q q, p q

i se revine la pasul P2.


Pasul P4: (crete i):
Dac p = 1 algoritmul se termin fr succes.
n caz contrar se stabilete:
iiq

p pq
qq p

i se revine la pasul P2.


Subiectul 29
Cutarea prin interpolare
46

K l i K u se poate alege
circa K K l / K u K l

Cnd se cunoate c K se gsete ntre

urmtorul element de

comparare ca fiind cel ce se gsete la

distana ntre

i u,

presupunnd c cheile sunt numerice i c ele cresc n general n interval n mod constant.
Experimentele de simulare cu calculatorul arat urmtoarele: cutarea prin interpolare nu
micoreaz numrul de comparaii suficient de mult pentru a compensa timpul de calcul
suplimentar necesar n cazul cutrii ntr-un tabel memorat ntr-o oarecare msur. Metoda s-a
dovedit
eficient
numai
ntr-o
oarecare msur, cnd cutarea a fost o cutare extern, folosind o unitate de memorie.
n paragrafele anterioare s-a constatat c o structur implicit de arbore binar uureaz
nelegerea comportrii cutrii binare i a cutrii de tip Fibonacci. Metodele prezentate anterior
sunt adecvate pentru tabelele de dimensiuni fixe, deoarece alocarea succesiv a nregistrrilor
complic operaiile de cutare i tergere.
Dac tabelul se modific dinamic, am pierde mai mult timp pentru ntreinerea lui dect
am economisi n cazul cutrii binare.
Utilizarea unei structuri de arbore binar explicit
Aceasta face posibil inserarea i tergerea rapid din nregistrri, precum i cutarea
eficient a tabelului. n consecin, dispunem de o metod eficient att pentru cutare, ct i
pentru sortare. Acest ctig n flexibilitate se realizeaz prin adugarea la fiecare nregistrare din
tabel a dou cmpuri suplimentare de legturi.
Algoritmul 5.2.8.1
Fiind dat un tabel de nregistrri care formeaz un arbore binar descris ca mai sus,
algoritmul caut nregistrarea cu o anumit cheie K. Dac K nu se gsete n tabel, se insereaz n
arbore la locul potrivit un nod ce conine cheia K. Presupunem c nodurile arborelui conin cel
puin urmtoarele cmpuri:
- CHEIE(P) = cheia nregistrrii n NOD(P);
- LLINK(P) = adresa de legtur la subarborele din stnga lui NOD(P);
- RLINK(P) = adresa de legtur la subarborele din dreapta lui NOD(P).
Subarborii noduri extreme (vizi) sunt reprezentai prin adresa de legtur nul . Variabila
ROOT face legtura la tulpina arborelui. Vom presupune c arborele nu este vid (ROOT ).
Pasul P1: (iniializarea):
Se stabilete P ROOT
(Variabila de legtur P se va deplasa de-a lungul arborelui).
Pasul P2: (comparare):
Dac K < CHEIE(P), se trece la pasul P3.
Dac K > CHEIE(P), se trece la pasul P4.
Dac K = CHEIE(P), cutarea se termin cu succes.
Pasul P3: (deplasarea spre stnga):
Dac LLINK(P) se stabilete
P LLINK(P) i se revine la pasul P2.
n caz contrar, se trece la pasul P5.
Pasul P4: (deplasare spre dreapta):
47

Dac RLINK(P) se stabilete:


P RLINK(P) i se revine la pasul P2.
Altfel se trece la pasul P5.
Pasul P5: (Cutarea este fr succes, se insereaz K n arbore).
Se stabilete Q DISP , care reprezint adresa unui nou nod.
Se stabilete:
CHEIE(Q) K;
LLINK(Q) ;
RLINK(Q) .
Dac K < CHEIE(P), atunci LLINK(P) Q.
Dac K > CHEIE(P), atunci RLINK(P) Q.
n acest moment se poate stabili P Q i algoritmul se termin cu succes. Schema logic
ce cespunde acestui algoritm este dat n figura 5.8.

48

Figura 5.8. Schema corespunztoare algoritmului ce utilizeaz structuri de arbore binar explicit
(adugare)
Subiectul 31
METODA GREEDY
Algoritmii greedy (greedy = lacom) sunt n general simpli i sunt folosii la probleme de
optimizare, cum ar fi: s se gseasca cea mai bun ordine de executare a unor lucrri pe
calculator, s se gseasca cel mai scurt drum ntr-un graf etc. n cele mai multe situaii de acest
fel avem:
o multime de candidai (lucrri de executat, vrfuri ale grafului etc);
o funcie care verific dac o anumit mulime de candidai constituie o soluie posibil, nu
neaparat optim, a problemei;
o funcie care verific dac o mulime de candidai este fezabil, adic dac este posibil s
completm aceast mulime astfel nct s obinem o soluie posibil, nu neaprat optim, a
problemei;
o funcie de selecie care indic la orice moment care este cel mai promitor dintre candidaii
nc nefolosii;
o funcie obiectiv care dvaloarea unei soluii (timpul necesar executrii tuturor lucrrilor ntro anumit ordine, lungimea drumului pe care l-am gsit etc); aceasta este funcia pe care urmrim
s o optimizm (minimizm/maximizm).
Pentru a rezolva problema noastr de optimizare, cutam o soluie posibil care s
optimizeze valoarea funciei obiectiv. Un algoritm greedy construiete soluia pas cu pas. Iniial,
mulimea candidailor selectai este vid. La fiecare pas, ncercam s adugm acestei mulimi cel
mai promitor candidat, conform funciei de selecie. Dac, dup o astfel de adugare, mulimea
de candidai selectai nu mai este fezabil, eliminm ultimul candidat adugat; acesta nu va mai fi
niciodat considerat. Dac, dup adugare, mulimea de candidai selectai este fezabil, ultimul
candidat adugat va rmne de acum ncolo n ea. De fiecare dat cnd lrgim mulimea
candidailor selectai, verificm dac aceast mulime nu constituie o soluie posibil a problemei
noastre. Dac algoritmul greedy funcioneaz corect, prima soluie gsit va fi totodat o soluie
optim a problemei. Soluia optim nu este n mod necesar unic: se poate ca funcia obiectiv s
aib aceeai valoare optim pentru mai multe soluii posibile.
Algoritmii de tip greedy, backtracking i de programare dinamic se aplic unor probleme a
cror soluie poate fi exprimat sub forma unui vector sau unei matrice de numere (de obicei
ntregi cu valori ntr-un subdomeniu limitat).
Exemple de probleme cu soluie vectorial i matricial:
- Problema restului: O sum de bani trebuie pltit cu un numr minim de monede de
valori cunoscute. Vectorul soluie conine numrul de monede de fiecare valoare disponibil.
- Problema colorrii nodurilor unui graf cu numr minim de culori. Vectorul soluie are
attea componente cte noduri sunt n graf, iar valoarea fiecrei componente este codul unei
culori.
Problemele menionate sunt probleme de optimizare, n care trebuie gsit soluia optim
dintre toate soluiile posibile. Alte clase de probleme cu soluie vectorial sunt probleme de
enumerare a tuturor soluiilor posibile i probleme de decizie, la care trebuie spus dac exist sau
nu cel puin o soluie.
Prezentarea metodei Greedy

49

Metoda Greedy se poate aplica unor probleme de optimizare cu soluie vectorial, ca


alternativ mai eficient la o cutare exhaustiv (de tip 'backtracking'). Complexitatea unui
algoritm greedy este polinomial.
n continuare, vom nota vectorul soluie cu 'x' i vom considera c este un vector de
numere ntregi pozitive.
Un algoritm Greedy este un algoritm iterativ (nerecursiv) care determin n fiecare pas k
o component x[k] a soluiei i nu mai revine ulterior la aceast alegere.
Numele metodei ('Greedy'= lcomie) sugereaz modul de lucru: la stabilirea valorii lui
x[k] se alege dintre candidaii posibili pe acela care este optim n pasul k, deci un optim local.
n general, aceast alegere precipitat, grbit i care nu ine seama de valorile ce vor fi
stabilite n paii urmtori pentru x[k+1],..., x[n] nu poate garanta soluia optim a
problemei.
n funcie de specificul problemei, un algoritm greedy poate conduce la soluia optim sau
la o soluie destul de bun, dei suboptimal. Rezultatul unui algoritm greedy pentru o problem
dat depinde i de datele concrete ale problemei, sau chiar de ordinea introducerii lor.
De exemplu, n problema exprimrii unei sume de bani printr-un numr minim de monede
de valori date rezultatul (optim sau suboptim) depinde de valorile monedelor i de valoarea
sumei. Algoritmul greedy folosete monedele n ordinea descresctoare a valorilor lor, deci se
repede la monedele de valoare maxim, care vor fi n numr mai mic pentru aceeai sum. Fie
monede de valori 11, 5 i 1. Pentru suma 12 rezultatul algoritmului greedy va fi optim (dou
monede de valori 11 i 1), dar pentru suma 15 rezultatul algoritmului greedy nu va fi optim (5
monede de valori 11, 1, 1, 1, 1 n loc de 3 monede de valori 5, 5, 5).
Dac exist mai multe soluii optime egale ca valoare, algoritmul greedy produce numai
una din aceste soluii. De exemplu, n cazul drumului de cost minim dintre dou noduri dintr-un
graf algoritmul greedy (atribuit lui Dijkstra) produce o singur soluie; toate drumurile de cost
minim pot fi gsite numai printr-un algoritm Backtracking.
Simplificnd lucrurile, putem spune c metoda greedy conduce la soluia optim pentru
problemele care au proprietatea de optim local, adic soluia optim pentru problema de
dimensiune n conine n ea soluiile optime pentru probleme de acelai tip dar de dimensiune mai
mic. Determinarea tipului de probleme pentru care un algoritm greedy determin soluia optim
pentru orice instan a problemei este o provocare teoretic fr o soluie satisfctoare. Ceea ce
putem face ns, pentru o problem dat, este s cutm exemple de cazuri concrete pentru care
algoritmul greedy nu produce soluia optim.
Metoda greedy se aplic i pentru probleme care nu satisfac aceast condiie, pentru c ea
produce o soluie bun, suboptimal dar destul de apropiat de soluia optim ntr-un timp mult
mai scurt dect o metod de tip 'ncearc toate posibilitile'.
In aceste cazuri metoda greedy este considerat ca o metod euristic, care 'ghiceste'
soluia bun fr s fac o analiz exhaustiv a tuturor soluiilor posibile. O soluie 'bun' este o
soluie al crui cost este cel putin jumtate din costul soluiei optime.
Subiectul 32
Exemple de aplicare a metodei Greedy
1. Algoritm Greedy pentru problema restului
Problema restului cere exprimarea unei sume de bani (un rest de plat) printr-un numr minim de
monede cu valori date.
Fie n tipuri de monede cu valori c[1],c[2],..c[n] i o sum R. O soluie este un
vector x[1], x[2], ..x[n], unde x[k] este numrul de monede de valoare c[k] necesar
50

pentru achitarea sumei R. deci, R=x[1]*c[1]+x[2]*c[2]+...+x[n]*c[n]. O parte din


valorile x[k] pot fi zero, dac nu se folosesc monedele corespunztoare.
Vectorul soluie, n aceast problem, poate fi considerat ca un vector de lungime fix
(egal cu numrul de monede distincte) sau ca un vector de lungime variabil, cu x[k] egal cu
numrul de monede stabilit n pasul k i considerat complet la exprimarea ntregii sume de plat.
Algoritmul 'greedy' ncearc s foloseasc monedele n ordinea descresctoare a valorii
lor, deci ncepe cu moneda de valoare maxim i determin numrul maxim de monede de acest
tip pentru suma de plat, apoi ncearc cu moneda imediat inferioar .a.m.d.
Lista de candidai este lista monedelor disponibile, ordonat descresctor; la fiecare pas se
extrage primul element din list. Pentru anumite valori ale monedelor, acest algoritm conduce la
soluia optim pentru orice sum R. Complexitatea este O(n).
Vom exemplifica cu o instan a problemei pentru care soluia greedy nu este i soluia
optim. Lista ordonat de monede: c[1]=11, c[2]=5, c[3]=1. Suma de plat R= 15.
Soluia greedy :
x[1]= 1, x[2]=0, x[3]= 4 (5 monede)
Soluia optim :
x[1]= 0, x[2]=3, x[3]= 0 (3 monede)
2. Algoritm Greedy pentru problema rucsacului
Problema rucsacului, sau problema seleciei optime, se poate enuna astfel: Fiind date n
obiecte, fiecare cu greutatea g[i] i valoarea v[i] i un rucsac cu capacitatea total Gt, s se
determine ce obiecte trebuie selectate pentru a fi luate n rucsac astfel nct greutatea lor total s
nu depseasc Gt i valoarea lor s fie maxim.
Problema poate avea dou variante :
- varianta fracionar, dac se pot lua prti din fiecare obiect;
- varianta 0/1, dac nu se pot lua dect obiecte ntregi.
n varianta 0/1 vectorul soluie are n componente i fiecare x[k] poate fi 1 sau 0 dup
cum obiectul k a fost sau nu selectat.
Un algoritm greedy ordoneaz obiectele dup valoarea lor unitar (dup raportul v[i]/g[i])
i verific fiecare obiect din aceast list de candidati dac mai are loc sau nu n rucsac. Pentru
problema fractionar metoda greedy conduce sigur la soluia optim, dar pentru varianta 0/1 nu
este garantat soluia optim.
Lista candidatilor este lista obiectelor, ordonat dup valoarea lor specific.
Exemplu numeric: n=3, Gt=15
i
g[i]
v[i]
v[i]/g[i]
soluie:

1
10
20
2.0

2
3
6
8
10
12
1.66 1.5

Soluia greedy spune c trebuie selectat obiectul 1, valoarea seleciei fiind 20. Vectorul
x[1]=1, x[2]=0, x[3]=0
Soluia optim este cea care ia obiectele 2 i 3, cu valoarea total 22 i greutatea total 14:
x[1]=0, x[2]=1, x[3]=1

51

3. Algoritmul Greedy pentru minimizarea timpului mediu de ateptare


O singur staie de servire (procesor, pomp de benzin etc) trebuie s satisfac cererile a
n clieni. Timpul de servire necesar fiecrui client este cunoscut n prealabil: pentru clientul i este
necesar un timp ti, 1 i n. Dorim s minimizm timpul total de ateptare
(timpul de ateptare pentru clientul i)
ceea ce este acelai lucru cu a minimiza timpul mediu de ateptare, care este T/n. De exemplu,
dac avem trei clieni cu t1 = 5, t2 = 10, t3 = 3, sunt posibile ase ordini de servire. n primul caz,
clientul 1 este servit primul, clientul 2 ateapt pn este servit clientul 1 i apoi este servit,
clientul 3 ateapt pn sunt servii clienii 1, 2 i apoi este servit. Timpul total de ateptare a
celor trei clieni este 38.
Ordinea
T
1 2 3
5+(5+10)+(5+10+3)
= 38
1 3 2
5+(5+3)+(5+3+10)
= 31
2 1 3
10+(10+5)+(10+5+3)
= 43
2 3 1
10+(10+3)+(10+3+5)
= 41
3 1 2
3+(3+5)+(3+5+10)
= 29 optim
3 2 1
3+(3+10)+(3+10+5)
= 34
Algoritmul greedy este foarte simplu: la fiecare pas se selecteaza clientul cu timpul minim
de servire din mulimea de clieni rmas. Vom demonstra c acest algoritm este optim. Fie
I = (i1 i2 ... in)
o permutare oarecare a ntregilor {1, 2, ..., n}. Dac servirea are loc n ordinea I, avem
n

T ( I ) t (t t ) (t t t ) .... nt (n 1)t ... (n k 1)t


i1
i1 i 2
i1 i 2 i 3
i1
i2
ik
k 1
Presupunem acum c I este astfel nct putem gsi doi ntregi a < b cu

t t
i a ib

Interschimbam pe ia cu ib n I; cu alte cuvinte, clientul care a fost servit al


b-lea va fi servit acum al a-lea i invers. Obinem o nou ordine de servire J, care este de preferat
deoarece:
n

T ( J ) (n a 1)t (n b 1)t (n k 1)t


ib
i a k 1
ik
k a ,b

T ( I ) T ( J ) (n a 1)(t t ) (n b 1)(t t ) (b a )(t t ) 0 Prin


ia ib
ib ia
i a ib
metoda greedy obinem deci ntotdeauna planificarea optim a clienilor.
Problema poate fi generalizat pentru un sistem cu mai multe staii de servire.
Subiectul 33
Algoritmul Greedy pentru colorarea unui graf
Fie G = <V, M> un graf neorientat, ale crui vrfuri trebuie colorate astfel nct oricare
dou vrfuri adiacente s fie colorate diferit. Problema este de a obine o colorare cu un numr
minim de culori.
52

Folosim urmtorul algoritm greedy: alegem o culoare i un vrf arbitrar de pornire, apoi
considerm vrfurile rmase, ncercnd s le colorm, fr a schimba culoarea. Cnd nici un vrf
nu mai poate fi colorat, schimbm culoarea i vrful de start, repetnd procedeul.

Figura 1 Un graf care va fi colorat.


Dac n graful din figura 1 pornim cu vrful 1 i l colorm n rou, mai putem colora tot
n rou vrfurile 3 i 4. Apoi, schimbm culoarea i pornim cu vrful 2, colorndu-l n albastru.
Mai
putem
colora
cu
albastru
i
vrful
5.
Deci,
ne-au fost suficiente dou culori. Dac colorm vrfurile n ordinea 1, 5, 2, 3, 4, atunci se obine
o colorare cu trei culori.
Rezulta c, prin metoda greedy, nu obinem dect o soluie euristic, care nu este n mod
necesar soluia optim a problemei.
De ce suntem atunci interesai
ntr-o astfel de rezolvare? Toi algoritmii cunoscui, care rezolv optim aceast problem, sunt
exponeniali, deci, practic, nu pot fi folosii pentru cazuri mari. Algoritmul greedy euristic propus
furnizeaz doar o soluie acceptabil, dar este simplu i eficient.
Un caz particular al problemei colorrii unui graf corespunde celebrei probleme a
colorrii hrilor: o hart oarecare trebuie colorat cu un numr minim de culori, astfel nct
dou ri cu frontier comun s fie colorate diferit. Dac fiecrui vrf i corespunde o ar, iar
dou vrfuri adiacente reprezint ri cu frontier comun, atunci hrii i corespunde un graf
planar, adic un graf care poate fi desenat n plan fr ca dou muchii s se intersecteze.
Celebritatea problemei const n faptul c, n toate exemplele ntlnite, colorarea s-a putut face cu
cel mult 4 culori. Aceasta n timp ce, teoretic, se putea demonstra c pentru o hart oarecare este
nevoie de cel mult 5 culori. Recent s-a demonstrat pe calculator faptul c orice hart poate fi
colorat cu cel mult 4 culori. Este prima demonstrare pe calculator a unei teoreme importante.
Problema colorrii unui graf poate fi interpretata i n contextul planificarii unor activiti.
De exemplu, s presupunem c dorim s executm simultan o mulime de activiti, n cadrul
unor sli de clas. n acest caz, vrfurile grafului reprezint activiti, iar muchiile unesc
activitile incompatibile. Numrul minim de culori necesare pentru a colora graful corespunde
numrului minim de sli necesare.
Subiectul 36
Algoritmul lui Kruskal
Arborele partial de cost minim poate fi construit muchie cu muchie, dupa urmatoarea
metoda a lui Kruskal (1956): se alege ntai muchia de cost minim, iar apoi se adauga repetat
53

muchia de cost minim nealeasa anterior i care nu formeaza cu precedentele un ciclu. Alegem
astfel X1 muchii. Este usor de dedus ca obinem n final un arbore. Este nsa acesta chiar
arborele partial de cost minim cautat?
nainte de a raspunde la ntrebare, sa consideram, de exemplu, graful din Figura 6.1.a. Ordonam
crescator (n functie de cost) muchiile grafului: {1, 2}, {2, 3}, {4, 5}, {6, 7}, {1, 4}, {2, 5},
{4, 7}, {3, 5}, {2, 4}, {3, 6}, {5, 7}, {5, 6} i apoi aplicam algoritmul. Structura componentelor
conexe este ilustrata, pentru fiecare pas, n Tabelul 1.

Figura 1 Un graf i arborele sau partial de cost minim.

Pasul

Muchia considerata Componentele conexe alesubgrafului <X, A>

Initializare

{1}, {2}, {3}, {4}, {5}, {6}, {7}

{1, 2}

{1, 2}, {3}, {4}, {5}, {6}, {7}

{2, 3}

{1, 2, 3}, {4}, {5}, {6}, {7}

{4, 5}

{1, 2, 3}, {4, 5}, {6}, {7}

{6, 7}

{1, 2, 3}, {4, 5}, {6, 7}

{1, 4}

{1, 2, 3, 4, 5}, {6, 7}

{2, 5}

respinsa (formeaza ciclu)

{4, 7}

{1, 2, 3, 4, 5, 6, 7}

Tabelul 1 Algoritmul lui Kruskal aplicat grafului din Figura1a.

54

Multimea A este initial vida i se completeaza pe parcurs cu muchii acceptate (care nu


formeaza un ciclu cu muchiile deja existente n A). n final, multimea A va contine muchiile
{1, 2}, {2, 3}, {4, 5}, {6, 7}, {1, 4}, {4, 7}. La fiecare pas, graful partial <X, A> formeaza o
padure de componente conexe, obtinuta din padurea precedenta unind doua componente. Fiecare
componenta conexa este la randul ei un arbore partial de cost minim pentru vrfurile pe care le
conecteaza. Initial, fiecare vrf formeaza o componenta conexa. La sfarit, vom avea o singura
componenta conexa, care este arborele partial de cost minim cautat (Figura 1b).Ceea ce am
observat n acest caz particular este valabil i pentru cazul general.
n vectorul V vom sorta n ordine crescatoare numarul muchiilor n ordine crescatoare n
functie de costul fiecareia.n vectorul X vom retine pentru fiecare nod numarul componenetei din
care face parte acesta i care se schimba o data ce adaugam o noua muchie.Modificarea acestuia
se face n functie de apartenenta uneia dintre extremitati la un arbore cu mai mult de un nod.n
multimea B se retin numerele de ordine ale muchiilor ce apartin arborelui de cost minim.
Subiectul 37
Algoritmul lui Prim
Cel de-al doilea algoritm greedy pentru determinarea arborelui partial de cost minim al
unui graf se datoreaza lui Prim (1957). n acest algoritm, la fiecare pas, multimea A de muchii
alese impreuna cu multimea X a vrfurilor pe care le conecteaza formeaza un arbore partial de
cost minim pentru subgraful <X, A> al lui G. Initial, multimea W a vrfurilor acestui arbore
contine un singur vrf oarecare din X, care va fi radacina, iar multimea A a muchiilor este vida.
La fiecare pas, se alege o muchie de cost minim, care se adauga la arborele precedent, dand
nastere unui nou arbore partial de cost minim (deci, exact una dintre extremitatile acestei muchii
este un vrf n arborele precedent). Arborele partial de cost minim creste natural, cu cate o
ramura, pina cand va atinge toate vrfurile din X, adica pina cand W = X. Functionarea
algoritmului, pentru exemplul din Figura 6.1a, este ilustrata n Tabelul 2. La sfarit, A va contine
aceleai muchii ca i n cazul algoritmului lui Kruskal.
Pasul
Initializare

Muchia considerata

W
{1}

{2, 1}

{1, 2}

{3, 2}

{1, 2, 3}

{4, 1}

{1, 2, 3, 4}

{5, 4}

{1, 2, 3, 4, 5}

{7, 4}

{1, 2, 3, 4, 5, 6}

{6, 7}

{1, 2, 3, 4, 5, 6, 7}

Tabelul 6.2 Algoritmul lui Prim aplicat grafului din Figura 6.1a.
55

Descrierea algoritmului este data n continuare.


Pentru a obine o implementare simpla, presupunem ca: vrfurile din X sunt numerotate
de la 1 la n, X = {1, 2, ..., n}; matricea simetrica C da costul fiecarei muchii, cu C[i, j] = maxint,
dac muchia {i, j} nu exista. Folosim doi vectori,vectorul parintilor T[i] i un vector s[i]. Vectorul
T este vectorul tata n care, pentru fiecare nod i din X,T[i] este egal cu parintele lui i. Vectorul S
este definit astfel:
S[i]= 0 dac i apartine arborelui partial construit pana atunci
S[i]= K dac i nu apartine arborelui partial deja construit
-muchia de cost minim care uneste i cu un nod din graful deja construit este [i,k] cu k
neapartinand arborelui partial
Initial vectorul tata este 0 peste tot iar vectorul S este definit astfel:S[v]=0 i S[i]=v pentru
i<>v,unde v este vrful arborelui.Se alege apoi muchia de cost minim (i,j) care are numai o
extremitate n arborele partial construit adica S[i]=0 iar S[j]<>0.Se reactualizeaza cei doi
vectori:vectorul S pentru j adica S[j]=0 iar vectorul tata T[j]=S[j].Se reia cautarea muchiei de cost
minim dac nu au fost alese n-1 muchii.
Bucla principala se executa de n1 ori i buclele for din interior necesita un timp n O(n).
Algoritmul Prim necesita, deci, un timp n O(n2). Am vazut ca timpul pentru algoritmul lui
Kruskal este n O(m log n). Pentru un graf dens (adica, cu foarte multe muchii), se deduce ca m se
apropie de n(n1)/2. n acest caz, algoritmul Kruskal necesita un timp n O(n2 log n) i algoritmul
Prim este probabil mai bun. Pentru un graf rar (adica, cu un numar foarte mic de muchii), m se
apropie de n i algoritmul Kruskal necesita un timp n O(n log n), fiind probabil mai eficient
dect algoritmul Prim.

56

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