Issuu on Google+

Grafs Miguel テ]gel Sicilia Urbテ。n Elena Garcテュa Barriocanal P06/05001/00582 Mテイdul 8


© FUOC • P06/05001/00582 • Módulo 8

Grafs

Índex

Introducció ..............................................................................................

5

Objectius ...................................................................................................

6

1. El concepte de graf ............................................................................

7

2. El tipus abstracte de dades Graf .................................................... 11 2.1. Grafs dirigits i no dirigits ................................................................ 12 2.2. Grafs bipartits o relacions ............................................................... 14 3. Interfícies Java per a grafs dirigits i no dirigits ....................... 16 4. Implementació de grafs .................................................................. 20 4.1. Mitjançant matrius d’adjacència .................................................... 20 4.2. Mitjançant llistes d’adjacència ....................................................... 22 5. Exemple d’ús: TAD Acadèmia ........................................................ 25 Resum ........................................................................................................ 28 Exercicis d’autoavaluació .................................................................... 29 Solucionari ............................................................................................... 30 Glossari ..................................................................................................... 30 Bibliografia .............................................................................................. 30


© FUOC • P06/05001/00582 • Módulo 8

5

Introducció

En aquest mòdul s’introdueix el tipus abstracte de dades Graf, en les dues variants: grafs dirigits i grafs no dirigits, així com la seva implementació eficient mitjançant llistes d’adjacència. L’exposició dels conceptes teòrics es limita a les definicions fonamentals, ja que es pressuposen els coneixements bàsics sobre teoria de grafs de l’assignatura Matemàtica discreta. Tampoc no ens aturem en els algorismes fonamentals de grafs com ara recorreguts, obtenció del camí mínim en un graf, o obtenció d’arbres d’expansió mínims, ja que aquests algorismes s’expliquen també en

a

Matemàtica discreta.

Aquest mòdul pretén que sigueu capaços de traslladar els vostres coneixements sobre els grafs com a estructura matemàtica a la resolució de problemes mitjançant programes. Per a això teniu disponibles les biblioteques creades que proporcionen algunes interfícies de programació.

Grafs


© FUOC • P06/05001/00582 • Módulo 8

6

Objectius

Els objectius que s’espera que pugueu assolir amb els continguts d’aquest mòdul són els següents: 1. Conèixer el tipus abstracte de dades Graf, i comprendre’n la utilitat per a modelitzar problemes en què hi ha relacions entre elements que no són lineals (com en les llistes), ni tampoc jeràrquiques (com en els arbres). D’aquesta manera, els grafs es poden considerar una generalització de les altres estructures. 2. Recordar el concepte de graf, en les seves variants dirigida i no dirigida, i els conceptes fonamentals que hi fan referència. 3. Conèixer la implementació de l’estructura de Graf mitjançant llistes d’adjacència, com a alternativa eficient a la implementació mitjançant matrius d’adjacència. 4. Introduir la part de les biblioteques de propòsit general en Java que implementen el tipus abstracte de dades Graf. Concretament, les biblioteques esmentades tenen un paquet denominat grafs en què s’ubiquen les interfícies i les classes que permeten la programació amb estructures de tipus graf.

Grafs


© FUOC • P06/05001/00582 • Módulo 8

7

1. El concepte de graf

En moltes situacions, ens trobem amb un conjunt d’elements entre els quals s’estableixen certes relacions. Per exemple, a qualsevol universitat, els alumnes estan relacionats amb les assignatures que estudien, i els professors amb les que ensenyen. De la mateixa manera es poden representar els llaços d’amistat en una comunitat de veïns. També es poden considerar relacions les connexions de vol entre països europeus, o les interconnexions entre els components d’un circuit electrònic.

Una característica fonamental d’aquestes relacions és que cada enllaç involucra dos elements, és a dir, les relacions es poden representar per parells de números. Des de la perspectiva del paradigma de l’orientació a objectes, aquestes relacions no són cap altra cosa que associacions binàries (segons la terminologia d’UML), és a dir, associacions entre dues classes. Un cas especial són les associacions reflexives, en les quals, els dos extrems de l’associació binària són la mateixa classe.

Si considerem que els objectes enllaçats en virtut de la relació són nodes o vèrtexs en una xarxa, i els enllaços són les arestes o arcs que connecten els nodes en aquesta xarxa, tindrem el concepte de graf. De fet, un diagrama d’objectes UML que representa instàncies i enllaços concrets d’una associació és un graf.

Per exemple, si volem representar les relacions d’amistat entre els estudiants d’una universitat, ho podem fer mitjançant el model UML de la figura 1.

Figura 1

Doncs bé, les instàncies i els enllaços concrets que es produeixin d’acord amb aquest model en una situació determinada, formaran un graf. En la figura 2, es mostra un exemple de diagrama d’objectes i la representació equivalent en termes de nodes i arestes, segons la notació gràfica habitual que se sol utilitzar per als grafs.

Grafs


© FUOC • P06/05001/00582 • Módulo 8

8

Figura 2

Els grafs es poden subdividir en dues categories importants: els grafs dirigits i els grafs no dirigits. En un graf dirigit, cal tenir en compte el sentit de la relació, mentre que en els grafs no dirigits, el sentit és indiferent.

esGermaDe i esClientDe La relació esGermaDe és una relació recíproca o simètrica, és a dir, si en Joan esGermaDe Pep, llavors en Pep ha de complir que en Pep esGermaDe Joan. Dit d’una altra manera, és igual que expressem la relació com esGermaDe(Pep,Joan) que com esGermaDe(Joan,Pep), el sentit de la relació no és rellevant. Tanmateix, si tenim una relació denominada esClientDe entre empreses, el sentit de la relació sí que aporta una informació rellevant, i el fet que l’empresa A sigui clienta de l’empresa B no implica necessàriament que l’empresa B sigui clienta de l’empresa A. El diagrama de la figura 3 representa un possible graf dirigit amb la relació esClientDe, en el qual la presència de puntes en les fletxes representa el sentit de cada relació particular; per exemple, e3 és client de e5 i de e4, i e5 i e6 són clients l’un de l’altre. Figura 3

Grafs


© FUOC • P06/05001/00582 • Módulo 8

9

Una variant addicional dels grafs (siguin dirigits o no) són els grafs valorats. En aquests grafs, les arestes tenen associat un valor (habitualment un número, encara que no necessàriament) que representa informació sobre la aresta en si.

