logo

Algoritmo dell'albero di copertura minimo (MST) di Kruskal

Un albero di copertura minimo (MST) o spanning tree di peso minimo per un grafo pesato, connesso e non orientato è uno spanning tree con un peso inferiore o uguale al peso di ogni altro spanning tree. Per ulteriori informazioni sull'albero ricoprente minimo, fare riferimento a Questo articolo .

Introduzione all’algoritmo di Kruskal:

Qui discuteremo L'algoritmo di Kruskal per trovare l'MST di un dato grafico ponderato.

Nell'algoritmo di Kruskal, ordina tutti i bordi del grafico dato in ordine crescente. Quindi continua ad aggiungere nuovi bordi e nodi nel MST se il bordo appena aggiunto non forma un ciclo. Inizialmente seleziona il bordo con ponderazione minima e infine quello con ponderazione massima. Quindi possiamo dire che fa una scelta localmente ottimale in ogni passo per trovare la soluzione ottimale. Quindi questo è a Di seguito sono riportati i passaggi per trovare MST utilizzando l'algoritmo di Kruskal:



  1. Ordina tutti i bordi in ordine non decrescente in base al loro peso.
  2. Scegli il bordo più piccolo. Controlla se forma un ciclo con lo spanning tree formatosi finora. Se il ciclo non è formato, includere questo bordo. Altrimenti, scartalo.
  3. Ripetere il passaggio n. 2 finché non ci sono bordi (V-1) nello spanning tree.

Passo 2 utilizza il Algoritmo Unione-Trova per rilevare i cicli.

Pertanto consigliamo di leggere il seguente post come prerequisito.

  • Algoritmo di ricerca dell'unione | Set 1 (rileva il ciclo in un grafico)
  • Algoritmo di ricerca dell'unione | Set 2 (Unione per rango e compressione del percorso)

L’algoritmo di Kruskal per trovare l’albero di copertura del costo minimo utilizza l’approccio greedy. La scelta golosa è quella di scegliere il bordo di peso più piccolo che non causi un ciclo nel MST costruito finora. Cerchiamo di capirlo con un esempio:

Illustrazione:

Di seguito è riportato l'illustrazione dell'approccio di cui sopra:

Grafico di input:

Algoritmo dell’albero di copertura minimo di Kruskal

Il grafico contiene 9 vertici e 14 spigoli. Quindi, l'albero di copertura minimo formato avrà (9 – 1) = 8 archi.
Dopo l'ordinamento:

Peso Fonte Destinazione
1 7 6
2 8 2
2 6 5
4 0 1
4 2 5
6 8 6
7 2 3
7 7 8
8 0 7
8 1 2
9 3 4
10 5 4
undici 1 7
14 3 5

Ora seleziona tutti i bordi uno per uno dall'elenco ordinato dei bordi

Passo 1: Scegli il bordo 7-6. Nessun ciclo si forma, includilo.

Aggiungi il bordo 7-6 nel MST

Aggiungi il bordo 7-6 nel MST

Passo 2: Scegli il bordo 8-2. Nessun ciclo si forma, includilo.

Aggiungi il bordo 8-2 nel MST

Aggiungi il bordo 8-2 nel MST

sottostringa java

Passaggio 3: Scegli il bordo 6-5. Nessun ciclo si forma, includilo.

Aggiungi il bordo 6-5 nel MST

Aggiungi il bordo 6-5 nel MST

Passaggio 4: Scegli il bordo 0-1. Nessun ciclo si forma, includilo.

Aggiungi il bordo 0-1 nel MST

Aggiungi il bordo 0-1 nel MST

Passaggio 5: Scegli il bordo 2-5. Nessun ciclo si forma, includilo.

Aggiungi il bordo 0-1 nel MST

Aggiungi il bordo 2-5 nel MST

Passaggio 6: Scegli il bordo 8-6. Poiché includere questo vantaggio risulta nel ciclo, scartatelo. Scegli il bordo 2-3: Nessun ciclo si forma, includilo.

