Docsity
Docsity

Prepara i tuoi esami
Prepara i tuoi esami

Studia grazie alle numerose risorse presenti su Docsity


Ottieni i punti per scaricare
Ottieni i punti per scaricare

Guadagna punti aiutando altri studenti oppure acquistali con un piano Premium


Guide e consigli
Guide e consigli


algoritmi e struttura dati, Prove d'esame di Algoritmi E Strutture Di Dati

appunti per svolgere al meglio l'esame scritto

Tipologia: Prove d'esame

2016/2017
In offerta
30 Punti
Discount

Offerta a tempo limitato


Caricato il 26/01/2017

giuseppe_palmisano
giuseppe_palmisano 🇮🇹

5

(2)

1 documento

1 / 16

Toggle sidebar

Questa pagina non è visibile nell’anteprima

Non perderti parti importanti!

bg1
ALGORITMI E STRUTTURE DATI
COSA è un ALGORITMO?
Sequenza finita di passi interpretabili da un esecutore.
CLASSIFICAZIONE DEGLI ALGORITMI
A seconda dei passi svolti in un esecuZione:
Algoritmi sequenziali: eseguono un passo alla volta;
Algoritmi paralleli: avvalendosi di un numero prefissato di esecutori, eseguono più passi per volta;
A seconda del modo in cui risolvono le scelte:
Deterministici: ad ogni punto di scelta, intraprendono una sola via determinata in base ad un
criterio pressato;
Probabilistici: ad ogni punto di scelta, intraprendono una sola via
determinata a caso;
Non deterministici: ad ogni punto di scelta, esplorano tutte le vie contemporaneamente.
CORRETTEZZA DI UN ALGORITMO RISPETTO AD UN PROBLEMA
Esistono vari problemi reali che possono essere risolti attraverso l’ uso di determinati algoritmi (problem
solving).
Problema di decisione: richiede una risposta binaria {0,1} rappresentante il soddisfacimento di
qualche proprietà o l’esistenza di qualche entità;
Problema di ricerca: richiede di trovare una soluzione in corrispondenza dei dati di ingresso;
Problema di ottimizzazione: richiede di trovare la soluzione ottima, in virtù di un criterio già fissato
in precedenza, in corrispondenza degli ingressi.
Il problem solving è basato su varie tecniche come divide et impera o tecniche golose ecc..
Mentre un problema specica il cosa, cioè quali soluzioni produrre in uscita a partire dai dati ricevuti in
ingresso, un algoritmo per quel problema descrive il come, cioè quale procedimento seguire per produrre le
soluzioni attese a partire dai dati di ingresso.
Dati un problema e un algoritmo, l’algoritmo è detto corretto rispetto al problema se, per ogni istanza dei dati
di ingresso del problema, l’algoritmo termina e produce la soluzione corrispondente.
COMPLESSITA di un ALGORITMO rispetto all’uso di RISORSE
Esistono più algoritmi equivalenti per la soluzione di un problema, ma l’astuzia sta nel confrontarli e nel
trovare quello che è più conveniente dal punto di vista:
Tempo di calcolo;
Spazio in memoria;
Banda trasmissiva;
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff
Discount

In offerta

Anteprima parziale del testo

Scarica algoritmi e struttura dati e più Prove d'esame in PDF di Algoritmi E Strutture Di Dati solo su Docsity!

ALGORITMI E STRUTTURE DATI

COSA è un ALGORITMO? Sequenza finita di passi interpretabili da un esecutore. CLASSIFICAZIONE DEGLI ALGORITMI

  • A seconda dei passi svolti in un esecuZione: Algoritmi sequenziali: eseguono un passo alla volta; Algoritmi paralleli: avvalendosi di un numero prefissato di esecutori, eseguono più passi per volta;
  • A seconda del modo in cui risolvono le scelte: Deterministici: ad ogni punto di scelta, intraprendono una sola via determinata in base ad un criterio pressato; Probabilistici: ad ogni punto di scelta, intraprendono una sola via determinata a caso;

