Un graf este o colecție de noduri si arce. Nodurile pot fi identificate prin chei, iar arcele reprezinta conexiuni intre noduri.
Un graf G poate fi notat G=(N,A), unde N e multimea nodurilor, iar A a arcelor.
Ordinul |G| unui graf G e dat de numarul nodurilor.
Arcul a ce leaga nodurile x si y se spune ca este incident cu x si y si se noteaza a~(x,y), iar x si y se spune ca sunt adiacente.
Gradul unui nod este egal cu numarul arcelor incidente lui. Un graf regulat are acelasi grad pentru toate nodurile.
Grafurile pentru care orice arc (x,y)=(y,x) sunt neorientate.
Bucla e un arc de forma a ~ (x,x).
Un graf simplu ( toate discutiile urmatoare se vor referi la astfel de grafuri ) nu accepta existenta arcelor multiple, deci intre orice doua noduri poate exista cel mult un arc.
Un graf G'=(N',A') este subgraf al unui graf G=(N,A) daca N' Ì N, A' Ì A si orice arc a' ~ (x,y) din A' conecteaza noduri din N' ( x si y sunt din N' ).
Un drum de la x la y e o succesiune de noduri conectate prin arce : x, n1, n2, n3,..., y, lungimea drumului fiind data de numarul de arce.
Un drum este simplu daca nodurile din drum sunt distincte (cu exceptia posibila a primului si ultimului ).
Un ciclu e un drum cu acelasi nod initial si final.
Doua noduri x si y se numesc conectate daca exista cel putin un drum intre ele.
Un graf este conex daca toate perechile sale de noduri sunt conectate.
Orice graf neconex este format din componenete conexe.
Se observa ca arborii sunt cazuri particulare ale grafurilor.
Un arbore de acoperire pentru un graf conex, este un subgraf care contine toate nodurile grafului, dar numai atâtea conexiuni câte sunt necesare formarii unui arbore. Pentru orice graf se poate gasi o padure de arbori de acoperire, cate unul pentru fiecare componenta conexa.
Un graf complet de ordinul n contine arcuri intre toate perechile ce se pot forma cu cele n noduri ( deci contine n (n-1)/2 arce ).
Un graf e rar daca are relativ putine arce si dens daca e aproape complet.
Un graf e orientat daca arcele sale au un sens precizat.
Un graf este ponderat daca arcelor sale li se asociaza cate o valoare.
Un graf ponderat orientat se numeste retea.
Se folosesc notatiile:
Tip_Element - tipul nodurilor, cu campurile de Tip_Cheie si Tip_Info
g - graf
indic_Nod - indicator la nod
indic_Arc - indicator la arc
e - variabila de Tip_Element
k,k1,k2 - variabile de Tip_Cheie
x - variabila de Tip_Info
b - variabila booleana.
Operatorii setului extins sunt:
- graful contine multimile ATOM si POZITIE
- g=(P,R,f) - unde
- P - subset finit al multimii POZITIE
- f - functie P-> ATOM
- R - relatie simetrica in P ( si ireflexiva daca nu se admit bucle )
- p,q - variabile de tip POZITIE
- e - variabila de tip ARC
- a - variabila de tip ATOM
Operatorii setului restrans sunt:
Se realizeaza mai intai o corespondenta intre numele nodurilor si multimea indicilor, in una din variantele :
Varianta de implementare cu matrice de adiacente: O varianta de implementare cu matrice de adiacente este data mai jos, graful aparand ca o structura ce contine contorul nodurilor, tabloul nodurilor si matricea de adiacente ( arce ). Tabloul nodurilor nu este ordonat dupa chei. Un nod nou se adauga in continuarea celor existente. Suprimarea unui nod se realizeaza prin copierea ultimei intrari peste cea care se sterge in tabloul Noduri, respectiv a conexiunilor ultimului nod peste cele ale nodului sters in Arce:
const NumarNoduri = .......; type TipCheie = .......; TipInfo = .......; TipElement = record Cheie: TipCheie; Info : TipInfo end; TipContor = 0..NumarNoduri; TipIndex = 1..NumarNoduri; TipTablouElem = array[TipIndex] of TipElement; TipMatrAdj = array[TipIndex,TipIndex] of boolean; Graf = record Contor : TipContor; Noduri : TipTablouElem; Arce : TipMatrAdj end; TipArc = record linie, coloana: TipIndex end; var g: Graf; procedure InserNod(var g: Graf;e: TipElement); { insertia unui nod izolat } var i,j: TipIndex; begin with g do begin contor := contor + 1; { se plaseaza e Noduri[contor] := e; in nodul nou} for i := 1 to contor do Arce[i,contor] := false { se initializeaza for j := 1 to contor do matricea de adiacente Arce[contor,j] := false pentru nodul nou } end {with} end; {InserNod} procedure InserArc(var g: Graf; indicArc: TipArc); begin g.Arc[indicArc.linie,indicArc.coloana] := true; g.Arc[indicArc.coloana,indicArc.linie] := true end; { InserArc } procedure SuprimNod(var g: Graf; indicNod: TipIndex); { suprima nodul dat impreuna cu toate arcele incidente } var i,j: TipIndex; begin with g do begin Noduri[indicNod] := Noduri[contor]; for j := 1 to contor do Arce[indicNod,j] := Arce[contor,j]; for i := 1 to contor do Arce[i,indicNod] := Arce[i,contor]; contor := contor - 1 end { with } end; { SuprimNod } procedure SuprimArc(var g: Graf; indicArc: TipArc); begin g.Arc[indicArc.linie,indicArc.coloana] := false; g.Arc[indicArc.coloana,indicArc.linie] := false end; { SuprimArc }
Construirea unui graf necesita cate un apel la InserNod pentru fiecare nod, respectiv cate un apel la InserArc pentru fiecare arc. Daca nodurile s-ar introduce ordonate dupa cheie in Noduri, localizarea unei chei poate fi facuta folosind cautarea binara.
Varianta a.) inceputurile listelor de inlantuiri se pastreaza intr-un tablou Stradj. Listele pot partaja acelasi nod final fictiv. Orice insertie se face la inceputul listei. Trebuie realizata o corespondenta intre numele nodurilor si multimea indicilor, prin functia index. Insertia unui arc implica insertia unui nod in fiecare din cele doua liste corespunzatoare nodurilor conectate.
const maxN = 100; type legatura = ^Nod; Nod = record nume: integer; { index } urm: legatura end; { nod } var Stradj: array[1..maxN] of legatura; Fiecare element din StrAdj ar putea retine si cheia nodului, astfel nemaifiind necesara o alta asociere: StrAdj:array[1..maxN] of record cheie:TipCheie; adj:legatura end;
Varianta b) Graful se implementeaza ca multilista: o lista a nodurilor contine, pentru fiecare nod, inceputul listei de adiacente. Nodurile pot fi pastrate ordonat sau nu, in lista nodurilor cat si in cele de adiacente. Se precizeaza ca valorile nodurilor sunt pastrate integral in lista de noduri, in lista de arce apar numai cheile.
type TipCheie = .....; TipInfo = .....; TipElement = record cheie: TipCheie; info : TipInfo end; PtrAdj = ^Adj; Adj = record cheieAdj: TipCheie; urmAdj : PtrAdj end; ptrNod = ^Nod; graf = ptrNod; Nod = record elem : TipElement; urmNod : ptrNod; incepAdj : PtrAdj end; TipArc = record v1,v2 : ptrNod end; var g : graf;Insertia unui arc nou, care conecteaza nodurile de chei k1 si k2, presupune insertia lui k1 in lista de adiacente a lui k2 si reciproc. Cel mai simplu este sa se faca insertiile la inceputul listelor de adiacente. Suprimarea unui arc precizat presupune extragerea celor doua noduri care sunt capetele arcului din doua liste de adiacente diferite. Pentru a suprima arcul care conecteaza nodurile k1 si k2 este necesar ca fiecare nod sa fie suprimat din lista de adiacente a celuilalt.
Suprimarea unui nod din graf presupune nu numai suprimarea nodului respectiv, ci si a tuturor arcelor incidente acestui nod. Fie k cheia nodului de suprimat. Pentru fiecare nod k2 din lista de adiacente a lui k, se suprima arcul (k,k2) prin stergerea lui k din lista de adiacente a lui k2 si pe k2 din lista de adiacente a lui k.
Varianta c.) Ceea ce este diferit fata de varianta anterioara este faptul ca in listele de adiacente nu apar cheile nodurilor, ci pointerii spre nodurile adiacente din lista (principala) de noduri ale grafului, algoritmii de prelucrare devenind mai simpli.
type POZITIE = ^CelulaListNod; PointListArc = ^CelulaListArc; CelulaListNod = record data : ATOM; { informatie apartinind nodului } urm : POZITIE; { urmatoarea celula in lista nodurilor } incep : PointListArc { pointer la lista de adiacente } end; CelulaListArc = record data : ...; { informatie atasata arcului } nod : POZITIE; { destinatia arcului } urm : PointListArc { inlantuirea in lista de arce } end; ARC = record nod1,nod2: POZITIE end; GRAF = POZITIE;In figura 1 sunt prezentate schematic structurile de adiacente pentru variantele b si c.