Aggiungi il bordo 2-3 nel MST

Aggiungi il bordo 2-3 nel MST

Passaggio 7: Scegli il bordo 7-8. Poiché includere questo vantaggio risulta nel ciclo, scartatelo. Scegli il bordo 0-7. Nessun ciclo si forma, includilo.

Aggiungi il bordo 0-7 in MST

Aggiungi il bordo 0-7 in MST

Passaggio 8: Scegli il bordo 1-2. Poiché includere questo vantaggio risulta nel ciclo, scartatelo. Scegli il bordo 3-4. Nessun ciclo si forma, includilo.

Aggiungi il bordo 3-4 nel MST

Aggiungi il bordo 3-4 nel MST

Nota: Poiché il numero di archi inclusi nell'MST è pari a (V – 1), l'algoritmo si ferma qui

rinominare una directory linux

Di seguito è riportata l’implementazione dell’approccio di cui sopra:

C++




// C++ program for the above approach> > #include> using> namespace> std;> > // DSU data structure> // path compression + rank by union> class> DSU {> >int>* parent;> >int>* rank;> > public>:> >DSU(>int> n)> >{> >parent =>new> int>[n];> >rank =>new> int>[n];> > >for> (>int> i = 0; i parent[i] = -1; rank[i] = 1; } } // Find function int find(int i) { if (parent[i] == -1) return i; return parent[i] = find(parent[i]); } // Union function void unite(int x, int y) { int s1 = find(x); int s2 = find(y); if (s1 != s2) { if (rank[s1] parent[s1] = s2; } else if (rank[s1]>rango[s2]) { genitore[s2] = s1; } else { genitore[s2] = s1; rango[s1] += 1; } } } }; class Graph { vectorint>> edgelist; in tv; pubblico: Graph(int V) { this->V = V; } // Funzione per aggiungere un bordo in un grafico void addEdge(int x, int y, int w) { edgelist.push_back({ w, x, y }); } void kruskals_mst() { // Ordina tutti i bordi sort(edgelist.begin(), edgelist.end()); // Inizializza la DSU DSU s(V); int ans = 0; cout<< 'Following are the edges in the ' 'constructed MST' << endl; for (auto edge : edgelist) { int w = edge[0]; int x = edge[1]; int y = edge[2]; // Take this edge in MST if it does // not forms a cycle if (s.find(x) != s.find(y)) { s.unite(x, y); ans += w; cout << x << ' -- ' << y << ' == ' << w << endl; } } cout << 'Minimum Cost Spanning Tree: ' << ans; } }; // Driver code int main() { Graph g(4); g.addEdge(0, 1, 10); g.addEdge(1, 3, 15); g.addEdge(2, 3, 4); g.addEdge(2, 0, 6); g.addEdge(0, 3, 5); // Function call g.kruskals_mst(); return 0; }>

>

>

C




// C code to implement Kruskal's algorithm> > #include> #include> > // Comparator function to use in sorting> int> comparator(>const> void>* p1,>const> void>* p2)> {> >const> int>(*x)[3] = p1;> >const> int>(*y)[3] = p2;> > >return> (*x)[2] - (*y)[2];> }> > // Initialization of parent[] and rank[] arrays> void> makeSet(>int> parent[],>int> rank[],>int> n)> {> >for> (>int> i = 0; i parent[i] = i; rank[i] = 0; } } // Function to find the parent of a node int findParent(int parent[], int component) { if (parent[component] == component) return component; return parent[component] = findParent(parent, parent[component]); } // Function to unite two sets void unionSet(int u, int v, int parent[], int rank[], int n) { // Finding the parents u = findParent(parent, u); v = findParent(parent, v); if (rank[u] parent[u] = v; } else if (rank[u]>rango[v]) { genitore[v] = u; } else { genitore[v] = u; // Poiché il rango aumenta se // i ranghi di due insiemi sono uguali[u]++; } } // Funzione per trovare l'MST void kruskalAlgo(int n, int edge[n][3]) { // Per prima cosa ordiniamo l'array di edge in ordine crescente // in modo da poter accedere alle distanze minime/costo qsort(edge , n, sizeof(edge[0]), comparatore); int genitore[n]; int rango[n]; // Funzione per inizializzare parent[] e rango[] makeSet(parent, rango, n); // Per memorizzare il costo minimo int minCost = 0; printf( 'Seguono gli spigoli nel MST costruito '); for (int i = 0; i int v1 = findParent(parent, edge[i][0]); int v2 = findParent(parent, edge[i][1]); int wt = edge[i][2] ; // Se i genitori sono diversi // significa che si trovano in insiemi diversi, quindi // uniscili if (v1 != v2) { unionSet(v1, v2, parent, minCost += wt); '%d -- %d == %d ', edge[i][0], edge[i][1], wt } } printf('Albero di copertura del costo minimo: %d); n', minCost); } // Codice driver int main() { int edge[5][3] = { { 0, 1, 10 }, { 0, 2, 6 }, { 0, 3, 5 } , { 1, 3, 15 }, { 2, 3, 4 } }; kruskalAlgo(5, bordo); return 0 }>