L’exemple més habitual d’aquest tipus de grafs és el de la representació de les distàncies entre ciutats. Per exemple, el graf de la figura 4 representa algunes distàncies (en quilòmetres) entre ciutats espanyoles. Figura 4

El cas dels grafs valorats és anàleg al de les classes de l’associació o atributs de l’associació en UML. Així, el graf de la figura 4 podria deduir-se d’un diagrama d’objectes corresponent al diagrama de classes de la figura 5.

Figura 5

Una altra subdivisió possible i important dels grafs seria la dels grafs bipartits. En els grafs bipartits, no tots els nodes són iguals. És a dir, hi ha nodes de dos tipus diferents, i només es permeten relacions entre nodes de diferent tipus.

Grafs


© FUOC • P06/05001/00582 • Módulo 8

10

Per exemple, en el cas de les relacions professorat-alumnat en educació infantil, del tipus teComAProfessor, no és possible que un estudiant tingui com a docent un altre estudiant, ni que un docent tingui com a estudiant un altre docent (sempre suposant que no hi pot haver un estudiant que, al seu torn, sigui docent en la vida real). La representació d’aquesta associació en UML es mostra en la figura 6. Figura 6

I el diagrama de la figura 7 mostra un graf bipartit d’exemple, que representa relacions teComAProfessor entre els alumnes a1, a2 i a3, i els professors p1 i p2. Figura 7

És important ressaltar que una relació de tipus “molts a molts” en orientació a objectes defineix de manera implícita un graf d’instàncies connectades. En el cas de les associacions entre dues classes diferents, tenim un graf bipartit, sempre que aquestes no siguin reflexives, com l’associació de la classe Ciutat que ha aparegut més amunt.

Grafs


© FUOC • P06/05001/00582 • Módulo 8

11

Grafs

2. El tipus abstracte de dades Graf

El concepte matemàtic de graf es defineix en relació amb dos conjunts. Un conjunt de vèrtexs o nodes, i un conjunt d’arestes, arcs o enllaços. Els nodes són els objectes del problema que estem considerant, i les arestes representen les relacions. Graf com a tipus abstracte de dades És important tenir en compte des d’ara que un graf és un tipus abstracte de dades molt general. De fet, els arbres i les estructures lineals com les llistes es poden considerar grafs connexos en els quals les relacions permeses entre els nodes estan restringides d’alguna manera. Un arbre binari, per exemple, seria un graf dirigit en què cada node només pot tenir enllaços que “en surten”, com a màxim, a uns altres dos nodes; i només pot tenir un enllaç que “hi entra” i, a més, no permet cicles en la seqüència d’arestes. En el cas d’una llista, tindríem un graf dirigit en què cada element només pot tenir, a tot estirar, un enllaç que “en surt” i un altre que “hi entra”.

Hi ha dos tipus fonamentals de grafs: dirigits i no dirigits. És important tenir molt clares les seves diferències, ja que s’apliquen a la resolució de problemes amb requisits diferents, i alguns algorismes només s’utilitzen per a un dels dos tipus de graf. A continuació oferim una possible definició matemàtica dels dos tipus de grafs.

Un graf no dirigit G es defineix com el parell ordenat G = (V, A), en què V és un conjunt finit no buit de nodes o vèrtexs, i A és un conjunt d’arestes o arcs entre aquests nodes, amb la propietat que cada aresta en A és un parell no ordenat d’elements (vèrtexs) a V.

Encara que la definició matemàtica de graf requereix que hi hagi almenys un vèrtex, en la pràctica, les implementacions del tipus abstracte de dades solen permetre que no tingui nodes, ja que en crear un objecte de tipus graf, encara no s’ha “omplert” amb la informació del graf, i estarà, provisionalment, buit de nodes. D’aquesta manera, en un graf no dirigit, una aresta és un conjunt {x, y}, en què x, y ∈ V, i x ≠ y. Per coherència amb la notació habitual dels grafs dirigits, se sol utilitzar una notació de parells (x, y) en lloc de la notació de conjunts {x, y}, però sempre cal tenir en compte que (x, y) i (y, x) es consideren la mateixa aresta. Vegem ara la definició de graf dirigit i assenyalem-ne les diferències amb els grafs no dirigits.

Parell ordenat i parell no ordenat Considerarem el parell ordenat (A, B) diferent de (B, A) si A ≠ B. En canvi, el parell no ordenat (A, B) és igual a (B, A).


© FUOC • P06/05001/00582 • Módulo 8

12

Grafs

Un graf dirigit G es defineix com el parell ordenat G = (V, A), en què V és un conjunt finit no buit de nodes o vèrtexs, i A és un conjunt d’arestes o arcs entre aquests nodes, amb la propietat que cada aresta en A és un parell ordenat d’elements (vèrtexs) a V.

En termes matemàtics, el conjunt d’arestes A d’un graf dirigit és una relació binària sobre V, és a dir, és un subconjunt del producte cartesià V × V. Enllaços reflexius De les dues definicions anteriors, es dedueix que en un graf dirigit, hi poden haver enllaços “reflexius”, és a dir, arestes del tipus (a, a). Això no té sentit en el cas de grafs no dirigits, ja que una aresta d’aquest tipus en un graf no dirigit no representaria informació rellevant. Això no obstant, hi pot haver cicles dins dels dos tipus de grafs, és a dir, seqüències d’arestes que formen un camí tancat dins del graf.

En la introducció d’aquest mòdul, s’han proporcionat exemples de la representació gràfica habitual per a grafs no dirigits i grafs dirigits, i s’han utilitzat puntes

a

de fletxa per a indicar la destinació de l’aresta en el cas dels grafs dirigits.

En tots dos casos (graf dirigit o no), pot ser que hi hagi una informació associada a cada aresta del graf. En aquest cas estaríem parlant de grafs valorats.

Un graf valorat o graf amb pesos és aquell en el qual tenim informació associada a cada una de les arestes del graf.

El tipus abstracte de dades graf tindrà, per tant, dues variants fonamentals: graf dirigit i graf no dirigit.

2.1. Grafs dirigits i no dirigits Un TAD Graf no dirigit es pot definir d’acord amb el següent conjunt mínim d’operacions d’inserció i eliminació. Per a identificar els vèrtexs, és necessari que tinguin alguna dada distintiva, com un nombre o una cadena de caràcters, que aquí denominarem nom o etiqueta del vèrtex. En principi, el tipus del valor associat als vèrtexs pot ser qualsevol, per la qual cosa hem indicat el tipus T com a genèric en la descripció següent. TAD GrafNoDirigit<TElem, TEtiqueta> Utilitza: Vertex, ArestaNoDirigida crearGraf(): Graf Crea un graf buit. @pre Cap @post El graf està buit