Non deterministici: ad ogni punto di scelta, esplorano tutte le vie contemporaneamente. CORRETTEZZA DI UN ALGORITMO RISPETTO AD UN PROBLEMA Esistono vari problemi reali che possono essere risolti attraverso l’ uso di determinati algoritmi (problem solving).

  • Problema di decisione: richiede una risposta binaria {0,1} rappresentante il soddisfacimento di qualche proprietà o l’esistenza di qualche entità;
  • Problema di ricerca: richiede di trovare una soluzione in corrispondenza dei dati di ingresso;
  • Problema di ottimizzazione: richiede di trovare la soluzione ottima, in virtù di un criterio già fissato in precedenza, in corrispondenza degli ingressi. Il problem solving è basato su varie tecniche come divide et impera o tecniche golose ecc.. Mentre un problema specica il cosa, cioè quali soluzioni produrre in uscita a partire dai dati ricevuti in ingresso, un algoritmo per quel problema descrive il come, cioè quale procedimento seguire per produrre le soluzioni attese a partire dai dati di ingresso.

Dati un problema e un algoritmo, l’algoritmo è detto corretto rispetto al problema se, per ogni istanza dei dati di ingresso del problema, l’algoritmo termina e produce la soluzione corrispondente.

COMPLESSITA’ di un ALGORITMO rispetto all’uso di RISORSE Esistono più algoritmi equivalenti per la soluzione di un problema, ma l’astuzia sta nel confrontarli e nel trovare quello che è più conveniente dal punto di vista:

  • Tempo di calcolo;
  • Spazio in memoria;
  • Banda trasmissiva;

STRUTTURE DATI

Le strutture dati costituiscono gli ingredienti di base degli algoritmi. L’efficienza di un algoritmo dipende in maniera critica dal modo in cui sono organizzati i dati su cui esso deve operare.

Una struttura dati `e un insieme di dati logicamente correlati e opportunamente memorizzati, per i quali sono deniti degli operatori di costruzione, selezione e manipolazione.

Quattro classi fondamentali : array, liste, alberi e gra.

  • Strutture dati statiche: la quantità di memoria di cui esse necessitano è determinabile a priori (array).
  • Strutture dati dinamiche: la quantità di memoria di cui esse necessitano varia a tempo d’esecuzione e può essere diversa da esecuzione a esecuzione (liste, alberi, gra).

PROBLEMA DELLA DECIDIBILITA’

Purtroppo non `e sempre possibile trovare un algoritmo che risolve un problema dato. Di conseguenza i problemi si dividono in decidibili e indecidibili a seconda che possano essere risolti oppure no.

DECIDIBILE:

Se esiste un algoritmo che assegna una soluzione ad una configurazione di ingressi in tempo finito. Questi tipi di problemi sono classificati in base alla loro trattabilità(possibilità di risolvere un problema in maniera efficiente).