>

>

Giava




// Java program for Kruskal's algorithm> > import> java.util.ArrayList;> import> java.util.Comparator;> import> java.util.List;> > public> class> KruskalsMST {> > >// Defines edge structure> >static> class> Edge {> >int> src, dest, weight;> > >public> Edge(>int> src,>int> dest,>int> weight)> >{> >this>.src = src;> >this>.dest = dest;> >this>.weight = weight;> >}> >}> > >// Defines subset element structure> >static> class> Subset {> >int> parent, rank;> > >public> Subset(>int> parent,>int> rank)> >{> >this>.parent = parent;> >this>.rank = rank;> >}> >}> > >// Starting point of program execution> >public> static> void> main(String[] args)> >{> >int> V =>4>;> >List graphEdges =>new> ArrayList(> >List.of(>new> Edge(>0>,>1>,>10>),>new> Edge(>0>,>2>,>6>),> >new> Edge(>0>,>3>,>5>),>new> Edge(>1>,>3>,>15>),> >new> Edge(>2>,>3>,>4>)));> > >// Sort the edges in non-decreasing order> >// (increasing with repetition allowed)> >graphEdges.sort(>new> Comparator() {> >@Override> public> int> compare(Edge o1, Edge o2)> >{> >return> o1.weight - o2.weight;> >}> >});> > >kruskals(V, graphEdges);> >}> > >// Function to find the MST> >private> static> void> kruskals(>int> V, List edges)> >{> >int> j =>0>;> >int> noOfEdges =>0>;> > >// Allocate memory for creating V subsets> >Subset subsets[] =>new> Subset[V];> > >// Allocate memory for results> >Edge results[] =>new> Edge[V];> > >// Create V subsets with single elements> >for> (>int> i =>0>; i subsets[i] = new Subset(i, 0); } // Number of edges to be taken is equal to V-1 while (noOfEdges 1) { // Pick the smallest edge. And increment // the index for next iteration Edge nextEdge = edges.get(j); int x = findRoot(subsets, nextEdge.src); int y = findRoot(subsets, nextEdge.dest); // If including this edge doesn't cause cycle, // include it in result and increment the index // of result for next edge if (x != y) { results[noOfEdges] = nextEdge; union(subsets, x, y); noOfEdges++; } j++; } // Print the contents of result[] to display the // built MST System.out.println( 'Following are the edges of the constructed MST:'); int minCost = 0; for (int i = 0; i System.out.println(results[i].src + ' -- ' + results[i].dest + ' == ' + results[i].weight); minCost += results[i].weight; } System.out.println('Total cost of MST: ' + minCost); } // Function to unite two disjoint sets private static void union(Subset[] subsets, int x, int y) { int rootX = findRoot(subsets, x); int rootY = findRoot(subsets, y); if (subsets[rootY].rank subsets[rootY].parent = rootX; } else if (subsets[rootX].rank subsets[rootX].parent = rootY; } else { subsets[rootY].parent = rootX; subsets[rootX].rank++; } } // Function to find parent of a set private static int findRoot(Subset[] subsets, int i) { if (subsets[i].parent == i) return subsets[i].parent; subsets[i].parent = findRoot(subsets, subsets[i].parent); return subsets[i].parent; } } // This code is contributed by Salvino D'sa>