Terminologia En molts textos es considera que un graf “a seques” és un graf no dirigit, i els grafs dirigits (o digrafs) es consideren una classe especial de graf.


© FUOC • P06/05001/00582 • Módulo 8

13

crearVertex(v: valor): GrafNoDirigit Inclou un vèrtex amb un determinat valor en el graf. @ pre No hi ha un altre vèrtex amb la mateixa etiqueta. @post El graf té un vèrtex amb el valor especificat. El vèrtex esmentat no està connectat amb cap altre vèrtex del graf.

inserirAresta(n: Vertex, m: Vertex): GrafNoDirigit Inclou una aresta entre els vèrtexs n i m en el graf. @pre Els vèrtexs n i m han de formar part del graf. No hi ha una aresta entre els vèrtexs m i n. @post: El graf té una aresta entre m i n.

eliminarVertex(v: Vertex): GrafNoDirigit Elimina del graf el vèrtex especificat i totes les arestes que hi incideixen. @pre Existeix el vèrtex especificat en el graf. @post El graf no conté el vèrtex especificat ni cap de les arestes en què participa.

eliminarAresta(a: Aresta): GrafNoDirigit Elimina del graf l’aresta especificada. @pre Existeix en el graf l’aresta especificada. @post El graf no conté l’aresta especificada.

adjacents(m: Vertex): Iterador Torna un iterador amb els vèrtexs adjacents. @pre Existeix el vèrtex especificat en el graf. @post S’obté un iterador amb els vèrtexs adjacents al vèrtex especificat. El graf no modifica el seu estat.

obtenirVertexs(): Iterador Torna un iterador sobre la col·lecció de vèrtexs del graf. @pre Cap. @post Torna un iterador sobre la col·lecció de vèrtexs del graf.

obtenirArestes(): Iterador Torna un iterador sobre la col·lecció d’arestes del graf. @pre Cap. @post Torna un iterador sobre la col·lecció d’arestes del graf.

Les operacions descrites permeten la manipulació bàsica dels vèrtexs i les arestes del graf. Sens dubte, és convenient que les implementacions del tipus abstracte continguin a més altres operacions per a una manipulació més fàcil dels grafs, però aquestes dependran de la representació escollida i del llenguatge de programació.

Grafs


© FUOC • P06/05001/00582 • Módulo 8

14

Exemples d’aquestes operacions poden ser l’obtenció directa del grau del graf, o el nombre d’arestes que conté. La descripció anterior es basa en dos tipus abstractes de dades, que són Vèrtex i Aresta, i que tindran les operacions necessàries per a una fàcil manipulació, com poden ser l’obtenció dels vèrtexs a partir d’una aresta o l’obtenció de les arestes que incideixen en un vèrtex. La definició de grafs valorats a partir del que s’ha exposat és immediata, ja que la biblioteca de TAD de l’assignatura implementa les arestes de manera que si són etiquetades o són valorades (per a obtenir grafs valorats) porten associat un valor corresponent a l’etiqueta. Si l’aresta no és valorada, aquest valor serà

a

‘nul’.

El TAD GrafDirigit té molt en comú amb el TAD GrafNoDirigit, ja que les diferències rauen en el tipus d’aresta, que es pot canviar per un nou tipus ArestaDirigida. D’aquesta manera, totes les operacions bàsiques de GrafNoDirigit continuen servint per a GrafDirigit. Ho veurem amb més detall en la implementació, que es presenta més endavant.

2.2. Grafs bipartits o relacions

Una classe especial de graf són els grafs bipartits. En els grafs bipartits, el conjunt dels vèrtexs V no es considera homogeni, ja que conté dos “tipus” de nodes clarament diferenciats i, a més, es prohibeixen les “relacions” (és a dir, les arestes) entre nodes del mateix tipus.

Un graf G = (V, A) és un graf bipartit si hi ha una partició del conjunt de vèrtexs, és a dir, si V = V1 ∪ V2 amb V1 ∩ V2 = ∅, de manera que les arestes només connecten vèrtexs que estan en subconjunts diferents, és a dir, tota aresta (x, y) compleix que (x ∈ V1 ∧ y ∈ V2) ∨ (x ∈ V2 ∧ y ∈ V1).

Els grafs bipartits es poden utilitzar conceptualment per a representar relacions entre dos conjunts d’elements o classes. De fet, tota relació d’associació entre dues classes en el paradigme de l’orientació a objectes es pot representar mitjançant un graf bipartit. Els subconjunts que formen la partició es poden representar en llenguatges orientats a objectes com dues classes diferents, o també poden ser subconjunts disjunts d’instàncies de la mateixa classe.

Un graf bipartit és un tipus especial de graf, que es pot descriure de manera abstracta restringint simplement la creació d’arestes i de vèrtexs. Per exemple, amb la definició que proposem a continuació:

Grafs


© FUOC • P06/05001/00582 • Módulo 8

15

TAD GrafNoDirigitBipartit<A,B> { @pre El valor associat al vèrtex ha de ser del tipus A o del tipus B. @post Afegeix el vèrtex amb el valor associat al graf} inserirVertex(g:Graf, valor:A):Graf inserirVertex(g:Graf, valor:B):Graf @pre: Els vèrtexs n i m han de formar part del graf i ser de diferent tipus, d'entre els tipus A i B. No hi ha una aresta entre els nodes m i n. @post El graf conté una aresta entre els vèrtexs m i n} inserirAresta(g:Graf, n:Vertex, m:Vertex):Graf ... }

D’aquesta manera, es garanteix que els valors associats als vèrtexs seran dels tipus que accepta el graf concret, i es restringeixen les arestes de manera que connectin elements de diferents tipus.

Grafs


© FUOC • P06/05001/00582 • Módulo 8

16

3. Interfícies Java per a grafs dirigits i no dirigits

En aquest apartat, introduirem les interfícies fonamentals de la biblioteca en Java de TAD de l’assignatura que implementen els conceptes exposats anteriorment. Començarem per l’element més senzill, el vertex. L’única funcionalitat especial que demanem a aquests elements serà la possibilitat d’accedir a la informació que tenen associada, i que abans hem anomenat etiqueta. La interfície mínima quedaria, doncs, de la manera següent: uoc.ei.tads.grafs.Vertex public interface Vertex<TElem> { public TElem obtenirValor(); }