Un problema di decisione decidibile viene classificato come intrattabile se non è risolvibile in tempo polinomiale nemmeno da un algoritmo non deterministico. Questo tipo si divide in :

  • P (insieme di problemi di decisione risolvibile da un algoritmo deterministico in tempo polinomiale;
  • (^) NP(insieme di problemi di decisione risolvibile da un algoritmo non deterministico in tempo polinomiale.

P è un sottoinsieme di NP.

/* Esiste una soluzione al problema */

INDECIDIBILE:

Se non esiste un algoritmo che assegna una soluzione ad una configurazione di ingressi in tempo finito. In tal caso sarà possibile calcolare una soluzione in tempo finito solo per alcune delle istanze dei dati di ingresso.

TEOREMA DI COOK

È un risultato fondamentale nello studio della complessità della risoluzione dei problemi intrattabili e si basa sul concetto di riducibilità in tempo polinomiale tra problemi.

Dati due problemi di decisione:

ALGORITMI PER ARRAY

Un array è una struttura statica e omogenea, nel senso i cui elementi non variano di numero a tempo d’esecuizione e tutti dello stesso tipo. L’accesso a ciascun elemento di un array ha complessità asintotica O (1).

Problemi di:

  • (^) Visita: attraversare tutti gli elementi una volta.
  • Ricerca: stabilire se un determinato valore è contenuto nell’array.
  • Ordinamento: riordinare gli elementi degli array secondo una determinata relazione.

ALGORITMO DI VISITA

void visita(int a[], int n)

{

Int i; for ( i = 0; i < n; i++ ) { elabora( a[i]); }

}

Vediamo che la complessità dell’algoritmo è O(n), perché dipende dal numero di elementi dicui è composto l’array.

ALGORITMO DI RICERCA LINEARE

Int ricerca_lineare(int a[], int n, int valore)

{

Int i; for( i = 0; ((i < n) && (a[i] != valore)); i++ ) return(( i < n )? i : -1 );

}

Se l’algoritmo trova il valore ricercato nell’array allora la ricerca si blocca e la funzione ritornerà la posizione dell’array in cui si trova il valore ricercato, altrimenti la funzione ritornerà -1.

CASO PESSIMO: se il valore cercato non è presente nell’array e quindi l’algoritmo avrà complessità O(n).

CASO OTTIMO: il valore cercato è il primo elemento dell’array e quindi l’algoritmo avrà complessità O(1).

ALGORITMO DI RICERA BINARIA PER ARRAY ORDINATI

Se un array è già ordinato, un elemento può essere anche ricercato con l’uso del seguente algoritmo.

Si divide l’array in due parti uguali(dx e sx)e si confronta il valore ricercato con il valore che sta a metà, in questo modo se il valore ricercato è maggiore del mediano allora si dividerà nuovamente la parte a destra e si continuerà così via fino a quando non si trova il valore ricercato.

Int ricerca_binaria(int a[], int n,int valore)

{

Int sx,dx,mx; for( sx = 0, dx = n-1, mx = (sx + dx)/2; ((sx <= dx)&&(a[x] != valore)); mx = (sx + dx)/2) if ( a[mx] > valore) dx = mx – 1; else sx = mx + 1; return((s <= dx)? mx :-1);

}

CASO PESSIMO: Se non viene trovato alcun elemento dopo aver dimezzato ripetutamente l’array in questione. T(n) = O(log n).

CASO OTTIMO:Se viene torvato al primo dimezzamento come elemento mediano e ha quindi complessità T(n) = O(1).

ALGORITMO DI ORDINAMENTO

INSERTSORT

L'algoritmo solitamente ordina la sequenza sul posto. Si assume che la sequenza da ordinare sia partizionata in una sottosequenza già ordinata, all'inizio composta da un solo elemento, e una ancora da ordinare. Alla -esima iterazione, la sequenza già ordinata contiene elementi. In ogni iterazione, viene rimosso un elemento dalla sottosequenza non ordinata (scelto, in generale, arbitrariamente) e inserito (da cui il nome dell'algoritmo) nella posizione corretta della sottosequenza ordinata, estendendola così di un elemento.

CASO PESSIMO : quello in cui la sequenza di partenza sia ordinata al contrario. In questo caso, ogni iterazione dovrà scorrere e spostare ogni elemento della sottosequenza ordinata prima di poter inserire il primo elemento della sottosequenza non ordinata. Pertanto, in questo caso l'algoritmo ha complessità temporale quadratica, ossia T(n) = O(n^2).

In uno heap decrescente (utilizzato per ordinare ad esempio un array in senso crescente) ogni nodo padre contiene un valore maggiore o uguale a quello dei suoi due figli diretti, di conseguenza risulterà maggiore anche di tutti i nodi che si trovano nel sottoalbero di cui esso è la radice; questo non implica affatto che nodi a profondità maggiore contengano valori minori di quelli a profondità minore. Quindi in ogni istante, in un heap decrescente, la radice contiene il valore maggiore. L'algoritmo che ordina in senso crescente inizia creando uno heap decrescente. Per ogni iterazione si copia la radice (primo elemento dell'array) in fondo all'array stesso, eseguendo uno scambio di elementi. L'algoritmo poi ricostruisce uno heap di elementi spostando verso il basso la nuova radice, e ricomincia con un altro scambio (tra il primo elemento dell'array e quello in posizione ), eseguendo un ciclo che considera array di dimensione progressivamente decrescente.

Si può dimostrare che la complessità asintotica massima dell'heapsort è. Tuttavia, in generale (e soprattutto perarray quasi ordinati) altri algoritmi con la medesima complessità asintotica, per esempio quick sort o merge sort, ottengono migliori prestazioni.

ALGORITMI PER LISTE

Una lista è una tripla L = (E,t,S) dove E è un insieme di elementi, t € E è detto testa ed S è una relazione binaria su E, dove S è sottinsieme di E * E che soddisfa le seguenti proprietà:

• Per ogni e € E , (e,t) non appartiene S; /* non tutti gli elementi sono collegati alla testa */

• Per ogni e € E , se e != t, allora esiste uno ed un solo e’ € E tale che (e’,e) €

S; /* ogni elemento diverso dalla testa è collegato ad un solo elemento e’ */

• Per ogni e € E, esiste al più un e’ € E tale che (e,e’) € S;

/* ogni elemento è collegato al massimo ad un solo elemento e’ */

• Per ogni e € E, se e != t allora e è raggiungib. da t, cioè esistono e1’,…..,ek’ € E con k>= 2 talic

e1’ = t, (ei’, ei+1’) € S per ogni 1 <= i <= k – 1, ek’ = e. Una lista è rappresentata come una struttura dinamica lineare, in cui ogni elemento contiene un valore ed un puntatore all’elemento successivo,(se singolarmente collegata)ed anche all’elemento precedente (se doppiamente collegata). Ogni elemento della lista contiene la chiave dell’elemento successivo. Se la lista è singolarmente collegata:

• L’ indirizzo dell’elemento successivo all’ultimo elemento della lista è INDEFINITO.

Se è doppiamente collegata:

• L’ indirizzo dell’elemento successivo all’ultimo elemento della lista è INDEFINITO.

• L’indirizzo dell’elemento precedente al primo elemento della lista è INDEFINITO.

Fa ad eccezione se la lista è circolare. ALGORITMO DI VISITA, RICERCA, INSERIMENTO e RIMOZIONE per LISTE. void visita_vista(elem_lista *testa_p) { elem_lista *elem_p; for (elem_p = testa_p; elem_p != NULL; elem_p = elem_p -> succ_p) elabora(elem_p -> valore); } T(n) = O(n);

elem_lista *cerca_in_lista(elem_lista *testa_p, int valore) { Elem_lista *elem_p; for(elem_p = testa_p;((elem_p != NULL)&&(elem_p->valore != valore);elem_p = elem_p -> succ_p) return(elem_p); }

Int inserisci_in_lista(elem_lista *testa_p,int valore) { Elem_lista *corr_p, prec_p, nuovo_p; for(corr_p = prec_p = *testa_p; ((corr_p != NULL) &&(corr->valore < valore)); prec_p = corr_p, corr_p = corr_p -> succ_p) if ((corr_p != NULL) && (corr_p -> valore == valore)) inserito = 0; else { Inserito = 1; nuovo_p = (elem_lista *)malloc(sizeof(elem_lista)); nuovo_p -> valore = valore; nuovo_p -> succ_ p = corr_p; if ( corr_p == *testa_p) *testa_p = nuov_p; else prec_p -> succ_p =nuovo_p; } Return(inserito); }

If( nodo_p != NULL) { Elabora(nodo_p -> valore); visita_albero_bin_ant(nodo_p -> sx); visita_albero_bin_ant(nodo_p -> dx); } } Nella visita in ordine simmetrico si visita prima il sottoalbero sinistro , poi il nodo e poi il sottoalbero destro. Void visita_albero_bin_simm( nodo_albero * nodo_p) { If( nodo_p != NULL) { visita_albero_bin_ant(nodo_p -> sx); Elabora(nodo_p -> valore); visita_albero_bin_ant(nodo_p -> dx); } }

posticipato: si visita prima il sottoalbero sinistro, poi quello destro e poi il nodo. Void visita_albero_bin_post( nodo_albero * nodo_p) { If( nodo_p != NULL) { visita_albero_bin_ant(nodo_p -> sx); visita_albero_bin_ant(nodo_p -> dx); Elabora(nodo_p -> valore); } } Se a questo punto indichiamo con:

• “n” il numero di nodi dell’ albero;

• “d” il numero massimo di passi eseguiti durante l’elaborazione del valore conenunto in un nodo;

• “k” il numero di nodi del sottoalbero sx;

• “n – 1 – k” il numero di nodi del sottoalbero dx.

T(0) = 1;

T(n) = 1 + T(k) + T(n – 1 – k ) + d;

Alla fine dipenderà da n perché se vediamo per n = 0 T(n) = 1 e quindi anche la d deve dipendere da n. T(n) = O(n). I precedenti algoritmi di visita possono essere trasformati in algoritmi di ricerca che hanno una COMPLESSITA’ T(n) = O(1) per il CASO OTTIMO.(valore presente nella radice o albero vuoto) COMPLESSITA’ T(n) = O(n) per il CASO PESSIMO. (valore non presente nell’albero binario) ALGORITMO DI RICERA BINARIA PER ALBERI ORDINATI

Come per gli array si poteva usufruire di un algoritmo di ricerca per array ordinati che quando eseguito ha un guadagno rispetto al tempo delle altre ricerche, anche negli alberi si può guadagnare tempo durante la ricerca usufruendo del seguente algoritmo: Se ogni nodo ha valore k. Tutti i valori presenti nei loro sotto alberi di sinistra saranno <= k. A destra invece >= k. Insieme agli alg. di inserimento e rimoz. ha un CASO MEDIO T(n) = O(log n). Se si vuole ottenere anche nel caso pessimo una complessità = O(log n) anziché O(n) , bisogna mantenere l’albero bilanciato.(solo cosi la h può crescere logaritmicamente al crescere di n). COME BILANCIARE L’ALBERO?

• Si devono inserire i nuovi nodi nei livelli già esistenti cercandoli di riempirli il più possibile prima

di creare nuovi livelli.

• Quando si rimuovono i nodi invece bisogna ridistribuire i nodi rimasti all’ interno dei livelli nel

modo più uniforme possibile. Un albero binario di ricerca è perfettamente bilanciato o AVL-bilanciato (Adelson – Velsky & Landis) se,per ogni nodo l’altezza del sottoalbero destro con quello sinistro differiscono al massimo di 1. Quindi: log(n + 1) <= h <= 1.44 * log(n + 2) – 0. Tuttavia dopo una rimozione il numero di operazioni da effettuare per ribilanciare l’ albero potrebbe non essere costante).

ALBERO ROSSO – NERO

è un approssimazione di albero binario di ricerca bilanciato , che spreca meno nelle operazioni di

ribilanciamento dopo una rimozione o inserimento tramite una rotazione o un cambio di colore.. È

complessa, ma ha un eccellente tempo di esecuzione nel caso peggiore ed è molto efficiente: effettua ricerche, inserimenti e cancellazioni in un tempo di .. Un albero rosso-nero è un albero binario di ricerca in cui ciascun nodo ha un attributo colore , il cui valore può essere rosso oppure nero. In aggiunta ai requisiti ordinari per un albero binario di ricerca, un albero rosso-nero soddisfa le seguenti proprietà:

  1. Ogni nodo ha colore rosso o nero.
  2. Il nodo radice inizialmente è nero.
  3. Ogni foglia è nera e contiene elemento null;
  4. Entrambi i figli di ciascun nodo rosso sono neri;
  5. Ogni cammino da un nodo a una foglia nel suo sottoalbero contiene lo stesso numero di nodi neri. In questo caso vediamo che nessun cammino può avere due nodi rossi in fila, per la proprietà 4. Il cammino più breve possibile ha tutti nodi neri, e il più lungo alterna nodi rossi e nodi neri. Poiché tutti i cammini massimi hanno lo stesso numero di nodi neri, per la proprietà 5, ciò dimostra che nessun cammino è lungo più del doppio di qualsiasi altro cammino. Di conseguenza per queste proprietà elencate vediamo che i nodi neri in un qualsiasi percorso sono la metà : h <= 2 * log2(n+1)

Vertice terminale: do(v) = 0; /* non vi sono vertici adiacenti / di(v) > 0 / ma è adiacente a qualcuno */ Vertice iniziale: Do(v) > 0; di(v) = 0; Vertice isolato: d(grado totale) = di(v) + do(v) = 0. GRAFO COMPLETO Se E = {V * V} GRAFO CONNESSO Se per ogni v1, v2€ V esiste almeno un percorso (v1,v2) o (v2,v1) € E GRAFO FORTEMENTE CONNESSO Se per ogni v1, v2€ V esiste un percorso (v1,v2) e (v2,v1) € E COMPONENTE CONNESSA Si dice che G’ = (V’,E’) è componente connessa di G se G’ è un sottografo indotto di G, che è connesso e massimale.

COMPONENTE FORTEMENTE CONNESSA Si dice che G’ ={V’,E’} componente fortemente connessa di G se G’ è un sottografo indotto di G, che è fortemente connesso e massimale. GRAFO INDIRETTO Una coppia (V,E) tale che E è una relazione binaria su V antirifflessiva e simmetrica. L’albero libero è un tipo di grafo indiretto dove valgono anche le proprietà di connettività e aciclicità. GRAFO PESATO Se ad ogni arco del grafo è associato un “peso”(tempo,distanza….). Sarà quindi una tripla G = (V,E,w) Un grafo viene di solito rappresentato tramite una struttura dinamica chiamata lista di adiacenza, formata da una lista primaria contenente i vertici e in ogni vertice è contenuta la testa della lista secondaria relativa a quel vertice contenente gli indirizzi di tutti i vertici adiacenti al vertice in questione. La rappresentazione a matrice di adiacenza spreca in memoria: O(|V| + |E|) Se si ha una matrice di adiacenza invece si mettono in corrispondenza di Ei,j = 1 se esiste un arco tra vi e vj e 0 altrimenti. O(|V^2|) PROBLEMA DELLA VISITA IN AMPIEZZA O IN PROFONDITA’ Per il problema della visita viene introdotto il colore. La visita in ampiezza lavora sullo stesso livello, infatti prima di scendere giù visita pian piano i livelli superiori. Nella visita in profondita viene introdotta anche la variabile tempo. Nella visita in profondità prima si elabora il vertice in cui si è giunti e poi si visitano tutti i vertici ad esso adiacenti e si continua così richiamando l’algoritmo ricorsivamente. PROBLEMA DELL’ ORDINAMENTO TOPOLOGICO. Determinare un ordinamento lineare dei suoi vertici tale che se (v,v’) € E allora v precede v’ nell’ ordinamento. Mette quindi tutti gli eventi in sequenza rispettando i vincoli di dipendenza causale.

Per risolverlo consideriamo l’algoritmo di visita in profondità, considerando i vertici in ordine di tempo decrescente di fine visita. Si crea una lista all’inizio della quale i vertici vengono inseriti man mano che vengono colorati di nero. Poiché gli inserimenti avvengono sempre all’inizio della lista, la complessità è O(|V| + | E|); PER IL PROBLEMA DELLE COMPONENT FORTEMENTE CONNESSE Cioè stablire se Se per ogni v1, v2€ V esiste un percorso (v1,v2) e (v2,v1) € E Si effettuano due visite in profondità: una sul grafo trasposto e una sul grafo dato. La seconda visita in profondità (sul grafo trasposto) avrà bisogno di considerare i vertici in ordine di tepo decrescente di fine prima visita, cioè considerati in ordine topologico. Così facendo gli alberi ricoprenti massimali costruiti durante la seconda visita rappresentano le componenti fortemente connesse. ALBERO RICOPRENTE MINIMO Trovare l’albero contenente tutti i vertici, ma solamente una parte degli archi E. Algoritmo di Kruskal: Parte da tanti alberi liberi quanti sono i vertici del grafo e ad ogni passo esso include l’arco di peso minimo che collega due diversi alberi liberi, fino ad ottenere un singolo albero libero. Algoritmo di Prim: Partendo da un albero libero costituito da un singolo vertice del grafo, ad ogni passo include l’arco di peso minimo che collega un vertice dell’albero libero ad un vertice che non sta ancora nell’albero.Fino ad ottenere un albero libero con tutti i vertici del grafo.

PROBLEMA DEL PERCORSO PIU’ BREVE.

Dati due vertici, uno di partenza e uno di arrivo bisogna calcolare il percorso complessivo di peso minimo che li unisca. Algoritmo di Belman-Ford Si usa una rappresentazione a matrice di adiacenza e consente la presenza di archi di peso negativo e procede alla riduzione sistematica della stima della distanza minima calcolata per ciascun vertice del grafo, sfruttando il fatto che un percorso minimo non può contenere più di |V| - 1 archi (Restituisce 1 se non ci sono cicli di peso negativo, 0 altrimenti). Quindi rilassa tutti gli archi V – 1 volte e man mano aggiorna la stima della distanza minima di ogni vertice dal vertice sorgente.

Algoritmo di Dijkstra T(n) = O(V + E) Si applica solo a grafi privi di archi di peso negativo. Si prende il vertice con la stima della distanza <. Infatti si mette una variabile temporanea della distanza. Dopo aver preso il vertice che ha minima questa variabile si rilassano gli archi da sso uscenti e si ricerca l’arco dal peso minore. A questo punto nell’ultimo vertice puntato dall’ultimo archo durante l’operazione la variabile temporanea verra aggiornata:

A B A V_p

Ecco così trovato il percorso più breve.

ALGORITMO DI FLOYD WARSHALL

Rappresentazione del grafo a matrce di adiacenza. Operazione triangolare su dij: Si aggiorna dij solo se è conveniente, infatti si fa un controllo dove:

• Se dij > dih + dhj dij = dih + dhj

Complessità totale: O(n^3) dovendo essere eseguita su h e sui nodi i e j. Sono tre cicli for dove fa

questo controllo scritto sopra. In seguito controlla l’esistenza di un circuito negativo.

Dentro un for : IF dii < 0 THEN STOP; /* ∃ un circuito negativo */