Algoritmo di Kruskal Parte con tutti i vertici e nessun lato (sottografo aciclico, o foresta, ricoprente) Ordina i lati per costo non decrescente Li aggiunge via via alla foresta, purché non creino cicli Kruskal(G,c) U = V; X = For v = 1 to n do MakeSet(v) SortEdges(E) For each e = (u,v) |X| do r = FindSet(u) s = FindSet(v) If r s then X = X {e*} Union(r,s) Un lato crea un ciclo quando i suoi estremi sono nella stessa componente connessa
Algoritmo di Kruskal: esecuzione Kruskal(G,c) U = V; X = For v = 1 to n do MakeSet(v) SortEdges(E) ... 1 v1 v5 v2 v3 v4 2 6 5 3 4 E = { [v1,v2], [v1,v5], [v2,v5], [v3,v5], [v2,v3], [v1,v3], [v4,v5], [v3,v4], [v1,v4] } p = [1 2 3 4 5] rank = [0 0 0 0 0]
Algoritmo di Kruskal: esecuzione Kruskal(G,c) ... For each e = (u,v) |X| do r = FindSet(u) s = FindSet(v) If r s then X = X {e*} Union(r,s) r = FindSet(v1) = v1 s = FindSet(v2) = v2 1 v1 v5 v2 v3 v4 2 6 5 3 4 E = { [v1,v2], [v1,v5], [v2,v5], [v3,v5], [v2,v3], [v1,v3], [v4,v5], [v3,v4], [v1,v4] } p = [1 1 3 4 5] rank = [1 0 0 0 0]
Algoritmo di Kruskal: esecuzione Kruskal(G,c) ... For each e = (u,v) |X| do r = FindSet(u) s = FindSet(v) If r s then X = X {e*} Union(r,s) r = FindSet(v1) = v1 s = FindSet(v5) = v5 1 v1 v5 v2 v3 v4 2 6 5 3 4 E = { [v1,v2], [v1,v5], [v2,v5], [v3,v5], [v2,v3], [v1,v3], [v4,v5], [v3,v4], [v1,v4] } p = [1 1 3 4 1] rank = [1 0 0 0 0]
Algoritmo di Kruskal: esecuzione Kruskal(G,c) ... For each e = (u,v) |X| do r = FindSet(u) s = FindSet(v) If r s then X = X {e*} Union(r,s) r = FindSet(v2) = v1 s = FindSet(v5) = v1 1 v1 v5 v2 v3 v4 2 6 5 3 4 E = { [v1,v2], [v1,v5], [v2,v5], [v3,v5], [v2,v3], [v1,v3], [v4,v5], [v3,v4], [v1,v4] } p = [1 1 3 4 1] rank = [1 0 0 0 0]
Algoritmo di Kruskal: esecuzione Kruskal(G,c) ... For each e = (u,v) |X| do r = FindSet(u) s = FindSet(v) If r s then X = X {e*} Union(r,s) r = FindSet(v3) = v3 s = FindSet(v5) = v1 1 v1 v5 v2 v3 v4 2 6 5 3 4 E = { [v1,v2], [v1,v5], [v2,v5], [v3,v5], [v2,v3], [v1,v3], [v4,v5], [v3,v4], [v1,v4] } p = [1 1 1 4 1] rank = [1 0 0 0 0]
Algoritmo di Kruskal: esecuzione Kruskal(G,c) ... For each e = (u,v) |X| do r = FindSet(u) s = FindSet(v) If r s then X = X {e*} Union(r,s) r = FindSet(v2) = v1 s = FindSet(v3) = v1 1 v1 v5 v2 v3 v4 2 6 5 3 4 E = { [v1,v2], [v1,v5], [v2,v5], [v3,v5], [v2,v3], [v1,v3], [v4,v5], [v3,v4], [v1,v4] } p = [1 1 1 4 1] rank = [1 0 0 0 0]
Algoritmo di Kruskal: esecuzione Kruskal(G,c) ... For each e = (u,v) |X| do r = FindSet(u) s = FindSet(v) If r s then X = X {e*} Union(r,s) r = FindSet(v1) = v1 s = FindSet(v3) = v1 1 v1 v5 v2 v3 v4 2 6 5 3 4 E = { [v1,v2], [v1,v5], [v2,v5], [v3,v5], [v2,v3], [v1,v3], [v4,v5], [v3,v4], [v1,v4] } p = [1 1 1 4 1] rank = [1 0 0 0 0]
Algoritmo di Kruskal: esecuzione Kruskal(G,c) ... For each e = (u,v) |X| do r = FindSet(u) s = FindSet(v) If r s then X = X {e*} Union(r,s) r = FindSet(v4) = v4 s = FindSet(v5) = v1 1 v1 v5 v2 v3 v4 2 6 5 3 4 E = { [v1,v2], [v1,v5], [v2,v5], [v3,v5], [v2,v3], [v1,v3], [v4,v5], [v3,v4], [v1,v4] } p = [1 1 1 1 1] rank = [1 0 0 0 0] |X| = n-1
Correttezza dell’algoritmo di Kruskal Per assurdo, sia T(V,X) l’albero costruito dall’algoritmo di Kruskal e T*(V,X*) un albero ottimo Consideriamo il primo lato e X, ma X* Se e X, significa che è stato scartato perché creava un ciclo con i lati già inseriti In tal caso, non può appartenere a X*, che contiene tutti i lati già inseriti, ma non contiene cicli
Complessità dell’algoritmo di Kruskal ordinamento degli m lati: O(m log m) O(m log n2) == O(m log n) verifica di aciclicità: O(log n) per ogni lato complessità totale: O(m log n) Questa seconda operazione si può migliorare usando la compressione dei cammini, cioè sfruttando le chiamate a FindSet per far sì che tutti gli elementi della catena puntino direttamente quello rappresentativo La singola FindSet rallenta, la lunghezza d delle catene diventa quasi sempre 1: O(log n) diventa O(a(n)) O(1)