Com que no hi poden haver dos grafs amb la mateixa “etiqueta” o identificació, en les implementacions de Vèrtex és habitual trobar una redefinició del mètode equals, que permet comparar dos objectes. Per a la implementació en Java de grafs dirigits i no dirigits, és convenient (encara que no imprescindible) utilitzar TAD auxiliars ArestaNoDirigida i ArestaDirigida que simplifiquen la interfície dels grafs, com es va indicar en la descripció d’operacions de l’apartat anterior. A més, tots dos es poden considerar com a tipus més específics del concepte abstracte d’Aresta. Aquesta seria una possible especificació de la interfície Aresta a Java: uoc.ei.tads.grafs.Aresta public interface Aresta<TEtiqueta,TElem> { /** Obté el valor associat a l’aresta. * @returns null si el graf és no valorat. */ public Object obtenirEtiqueta(); /** Estableix el valor associat a l’aresta. */ public void establirEtiqueta(TEtiqueta v); /** Indica si l’aresta incideix en el vèrtex v. */ public boolean incideixEnVertex(Vertex<TElem> v); }

Segons aquest disseny, qualsevol aresta pot tenir un valor associat. Per això, quan es programa amb aquesta biblioteca, si volem utilitzar grafs no valorats, simplement hem de deixar totes les arestes amb el seu valor per defecte, que

Grafs


© FUOC • P06/05001/00582 • Módulo 8

17

ha de ser ‘null’. Les arestes no dirigides simplement tindran operacions per a obtenir cada un dels vèrtexs que connecten, per exemple:

public interface ArestaNoDirigida<TEtiqueta,TElem> extends Aresta<TEtiqueta,TElem> { public Vertex<TElem> obtenirVertex1(); public Vertex<TElem> obtenirVertex2(); }

Tanmateix, en la interfície de les arestes dirigides, s’ha d’expressar clarament que un vèrtex és a l’origen i l’altre a la destinació, per exemple:

public interface ArestaDirigida<TEtiqueta,TElem> extends Aresta<TEtiqueta,TElem> { public Vertex<TElem> obtenirVertexOrigen(); public Vertex<TElem> obtenirVertexDestinacio(); }

Encara que en aparença totes dues interfícies són molt semblants, cal destacar que les responsabilitats de les classes que les implementen tenen diferències subtils però importants. Concretament, la implementació d’una aresta no dirigida pot tornar com a vèrtex1 qualsevol dels dos, mentre que en el cas d’arestes dirigides, el vèrtex origen i destinació s’especificaran clarament mitjançant el constructor, o mitjançant mètodes que n’indiquin clarament la funció.

Les interfícies dels grafs també seran lleugerament diferents segons si el graf és dirigit o no. Per això és convenient agrupar en una interfície Graf allò que és comú a totes dues variants. Una especificació en llenguatge Java del TAD Graf és la interfície següent:

public interface Graf<TElem,TEtiqueta> { /** * Obté un iterador als vèrtexs del graf. */ public Iterador<Vertex<TElem>> vertexs(); /** * Obté un iterador a les arestes del graf. */ public Iterador<? extends Aresta<TEtiqueta,TElem>> arestes(); /** * Crea un nou vèrtex amb un valor associat * i l'inclou en el graf. */

Grafs


© FUOC • P06/05001/00582 • Módulo 8

18

public Vertex<TElem> crearVertex(Object valor); /** * Elimina el vèrtex del graf (si hi era), * incloent totes les arestes en què participa. */ public void eliminarVertex(Vertex<TElem> n); /** * Elimina l’aresta del graf (si hi era) */ public void eliminarAresta(Aresta<TEtiqueta,TElem> a); /** * Obté un iterador als vèrtexs adjacents al vèrtex v. */ public Iterador<Vertex<TElem>>adjacents(Vertex<TElem> v); }

Com es veu en la interfície anterior, l’operació per a crear una aresta s’ha omès, ja que és la part que varia en els casos dirigit i no dirigit. Així, en el cas d’un graf no dirigit tindríem la definició següent:

public interface GrafNoDirigit<TElem,TEtiqueta> extends Graf<TElem,TEtiqueta> { /** * Crea i inclou una nova aresta en el graf. */ public ArestaNoDirigida<TEtiqueta,TElem> crearAresta(Vertex<TElem> n, Vertex<TElem> m); //… }

En canvi, en el cas d’un graf dirigit, tindríem una definició com la següent:

public interface GrafDirigit<TElem,TEtiqueta> extends Graf<TElem,TEtiqueta> { /** * Crea i inclou una nova aresta en el graf. */ public ArestaDirigida<TEtiqueta,TElem> crearAresta(Vertex<TElem> n, Vertex<TElem> m); /** * Obté un iterador a les arestes amb origen en v. */

Grafs


© FUOC • P06/05001/00582 • Módulo 8

19

public Iterador<? extends ArestaDirigida<TEtiqueta,TElem>>arestesAmbOrigenEn(Vertex<TElem> v); /** * Obté un iterador a les arestes amb destinació en v. */ public Iterador<? extends ArestaDirigida<TEtiqueta,TElem>> arestesAmbDestinacioEn(Vertex<TElem> v); }

Fixeu-vos que, en el cas d’un graf dirigit, té sentit sol·licitar les arestes “amb destinació” o “amb origen” en un determinat vèrtex, mentre que en el cas de grafs no dirigits, això no té cap sentit.

Grafs


© FUOC • P06/05001/00582 • Módulo 8

20

4. Implementació de grafs

En aquest apartat tractarem dos mètodes possibles per a la implementació de grafs: per matrius d’adjacència i per llistes d’adjacència.

4.1. Per matrius d’adjacència La implementació més directa i senzilla d’un graf és per matrius d’adjacència. Una matriu d’adjacència emmagatzema la presència o absència d’una aresta entre cada parell possible de vèrtexs en el graf. En el cas d’un graf valorat, a més de la presència o absència d’aresta, s’emmagatzemarà el “pes” de cada aresta. En les implementacions concretes, l’absència d’aresta es pot indicar amb una referència nul·la o amb un valor especial. La figura 8 és un exemple de com es representaria mitjançant una matriu d’adjacència un graf dirigit no valorat, en què el valor 1 representés la presència d’una aresta, i la casella en blanc en representés l’absència. Així, l’aresta del node 8 al node 5 es representaria per 1 en la posició de la matriu (8, 5), mentre que la casella (5, 8) romandria en blanc, la qual cosa indicaria que no hi ha una aresta en la direcció del vèrtex 5 al vèrtex 8. Figura 8

La representació del graf en forma de conjunts serà la següent: G = (V, A) V = {1, 4, 5, 7, 8, 9} A = {(1, 5), (5, 1), (4, 5), (5, 9), (8, 5), (8, 7), (7, 9), (9, 7)} En el cas d’un graf no dirigit, s’ocuparà només una part de la matriu, per sota o per sobre de la seva diagonal principal, per a representar les arestes.

Grafs


© FUOC • P06/05001/00582 • Módulo 8

21

En la representació que acabem de veure, la matriu té una mida fixa, que depèn de la mida del domini dels valors associats als vèrtexs (que anteriorment hem anomenat etiquetes). En l’exemple numèric que acabem de veure, suposant que un node pot tenir com a valor associat un nombre enter positiu, seria necessari tenir una matriu de D × D, essent D el nombre d’enters positius diferents que es podrien representar en el llenguatge de programació; una mida molt gran, especialment en comparació amb la petita quantitat d’arestes emmagatzemades realment en l’exemple. L’avantatge fonamental d’aquesta representació per al cas dels enters és que podríem conèixer si hi ha una aresta entre dos vèrtexs determinats amb una sola operació –és a dir, temps constant O(1)– simplement indexant la matriu. Això no obstant, aquest avantatge comporta l’inconvenient que en la majoria dels casos es “desaprofiten” gran part de les posicions de la matriu. Una implementació alternativa podria emmagatzemar només posicions per als valors que actualment estan inclosos en el graf, i obtenir una representació compacta. L’exemple anterior es representaria, llavors, d’una manera semblant a la que es mostra en la figura 9. Figura 9

Tanmateix, aquesta última representació té l’inconvenient que els vèrtexs del graf (o almenys el seu nombre) s’han de conèixer a priori, ja que afegir un vèrtex addicional requeriria redimensionar la matriu, cosa que en els llenguatges com Java implica la creació d’una nova matriu més gran i la còpia dels valors de l’antiga a la nova (en llenguatges de tipus Pascal no es pot realitzar simplement amb matrius). Com que aquesta operació és molt costosa en temps, no és una implementació adequada. Hi ha un cas particular en què les matrius d’adjacència són una representació adequada. És el cas dels grafs “densos”, és a dir, d’aquells que tenen un nombre d’arestes molt alt (en relació amb el nombre de vèrtexs). És a dir, aquesta representació convé quan en la matriu d’adjacència hi ha poques caselles en blanc, la qual cosa significa “poc malbaratament de memòria”. Això no obstant, no hi ha gaires aplicacions que tinguin matrius d’adjacència molt ocupades, i quasi sempre tenen matrius més o menys esparses en més o menys grau.

Grafs


22

© FUOC • P06/05001/00582 • Módulo 8

Pel que acabem de veure, podem formular la següent regla general respecte a la implementació dels grafs.

La implementació d’un graf amb matrius d’adjacència només és convenient, en termes d'eficiència espacial (de consum de memòria), en el cas que el graf sigui dens; és a dir, quan |A| ≈ |V|2 (quan el nombre d’arestes és aproximadament igual o proper al màxim nombre d’arestes possibles).

La regla anterior val per a grafs dirigits. En el cas de grafs no dirigits, les matrius d’adjacència només seran convenients quan:

A ≈

V! 2 ⋅ ( V − 2)!

essent A el nombre d’arestes d’un graf no dirigit “dens”. Cal tenir en compte que, en aquest cas, encara es desaprofita una quantitat considerable de posicions, ja que només s’ocuparà una part de la matriu (per sota o per sobre de la diagonal principal). L’expressió anterior per a estimar el càlcul del nombre d’arestes que un graf no dirigit ha de tenir per a ser considerat dens és molt precisa, però es pot simplificar amb |A| = |V|2/2, és a dir, la meitat del nombre d’arestes que pot tenir un graf dirigit dens; ja que en un graf no dirigit entre dos vèrtexs qualssevol només hi pot haver una aresta, mentre que en un de dirigit, n’hi pot haver un parell: una en cada direcció. Òbviament, l’avantatge de la representació original amb matrius d’adjacència és que el temps necessari per a trobar si hi ha o no hi ha una aresta determinada en el graf és O(1), ja que s’implementa simplement indexant la matriu amb les etiquetes dels dos vèrtexs que s’estan considerant.

4.2. Per llistes d’adjacència Les implementacions de grafs per matrius d’adjacència –com la que hem vist en el subapartat anterior– requereixen una estructura de dades de mida |D| × |D|, o amb una implementació compacta, de |V| × |V|. Per exemple, en el cas de relacions de “préstec d’apunts” entre els estudiants d’una classe de 30 alumnes, hauríem d’utilitzar una estructura de 30 × 30 = 900 posicions per a allotjar totes les possibles arestes dins del graf dirigit resultant. En la pràctica, això sovint redueix molt l’eficiència en espai de memòria, ja que hi ha un gran nombre de posicions de la matriu que estan buides, perquè molts grafs són esparsos, és a dir, tenen una proporció relativament baixa d’arestes respecte a totes les possibles.

Grafs


© FUOC • P06/05001/00582 • Módulo 8

23

La implementació de grafs mitjançant llistes d’adjacència és una alternativa més eficient per a l’emmagatzemament de grafs. La idea fonamental d’aquesta implementació és la d’emmagatzemar una llista amb els vèrtexs del graf i que, al seu torn, cada vèrtex tingui associada una llista amb les arestes que porten a nodes adjacents.

En la implementació d’un graf amb llistes d’adjacència només s’utilitza espai de memòria per als vèrtexs i arestes que formen part en un moment donat del graf. Això contrasta amb la implementació mitjançant matrius d’adjacència, en la qual es consumeix espai per a totes les possibles arestes dins del domini del tipus de dades de les etiquetes dels nodes.

Considerant el mateix graf que vam posar com a exemple anteriorment, la representació quedaria com mostra la figura 10. Figura 10

La idea d’aquesta implementació és representar en primer lloc els vèrtexs mitjançant una llista o una matriu (array), que es mostra en la part esquerra de la figura 10. Llavors, les arestes es representen mitjançant la llista que està associada a cada vèrtex, que conté les etiquetes dels vèrtexs adjacents. Així, per exemple, en la figura veiem que la llista encadenada associada al vèrtex 5 conté les etiquetes 1 i 9. Aquesta implementació té l’avantatge que només es representen les arestes que realment formen part del graf. Si el graf fos valorat, el pes de l’aresta s’emmagatzemaria com a informació addicional en cada node de les llistes. L’estructura que emmagatzema els vèrtexs pot ser ordenada o no, i les pròpies llistes també. Per exemple, si la llista de vèrtexs i les llistes d’adjacència estan totes ordenades, l’operació de buscar un vèrtex en el graf ocuparia un temps O(log |V|) + O(max(|adjacents(vi)|)), si considerem que adjacents(vi) és el conjunt de vèrtexs adjacents al vèrtex vi. Això resulta en el fet que la recerca d’una aresta té una complexitat superior a O(1) però inferior a O(|A|).

Grafs


© FUOC • P06/05001/00582 • Módulo 8

24

En la biblioteca de TAD de l’assignatura es pot trobar una implementació de grafs utilitzant llistes d’adjacència. En aquesta implementació s’utilitza una llista doblement enllaçada per a emmagatzemar les arestes i una taula de dispersió per a emmagatzemar els vèrtexs, si bé per a això es podria haver utilitzat qualsevol altre tipus de taula de dispersió. L’ús de llistes per a emmagatzemar les arestes es pot substituir per altres estructures que proporcionin un accés més eficient en alguns casos, com seria, per exemple, un arbre AVL. Activitat Plantegeu un esquema de com es duria a terme aquesta implementació, i analitzeu-ne els principals avantatges des del punt de vista de l’eficiència.

Grafs


© FUOC • P06/05001/00582 • Módulo 8

25

5. Exemple d’ús: TAD Acadèmia

Una acadèmia d’electricitat encarrega al seu alumne més avantatjat la construcció del TAD Acadèmia que li permeti representar el seu pla d’estudis, l’alumnat i el professorat. Els alumnes de l’acadèmia aconsegueixen el títol quan han aprovat totes les assignatures de la titulació en la qual estan matriculats. Les assignatures, que tenen una càrrega lectiva en crèdits, actuen de “clau” entre si, de manera que una assignatura en pot “tancar” més d’una i, al seu torn, “ser tancada” per més d’una. Per exemple, haver aprovat les assignatures d’Electrònica bàsica i Sistemes digitals de primer curs és condició indispensable per a poder aprovar l’assignatura Sistemes digitals avançats de segon curs. D’altra banda, la política docent i de contractació de l’acadèmia impedeix que hi hagi més d’un grup d’alumnes per cada assignatura. El nombre d’assignatures A del pla d’estudis de la titulació que es dóna en l’acadèmia és d’unes quantes desenes, i com que és una acadèmia molt prestigiosa, té uns quants centenars d’alumnes (N) que poden estar matriculats a diverses assignatures simultàniament (denotem per AM el nombre d’assignatures de què s’ha matriculat un alumne, que no es preveu que superi l’ordre d’una dotzena, o una mica més, en el cas més ambiciós). Els alumnes no s’esborren mai de l’estructura, encara que ja hagin aconseguit la titulació. Una vegada que un alumne supera una assignatura, aquesta passa a formar part del seu expedient acadèmic, juntament amb la qualificació que ha obtingut. Els professors de l’acadèmia, que són pocs (un nombre P estable encara que desconegut), imparteixen un nombre petit (NA) d’assignatures. Els docents sempre imparteixen les mateixes assignatures, sense deixar-ne cap ni incorporar-ne de noves. En el TAD s’ha d’emmagatzemar quines assignatures imparteix cada professor, tenint en compte que cada semestre s’ha d’actualitzar aquesta dada, ja que sí que es poden produir baixes d’alguns professors i noves incorporacions. El TAD Acadèmia ha de permetre: 1) Crear l’estructura. Aquesta operació crea l’estructura i hi inclou les assigna-

