Un arbore care se întinde minim (MST) sau arborele de întindere cu greutate minimă pentru un grafic ponderat, conectat, nedirecționat este un arbore de întindere cu o greutate mai mică sau egală cu greutatea oricărui alt arbore de întindere. Pentru a afla mai multe despre Minimum Spanning Tree, consultați Acest articol .
Introducere în algoritmul lui Kruskal:
Aici vom discuta algoritmul lui Kruskal pentru a găsi MST-ul unui grafic ponderat dat.
În algoritmul lui Kruskal, sortați toate marginile graficului dat în ordine crescătoare. Apoi continuă să adauge noi margini și noduri în MST dacă marginea nou adăugată nu formează un ciclu. Alege marginea ponderată minimă la început și marginea ponderată maximă în cele din urmă. Astfel putem spune că face o alegere optimă local în fiecare pas pentru a găsi soluția optimă. Prin urmare, acesta este un Mai jos sunt pașii pentru găsirea MST folosind algoritmul lui Kruskal:
- Sortați toate marginile în ordinea nedescrescătoare a greutății lor.
- Alegeți cea mai mică margine. Verificați dacă formează un ciclu cu arborele de întindere format până acum. Dacă ciclul nu este format, includeți această margine. Altfel, aruncă-l.
- Repetați pasul #2 până când există margini (V-1) în arborele de întindere.
Pasul 2 folosește Algoritmul Union-Find pentru a detecta ciclurile.
Așa că vă recomandăm să citiți următoarea postare ca o condiție prealabilă.
- Algoritmul Union-Find | Set 1 (Detectează ciclu într-un grafic)
- Algoritmul Unirii-Găsire | Setul 2 (Unirea după rang și comprimarea căii)
Algoritmul lui Kruskal pentru a găsi arborele de acoperire a costurilor minime folosește abordarea lacomă. Alegerea Greedy este de a alege cea mai mică margine de greutate care nu provoacă un ciclu în MST construit până acum. Să înțelegem cu un exemplu:
Ilustrare:
Mai jos este ilustrarea abordării de mai sus:
căutare binară în java
Grafic de intrare:
Graficul conține 9 vârfuri și 14 muchii. Deci, arborele de întindere minim format va avea (9 – 1) = 8 muchii.
Dupa sortare:
Greutate Sursă Destinaţie 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 unsprezece 1 7 14 3 5 Acum alegeți toate marginile una câte una din lista sortată de margini
Pasul 1: Alegeți marginea 7-6. Nu se formează niciun ciclu, includeți-l.
Adăugați marginea 7-6 în MST
Pasul 2: Alegeți marginea 8-2. Nu se formează niciun ciclu, includeți-l.
Adăugați marginea 8-2 în MST
Pasul 3: Alegeți marginea 6-5. Nu se formează niciun ciclu, includeți-l.
Adăugați marginea 6-5 în MST
Pasul 4: Alegeți marginea 0-1. Nu se formează niciun ciclu, includeți-l.
Adăugați marginea 0-1 în MST
Pasul 5: Alegeți marginea 2-5. Nu se formează niciun ciclu, includeți-l.
Adăugați marginea 2-5 în MST
Pasul 6: Alegeți marginea 8-6. Deoarece includerea acestei margini rezultă în ciclu, aruncați-o. Alegeți marginea 2-3: Nu se formează niciun ciclu, includeți-l.
Adăugați marginea 2-3 în MST
Pasul 7: Alegeți marginea 7-8. Deoarece includerea acestei margini rezultă în ciclu, aruncați-o. Alegeți marginea 0-7. Nu se formează niciun ciclu, includeți-l.
Adăugați marginea 0-7 în MST
Pasul 8: Alegeți marginea 1-2. Deoarece includerea acestei margini rezultă în ciclu, aruncați-o. Alegeți marginea 3-4. Nu se formează niciun ciclu, includeți-l.
Adăugați marginea 3-4 în MST
Notă: Deoarece numărul de muchii incluse în MST este egal cu (V – 1), deci algoritmul se oprește aici
Mai jos este implementarea abordării de mai sus:
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]>rang[s2]) { părinte[s2] = s1; } else { părinte[s2] = s1; rang[s1] += 1; } } } }; class Graph { vectorint>> edgelist; în televizor; public: Graph(int V) { this->V = V; } // Funcție de adăugare a muchiei într-un grafic void addEdge(int x, int y, int w) { edgelist.push_back({ w, x, y }); } void kruskals_mst() { // Sortează toate marginile sort(edgelist.begin(), edgelist.end()); // Inițializați 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]>rang[v]) { părinte[v] = u; } else { părinte[v] = u; // Deoarece rangul crește dacă // rangurile a două seturi sunt de același rang[u]++; } } // Funcție pentru a găsi MST void kruskalAlgo(int n, int edge[n][3]) { // Mai întâi sortăm matricea de margini în ordine crescătoare // astfel încât să putem accesa distanțe minime/cost qsort(edge , n, sizeof(edge[0]), comparator); int părinte[n]; int rang[n]; // Funcție de inițializare parent[] și rank[] makeSet(parent, rank, n); // Pentru a stoca costul minim int minCost = 0; printf( 'Urmeaza marginile din MST construit
'); pentru (int i = 0; i int v1 = findParent(parent, edge[i][0]); int v2 = findParent(parent, edge[i][1]); int wt = edge[i][2] ; // Dacă părinții sunt diferiți, // înseamnă că sunt în seturi diferite deci // uniți-i if (v1 != v2) { unionSet(v1, v2, parent, rank, n); '%d -- %d == %d
', margine[i][0], margine[i][1], wt } } printf('Arborele de acoperire a costurilor minime: %d); n', minCost); } // Cod driver int main() { int edge[5][3] = { { 0, 1, 10 }, { 0, 2, 6 }, { 0, 3, 5 } , { 1, 3, 15 }, { 2, 3, 4 } } kruskalAlgo(5, edge); |
>număr în șir java
// 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>>>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]>rang[y]: părinte[y] = x # Dacă rangurile sunt aceleași, atunci creați unul ca rădăcină # și creșteți rangul său cu alt rang: părinte[y] = x rang[x] += 1 # Funcția principală de construit MST # folosind algoritmul lui Kruskal def KruskalMST(self): # Acesta va stoca rezultatul MST rezultat = [] # O variabilă index, folosită pentru muchiile sortate i = 0 # O variabilă index, folosită pentru rezultat[] e = 0 # Sortați toate marginile în # ordinea nedescrescătoare a # greutății lor self.graph = sorted(self.graph, key=lambda item: item[2]) parent = [] rank = [] # Creați V subseturi cu elemente individuale pentru nodul din interval(self.V): parent.append(node) rank.append(0) # Numărul de muchii care trebuie luate este mai mic decât V-1 în timp ce e>>C#
java citiți csv
// 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->Nu. de vârfuri & E->nr.de muchii>>>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>subsets[yroot].rank) subsets[yroot].parent = xroot; // Dacă rangurile sunt aceleași, atunci creați unul ca rădăcină // și creșteți rangul cu unul else { subsets[yroot].parent = xroot; subseturi[xroot].rank++; } } // Funcția principală pentru a construi MST // folosind algoritmul lui Kruskal void KruskalMST() { // Aceasta va stoca // rezultatul MST Edge[] rezultat = new Edge[V]; // O variabilă index, folosită pentru result[] int e = 0; // O variabilă index, folosită pentru muchiile sortate int i = 0; for (i = 0; i result[i] = new Edge(); // Sortați toate muchiile în ordinea nedescrescătoare // a greutății lor. Dacă nu avem voie // să schimbăm graficul dat, putem crea // o copie a matricei de margini Array.Sort(edge) // Alocați memorie pentru crearea V subseturi subset[] subsets = new subset[V] for (i = 0; i subsets[i] = new subset()); ; // Creați V subseturi cu elemente simple pentru (int v = 0; v subseturi[v].parent = v; subseturi[v].rank = 0; } i = 0; // Numărul de muchii care trebuie luate este egal la V-1 while (e // Alegeți cea mai mică muchie. Și creșteți // indexul pentru următoarea iterație Edge next_edge = new Edge(); next_edge = edge[i++]; int x = find(subsets, next_edge.src); int y = find(subsets, next_edge.dest // Dacă includerea acestei margini nu provoacă ciclul, // includeți-o în rezultat și creșteți indicele // de rezultat pentru următoarea muchie if (x != y) { result[e++] = next_edge; Union(subsets, x, y) // Printează conținutul rezultat[] pentru a afișa // MST Console.WriteLine (Urmează marginile în ' + '); MST-ul construit'); int minimumCost = 0; pentru (i = 0; i Console.WriteLine(rezultat[i].src + ' -- ' + rezultat[i].dest + ' == ' + rezultat[i].greutate); cost minim += rezultat[i].weight } Console.WriteLine('Arborele de acoperire a costurilor minime: ' + cost minim Console.ReadLine( } // Codul driverului public static void (String[] args)); int V = 4; int E = 5 Graph = new Graph(V, E) graph.edge[0].greutate = 10; ; // adaugă muchia 0-3 graph.edge[2].src = graph.edge[2].dest = graph.edge[2].weight = 5; edge[3].src = graph.edge[3].dest = graph.edge[3].weight = 15 graph.edge[4].src = 2; .edge[4].dest = 3; graph.edge[4].weight = 4;>
>// JavaScript implementation of the krushkal's algorithm.>>function>makeSet(parent,rank,n)>{>>for>