1nf 2nf 3nf
>

>

Python3




# Python program for Kruskal's algorithm to find> # Minimum Spanning Tree of a given connected,> # undirected and weighted graph> > > # Class to represent a graph> class> Graph:> > >def> __init__(>self>, vertices):> >self>.V>=> vertices> >self>.graph>=> []> > ># Function to add an edge to graph> >def> addEdge(>self>, u, v, w):> >self>.graph.append([u, v, w])> > ># A utility function to find set of an element i> ># (truly uses path compression technique)> >def> find(>self>, parent, i):> >if> parent[i] !>=> i:> > ># Reassignment of node's parent> ># to root node as> ># path compression requires> >parent[i]>=> self>.find(parent, parent[i])> >return> parent[i]> > ># A function that does union of two sets of x and y> ># (uses union by rank)> >def> union(>self>, parent, rank, x, y):> > ># Attach smaller rank tree under root of> ># high rank tree (Union by Rank)> >if> rank[x] parent[x] = y elif rank[x]>rango[y]: parent[y] = x # Se i ranghi sono uguali, creane uno come root # e incrementa il suo rango di un altro: parent[y] = x rango[x] += 1 # La funzione principale da costruire MST # usando l'algoritmo di Kruskal def KruskalMST(self): # Questo memorizzerà il risultato MST result = [] # Una variabile indice, usata per gli archi ordinati i = 0 # Una variabile indice, usata per result[] e = 0 # Ordina tutti gli spigoli in # ordine non decrescente del loro # peso self.graph = sorted(self.graph, key=lambda item: item[2]) parent = [] rango = [] # Crea V sottoinsiemi con singoli elementi for node in range(self.V): parent.append(node) ranking.append(0) # Il numero di archi da prendere è inferiore a V-1 while e

>

file con estensione java

>

C#