tures disponibles, la relació entre aquestes, i els professors. 2) Afegir un alumne de nou ingrés. 3) Permetre a un alumne matricular-se d’una assignatura, sempre que tingui

aprovades les que tanquen l’asignatura en què es vol matricular. 4) Actualitzar l’expedient de un alumne, afegint-hi una nova assignatura

aprovada amb una determinada qualificació.

Grafs


© FUOC • P06/05001/00582 • Módulo 8

26

5) Anotar que un docent imparteix una assignatura. 6) Consultar l’expedient d’un alumne. 7) Calcular la càrrega docent, és a dir, el nombre de crèdits total, que impar-

teix un docent. Per a realitzar el càlcul n’hi ha prou de sumar els crèdits de les assignatures que imparteix. Un exemple simplificat de les dades que es requereixen seria el següent: • Tenim les assignatures A1, A2, A3, A4, i A5 en què la A1 és clau de A2 i A3 (és a dir, no es poden cursar ni A2 ni A3 sense aprovar abans A1). Al seu torn, A2 i A3 són clau de A4, i A4 és clau de A5. Totes les assignatures tenen 3,5 crèdits, menys A5 que en té 6. • Tenim els professors P1 i P2. El professor P1 imparteix la docència d’A1, A2 i A5 i el professor P2 d’A3 i A4, per la qual cosa el professor P1 té una càrrega docent de 13 crèdits, i el professor P2 de 7 crèdits. • Suposem que hi ha un alumne E1 que ja porta temps matriculat, i que ha aprovat A1 i A2. En cap cas no podrà matricular-se encara en A4, ja que li falta aprovar A3. Se sol·licita un disseny d’estructura de dades que atenyi les funcionalitats establertes d’acord amb els requisits següents: 1) Les operacions de consulta han de ser tan ràpides com sigui possible. 2) Les operacions d’inserció no han de ser innecessàriament lentes. 3) No s’ha de malbaratar espai.

Per a resoldre aquest cas es parteix d’una anàlisi tant de les restriccions de la quantitat d’elements que cal emmagatzemar en cada part de l’estructura, com del tipus de relacions que es donen entre els elements del domini i dels tipus d’operacions que s’hi poden fer, i també de l’eficiència que s’espera de l’estructura.

Com s’especifica en l’enunciat, per a cursar una assignatura pot ser que calgui haver-ne aprovat una altra o més. Això indica que les assignatures de la titulació conformen un graf dirigit. És molt probable que el graf conformat no sigui dens, per la qual cosa la implementació més adequada per al graf serà una llista d’adjacència. Cada vèrtex emmagatzemarà el nom i els crèdits d’una assignatura.

Activitat Es deixa com a exercici la descripció de l’algorisme pel qual un alumne es matricula d’una assignatura i el càlcul de la seva eficiència.

Grafs


© FUOC • P06/05001/00582 • Módulo 8

27

El nombre d’alumnes és elevat i desconegut i, atès que les consultes han de ser tan ràpides com sigui possible, hi ha dues possibilitats per a emmagatzemarlos: una taula de dispersió, que es descarta en no conèixer el nombre exacte d’alumnes, i un arbre AVL, que serà l’estructura que farem servir. L’arbre està ordenat pel nom i els cognoms dels alumnes. Cada alumne ha de mantenir un apuntador a un contenidor amb les assignatures matriculades. Com que no seran gaires i el nombre és estimable, es pot optar per implementar una llista seqüencial afitada. El mateix, i pels mateixos motius, passarà amb les assignatures ja aprovades. El nombre de docents és desconegut, però estable i petit. Per això, s’opta per implementar un contenidor de tipus llista seqüencial afitada. Cada docent mantindrà un apuntador a un altre contenidor en què s’emmagatzema una referència a les assignatures que imparteix. Com que, altre cop, les assignatures són poques, es poden emmagatzemar en una llista afitada seqüencial. Figura 11

Activitat Com a ampliació de l’exemple, torneu a dissenyar l’estructura tenint en compte l’operació següent: obtenir l’alumne amb la millor nota mitjana calculada a partir de totes les assignatures que ha superat, independentment de la quantitat. En cas d’empat, s’obtindrà qualsevol alumne dels que tenen més bon expedient.

Grafs


© FUOC • P06/05001/00582 • Módulo 8

28

Resum

En aquest mòdul, s’ha descrit el tipus abstracte de dades Graf com una representació general de relacions binàries entre elements d’un domini. Els elements d’aquest domini es representen mitjançant vèrtexs (o nodes) amb una informació associada, i les relacions es representen mitjançant arestes (o arcs) que associen o igualen en tots dos sentits. Per exemple, la relació esGermaDe. Això no obstant, en els grafs dirigits, entre cada parell de nodes hi poden haver zero, una o dues arestes. Per exemple, la relació esClientDe entre dues empreses. Es pot aconseguir una implementació directa i senzilla d’un graf mitjançant una matriu d’adjacència. Tanmateix, en molts casos, aquesta representació no és eficient des del punt de vista del consum de memòria, ja que en molts grafs, només hi ha un petit nombre de les arestes possibles. Les llistes d’adjacència proporcionen una alternativa eficient d’implementació per a aquestes situacions. La implementació amb llistes també permet substituir les simples llistes enllaçades per altres estructures que proporcionin un accés més eficient en alguns casos, com per exemple un arbre AVL.

Grafs


29

© FUOC • P06/05001/00582 • Módulo 8

Grafs

Exercicis d’autoavaluació 1. Quines diferències, en les estructures de dades, tenen la implementació amb llistes d’adjacència d’un graf dirigit i d’un de no dirigit? 2. Quin és el nombre màxim d’arestes en un graf bipartit? 3. Si tenim un graf no dirigit bipartit que representa les regions d’Espanya, i volem representar com a arestes la relació “fa frontera amb”, quin serà el percentatge de posicions ocupades si implementem el graf amb una matriu d’adjacència? 4. Implementeu en Java una matriu d’adjacència per a un graf amb nodes en el domini d’un rang dels enters que comencen en 1. El rang d’enters representat serà un paràmetre del constructor. Resoleu l’exercici implementant les interfícies corresponents de la biblioteca de TAD de l’assignatura. 5. Suposem que tenim un graf que representa la distància entre ciutats dins d’un país. a) El viatger A vol saber el camí òptim entre dues ciutats, X i Y, segons la ràtio entre la distància i el preu total del viatge. Cada connexió entre ciutats té un preu determinat, que és el que s'utilitza per a calcular el preu total d’un viatge. b) El viatger B també vol saber el camí òptim entre dues ciutats, X i Y, però en aquest cas, segons la menor distància, i només en cas que hi hagi més d’un camí amb la mateixa distància, considera el preu, i lògicament prefereix el camí de menys cost d’entre els d’igual distància. Implementeu els algorismes que resolen els dubtes dels viatgers A i B, i calculeu la seva eficiència temporal asimptòtica. 6. La disciplina d’anàlisi de xarxes socials (AXS) estudia, entre altres coses, les relacions de centralitat de la xarxa i dels individus (actors) dins de la xarxa social d’una organització o situació determinada. Les relacions socials entre individus es representen com a arestes no valorades, i els actors com a vèrtexs dins d’un graf. La centralitat s’estima amb mesures com les següents: a) Centralitat en l’actor, c(A), definida com el nombre de connexions socials de l’actor A, normalitzada en l’interval [0,1]. És a dir, per a un actor determinat, es compten les seves relacions socials i, posteriorment, es divideixen pel total de relacions totals en el graf, i dóna com a resultat un nombre entre 0 i 1, que indica la quantitat relativa de relacions socials en les quals l’individu pren part. b) Centralitat en el grup. Es tracta d’una magnitud única per a tot el grup o conjunt de tots els actors, definida com:

CG =

V

[max[ c( vi )] − c( vi )] max[ c( vi )]

,

en què V és el conjunt dels actors de la xarxa i max[c(vi)] és la centralitat màxima de l’actor a la xarxa. c) Centralitat de proximitat d’un actor, definida com:

⎡ ⎤ CC(a) = ⎢ ∑ d(a, vi )⎥ ⎣V ⎦

−1

,

en què d(a,vi) és la distància entre l’actor a i l’actor vi, entenent per distància la longitud del camí mínim entre a i vi. Implementeu les tres operacions definides utilitzant la biblioteca de TAD descrita, i analitzeu-ne l’eficiència temporal asimptòtica.

Glossari aresta f Enllaç que uneix dos vèrtexs del graf. Representa algun tipus de vincle entre tots dos nodes. graf m Tipus abstracte de dades que representa un conjunt d’elements d’informació o vèrtexs, i un conjunt de relacions binàries entre aquests elements d’informació, denominats arestes. graf bipartit m Tipus de graf en què les relacions entre els vèrtexs inclouen un element de cada un de dos conjunts que conformen una partició del conjunt de vèrtexs. graf dirigit m Tipus de graf en què es té en compte el sentit de les relacions.

Consulteu els materials de l’assignatura Matemàtica discreta per repassar els algorismes de recorreguts de grafs.


© FUOC • P06/05001/00582 • Módulo 8

30