// C# Code for the above approach> > using> System;> > class> Graph {> > >// A class to represent a graph edge> >class> Edge : IComparable {> >public> int> src, dest, weight;> > >// Comparator function used for sorting edges> >// based on their weight> >public> int> CompareTo(Edge compareEdge)> >{> >return> this>.weight - compareEdge.weight;> >}> >}> > >// A class to represent> >// a subset for union-find> >public> class> subset {> >public> int> parent, rank;> >};> > >// V->NO. di vertici & E->n.di spigoli> >int> V, E;> > >// Collection of all edges> >Edge[] edge;> > >// Creates a graph with V vertices and E edges> >Graph(>int> v,>int> e)> >{> >V = v;> >E = e;> >edge =>new> Edge[E];> >for> (>int> i = 0; i edge[i] = new Edge(); } // A utility function to find set of an element i // (uses path compression technique) int find(subset[] subsets, int i) { // Find root and make root as // parent of i (path compression) if (subsets[i].parent != i) subsets[i].parent = find(subsets, subsets[i].parent); return subsets[i].parent; } // A function that does union of // two sets of x and y (uses union by rank) void Union(subset[] subsets, int x, int y) { int xroot = find(subsets, x); int yroot = find(subsets, y); // Attach smaller rank tree under root of // high rank tree (Union by Rank) if (subsets[xroot].rank subsets[xroot].parent = yroot; else if (subsets[xroot].rank>sottoinsiemi[yroot].rank) sottoinsiemi[yroot].parent = xroot; // Se i ranghi sono gli stessi, creane uno come root // e incrementa il suo rango di un altro { subsets[yroot].parent = xroot; sottoinsiemi[xroot].rank++; } } // La funzione principale per costruire MST // utilizzando l'algoritmo di Kruskal void KruskalMST() { // Questo memorizzerà il // MST risultante Edge[] result = new Edge[V]; // Una variabile indice, utilizzata per result[] int e = 0; // Una variabile indice, utilizzata per gli archi ordinati int i = 0; for (i = 0; i result[i] = new Edge(); // Ordina tutti gli archi in ordine // non decrescente in base al loro peso. Se non ci è consentito // modificare il grafico dato, possiamo creare // una copia dell'array di bordi Array.Sort(edge ​​// Alloca memoria per la creazione di V subset subset[] subsets = new subset[V] for (i = 0; i subsets[i] = new subset()); ; // Crea V sottoinsiemi con singoli elementi for (int v = 0; v subsets[v].parent = v; subsets[v].rank = 0; } i = 0; // Il numero di archi da prendere è uguale a V-1 while (e // Scegli il bordo più piccolo. E incrementa // l'indice per l'iterazione successiva Edge next_edge = new Edge(); next_edge = edge[i++]; int x = find(subsets, next_edge.src); int y = find(subsets, next_edge.dest); // Se includere questo bordo non causa il ciclo, // includerlo nel risultato e incrementare l'indice // del risultato per il bordo successivo if (x != y) { result[e++] = next_edge; Union(subsets, x, y); il MST costruito'); int costo minimo = 0; for (i = 0; i Console.WriteLine(risultato[i].src + ' -- ' + risultato[i].dest + ' == ' + risultato[i].peso); costominimo += risultato[i].weight; } Console.WriteLine('Spanning Tree costo minimo: ' + MinimumCost(} // Codice del driver public static void Main(String[] args) {); int V = 4; int E = 5; grafico grafico = nuovo grafico(V, E); graph.edge[0].weight = 10; // aggiungi bordo 0-2 graph.edge[1].src = 0; graph.edge[1].dest = 2; graph.edge[1].weight = 6 ; // aggiungi il bordo 0-3 graph.edge[2].src = 0; graph.edge[2].dest = 3; graph.edge[2].weight = 5; bordo[3].src = 1; grafico.edge[3].dest = 3; grafico.edge[3].peso = 15; // aggiunge bordo 2-3 grafico.edge[4].src = 2; .edge[4].dest = 3; graph.edge[4].weight = 4; // Chiamata di funzione graph.KruskalMST();

> 




> // JavaScript implementation of the krushkal's algorithm.> > function> makeSet(parent,rank,n)> {> >for>(let i=0;i { parent[i]=i; rank[i]=0; } } function findParent(parent,component) { if(parent[component]==component) return component; return parent[component] = findParent(parent,parent[component]); } function unionSet(u, v, parent, rank,n) { //this function unions two set on the basis of rank //as shown below u=findParent(parent,u); v=findParent(parent,v); if(rank[u] { parent[u]=v; } else if(rank[u] { parent[v]=u; } else { parent[v]=u; rank[u]++;//since the rank increases if the ranks of two sets are same } } function kruskalAlgo(n, edge) { //First we sort the edge array in ascending order //so that we can access minimum distances/cost edge.sort((a, b)=>{ return a[2] - b[2]; }) //la funzione di ordinamento rapido incorporata viene fornita con stdlib.h //vai a https://www.techcodeview.com L'ordinamento dei bordi richiede tempo O(E * logE). Dopo l'ordinamento, iteriamo su tutti gli spigoli e applichiamo l'algoritmo di ricerca unione. Le operazioni di ricerca e unione possono richiedere al massimo O(logV) tempo. Quindi la complessità complessiva è il tempo O(E * logE + E * logV). Il valore di E può essere al massimo O(V2), quindi O(logV) e O(logE) sono la stessa cosa. Pertanto, la complessità temporale complessiva è O(E * logE) o O(E*logV) Spazio ausiliario: O(V + E), dove V è il numero di vertici ed E è il numero di archi nel grafico. Questo articolo è stato compilato da Aashish Barnwal e rivisto dal team techcodeview.com.>