graf no dirigit m Tipus de graf en què es té en compte el sentit de les relacions. graf valorat m Tipus de graf en què cada aresta té associada una informació, que es denomina habitualment pes. llista d’adjacència f Tècnica d’implementació de grafs que consisteix essencialment a emmagatzemar els vèrtexs en una estructura lineal, i a associar a cada vèrtex una llista enllaçada amb els vèrtexs adjacents. matriu d’adjacència f Tècnica d’implementació de grafs que consisteix essencialment a emmagatzemar en una matriu bidimensional la presència o absència d’aresta entre cada parell de vèrtexs. En el cas de grafs valorats, s’emmagatzema, a més de la presència o absència, el pes, si hi ha aresta. vèrtex (node) f Element d’informació en un graf del qual s’emmagatzemen les relacions mitjançant arestes.

Bibliografia Bibliografia bàsica Cormen, T. H.; Leiserson C. E.; Rivest; R. L. (1990). Introduction to algorithms (cap. 5 i 23). MIT Press. Weiss, M. A. (2003). Data structures & problem solving using Java (2a. ed.). Upper Saddle River: Addison Wesley. Disponible en línia: http://www.cs.fiu.edu/~weiss

Grafs


© FUOC • P06/5001/00582 • Módulo 8

31

Grafs

Annex

Per a saber-ne més Hi ha diferents tipus d’algorismes per a recórrer grafs: obtenció d’un ordre topològic, obtenció de camins mínims, d’arbres d’expansió mínims, etc. (podeu trobar els algorismes més importants sobre grafs en els materials de l’assignatura Matemàtica discreta). Però, en certs casos, la implementació que es faci del graf pot condicionar l’eficiència d’aquests algorismes. Posem per cas l’algorisme de Dijkstra per a l’obtenció de camins mínims.

L’algorisme de Dijkstra permet realitzar el càlcul de distàncies mínimes, és a dir, permet trobar el camí més curt des d’un node fins a la resta, i la distància és la suma de les etiquetes que es troben en un camí. Un exemple de camí mínim des de Madrid a altres poblacions es mostra en la figura 12.

Figura 12

Per a aconseguir aquests camins mínims s’ha d’executar l’algorisme següent. D’altra banda, en la figura 13 es mostren les fases que executaria l’algorisme aplicat en l’exemple.

proc caminsMinims(g:tGraf, v:tVertex) retorna <D: vector [1..|V|] d'enter> var S : conjuntNodes; inici per a tot w ∈ V fer D[w]:= arc(g,v,w) fi per a D[v]:= 0; creaConjunt(S); afegeixElement(S,v); mentre numElements(S)≠ |V| - 1 fer elegir w ∉ S tal que D[w] és mínim; afegeixElement(S,w) per a tot o ∉ S fer actualitzar distancia mínima i comprovar si per w s’escurça fi per a fi mentre torna D fi


© FUOC • P06/5001/00582 • Módulo 8

32

Grafs

Figura 13

Per a estudiar la complexitat de l’algorisme es pot dividir en diverses fases: • Fase d’inicialització, en què s’inicialitza el vector amb les distàncies del node de partida a la resta. Aquesta fase té un cost temporal de O(n), essent n el nombre de nodes, tant si es realitza la implementació utilitzant llistes com matrius d’adjacència, ja que implica un recorregut per tots els nodes del graf. • Fase de selecció, en què es tria el vèrtex més proper (amb distància més curta) del que es tracta. Aquesta fase s’executa en O(n2) tant si s’utilitzen llistes com si s’utilitzen matrius d’adjacència per a implementar el graf, ja que per a cada node del graf cal recórrer els nodes no tractats, i buscar el que està unit amb una distància mínima. Aquesta operació s’ha realitzar mentre quedin vèrtexs per tractar.

• Fase de marcatge, en què s’afegeix el vèrtex seleccionat a la solució. En tots dos casos d’implementació del graf (llistes d’adjacència o matrius d’adjacència) s’executa en O(n), ja que per a cada node cal realitzar aquesta operació d’afegir a la solució i excloure el vèrtex seleccionat dels no tractats. • Fase de recàlcul, en què es tornen a calcular les distàncies tenint en compte el nou node incorporat en la solució, i s’actualitzen les rutes si la distància és més curta. Aquesta fase s’executa en O(n2) si el graf s’implementa amb una matriu d’adjacència, i en O(n + a), essent a el nombre d’arestes, si s’implementa amb una llista d’adjacència, ja que el càlcul es fa acumulant a la distància que hi ha fins al vèrtex seleccionat la distància des d’aquest fins als seus adjacents, i aquesta operació es repeteix per a cada vèrtex de la solució. Això fa que la complexitat de l’algorisme sigui en tots dos casos de O(n2). Ara bé, si s’aconsegueix realitzar la fase de selecció


© FUOC • P06/5001/00582 • Módulo 8

33

Grafs

en temps menor de O(n2) en el cas d’utilitzar una implementació amb llistes d’adjacència, es millorarà l’eficiència total de l’algorisme per a aquest cas.

qualsevol en O(1) i modificar el valor associat a un node en O(log n), operacions totes elles necessàries en la fase de recàlcul.

Com ja s’ha exposat, la fase de selecció consisteix a buscar l’element més petit d’un conjunt i eliminar-lo. L’ús d’una cua prioritària permetria tenir els elements ordenats, i si s’implementés amb un piló es podria consultar l’element més petit a O(1), i eliminar l’element més petit en O(log n), amb la qual cosa es podria aconseguir un cost temporal per a l’algorisme més petit.

D’aquesta manera, el cost de l’algorisme implementat amb llistes d’adjacència quedaria de la manera següent:

En introduir una cua prioritària, cal tenir en compte que en la fase de recàlcul es pot demanar la modificació de la distància de qualsevol vèrtex en la cua. Perquè aquesta operació es realitzi de la manera més senzilla possible, és convenient actualitzar l’estructura CuaPrioritaria afegint un vector indexat per vèrtexs. Cada posició del vector ha d’apuntar al vèrtex del piló (–1 si no hi és). Amb això, s’aconseguiria comprovar l’existència d’un vèrtex en O(1), obtenir el valor associat a un node

• Fase d’inicialització (insercions reiterades en la cua de prioritat): O(n log n). • Fase de selecció (consultes reiterades de l’element més petit de la cua): O(n). • Fase de marcatge (eliminacions reiterades de l’element més petit en la cua): O(n log n). • Fase de recàlcul (examen de totes les arestes del graf i, si és oportú, modificació d’un element de la cua): O(a log n). Per tot , l’algorisme adquireix un cost total de O((a + n) log n).



M8