Topologisk sortering for Regissert asyklisk graf (DAG) er en lineær rekkefølge av toppunkter slik at for hver rettet kant u-v, toppunkt i kommer før i i bestillingen.
Merk: Topologisk sortering for en graf er ikke mulig hvis grafen ikke er en DAG .
Eksempel:
Anbefalt praksisDFS-basert løsning for å finne en topologisk sortering har allerede vært diskutert.Inndata: Graf :
Eksempel
Produksjon: 5 4 2 3 1 0
Forklaring: Det første toppunktet i topologisk sortering er alltid et toppunkt med en in-grad på 0 (et toppunkt uten innkommende kanter). En topologisk sortering av følgende graf er 5 4 2 3 1 0. Det kan være mer enn én topologisk sortering for en graf. En annen topologisk sortering av følgende graf er 4 5 2 3 1 0.konverter streng til heltall
Topologisk rekkefølge er kanskje ikke unik:
Topologisk sortering er et avhengighetsproblem der fullføring av en oppgave avhenger av fullføring av flere andre oppgaver hvis rekkefølge kan variere. La oss forstå dette konseptet med et eksempel:
Anta at vår oppgave er å nå skolen vår, og for å nå dit må vi først kle på oss. Avhengighetene til å bruke klær er vist i avhengighetsgrafen nedenfor. For eksempel kan du ikke bruke sko før du bruker sokker.
Fra bildet ovenfor ville du allerede ha innsett at det finnes flere måter å kle seg på, bildet nedenfor viser noen av disse måtene.
strengformat i java
Kan du liste all mulig topologisk rekkefølge av å kle seg for over avhengighetsgrafen?
Algoritme for topologisk sortering ved bruk av DFS:
Her er en trinn-for-trinn-algoritme for topologisk sortering ved hjelp av Depth First Search (DFS):
- Lag en graf med n hjørner og m -rettede kanter.
- Initialiser en stabel og en besøkt rekke av størrelse n .
- Gjør følgende for hvert ubesøkt toppunkt i grafen:
- Kall DFS-funksjonen med toppunktet som parameter.
- I DFS-funksjonen merker du toppunktet som besøkt og kaller DFS-funksjonen rekursivt for alle ubesøkte naboer til toppunktet.
- Når alle naboene har blitt besøkt, skyver du toppunktet på stabelen.
- Tross alt er hjørnene besøkt, pop elementer fra stabelen og legg dem til utdatalisten til stabelen er tom.
- Den resulterende listen er den topologisk sorterte rekkefølgen av grafen.
Illustrasjonstopologisk sorteringsalgoritme:
Bildet nedenfor er en illustrasjon av tilnærmingen ovenfor:

Overordnet arbeidsflyt av topologisk sortering
Trinn 1:
- Vi starter DFS fra node 0 fordi den har null innkommende noder
- Vi skyver node 0 i stabelen og flytter til neste node med minimum antall tilstøtende noder, dvs. node 1.
Steg 2:
- I dette trinnet, fordi det ikke er noen ved siden av denne noden, så skyv node 1 i stabelen og gå til neste node.
Trinn 3:
- I dette trinnet velger vi node 2 fordi den har minimum antall tilstøtende noder etter 0 og 1.
- Vi kaller DFS for node 2 og skyver alle nodene som kommer på kryss og tvers fra node 2 i omvendt rekkefølge.
- Så trykk 3 og deretter 2.
Trinn 4:
- Vi kaller nå DFS for node 4
- Fordi 0 og 1 allerede er til stede i stabelen, så vi bare skyver node 4 i stabelen og returnerer.
rujira banerjeeTrinn 5:
- I dette trinnet, fordi alle tilstøtende noder av 5 allerede er i stabelen, skyver vi node 5 i stabelen og går tilbake.
ubuntu bygge viktigTrinn 6: Dette er det siste trinnet i den topologiske sorteringen der vi henter alt elementet fra stabelen og skriver det ut i den rekkefølgen.
Nedenfor er implementeringen av tilnærmingen ovenfor:
C++ #include using namespace std; // Function to perform DFS and topological sorting void topologicalSortUtil(int v, vector>& adj, vektor & besøkt, stable & Stack) { // Merk gjeldende node som besøkt besøkt[v] = sant; // Gjenta for alle tilstøtende hjørner for (int i : adj[v]) { if (!besøkt[i]) topologiskSortUtil(i, adj, besøkt, Stack); } // Skyv gjeldende toppunkt til stabel som lagrer resultatet Stack.push(v); } // Funksjon for å utføre Topologisk Sortering void topologicalSort(vector>& adj, int V) { stabel Stable; // Stable for å lagre resultatvektoren besøkt(V, usann); // Kall den rekursive hjelpefunksjonen for å lagre // Topologisk sortering starter fra alle toppunkter én etter // én for (int i = 0; i< V; i++) { if (!visited[i]) topologicalSortUtil(i, adj, visited, Stack); } // Print contents of stack while (!Stack.empty()) { cout << Stack.top() << ' '; Stack.pop(); } } int main() { // Number of nodes int V = 4; // Edges vector> kanter = { { 0, 1 }, { 1, 2 }, { 3, 1 }, { 3, 2 } }; // Graf representert som en tilgrensende listevektor> adj(V); for (auto i : kanter) { adj[i[0]].push_back(i[1]); } cout<< 'Topological sorting of the graph: '; topologicalSort(adj, V); return 0; }>
Java import java.util.*; public class TopologicalSort { // Function to perform DFS and topological sorting static void topologicalSortUtil(int v, List> adj, boolsk[] besøkt, stabel stack) { // Merk gjeldende node som besøkt besøkt[v] = sant; // Gjenta for alle tilstøtende hjørner for (int i : adj.get(v)) { if (!besøkt[i]) topologicalSortUtil(i, adj, besøkt, stack); } // Skyv gjeldende toppunkt til stabelen som lagrer // resultatet stack.push(v); } // Funksjon for å utføre Topological Sort static void topologicalSort(List> adj, int V) { // Stack for å lagre resultatet Stack stack = ny stabel(); boolsk[] besøkt = ny boolsk[V]; // Kall den rekursive hjelpefunksjonen for å lagre // Topologisk sortering starter fra alle toppunktene en // etter en for (int i = 0; i< V; i++) { if (!visited[i]) topologicalSortUtil(i, adj, visited, stack); } // Print contents of stack System.out.print( 'Topological sorting of the graph: '); while (!stack.empty()) { System.out.print(stack.pop() + ' '); } } // Driver code public static void main(String[] args) { // Number of nodes int V = 4; // Edges List> edges = new ArrayList(); edges.add(Arrays.asList(0, 1)); edges.add(Arrays.asList(1, 2)); edges.add(Arrays.asList(3, 1)); edges.add(Arrays.asList(3, 2)); // Graf representert som en tilstøtende liste Liste> adj = ny ArrayList(V); for (int i = 0; i< V; i++) { adj.add(new ArrayList()); } for (List i : edges) { adj.get(i.get(0)).add(i.get(1)); } topologiskSort(adj, V); } }>
Python3 def topologicalSortUtil(v, adj, visited, stack): # Mark the current node as visited visited[v] = True # Recur for all adjacent vertices for i in adj[v]: if not visited[i]: topologicalSortUtil(i, adj, visited, stack) # Push current vertex to stack which stores the result stack.append(v) # Function to perform Topological Sort def topologicalSort(adj, V): # Stack to store the result stack = [] visited = [False] * V # Call the recursive helper function to store # Topological Sort starting from all vertices one by # one for i in range(V): if not visited[i]: topologicalSortUtil(i, adj, visited, stack) # Print contents of stack print('Topological sorting of the graph:', end=' ') while stack: print(stack.pop(), end=' ') # Driver code if __name__ == '__main__': # Number of nodes V = 4 # Edges edges = [[0, 1], [1, 2], [3, 1], [3, 2]] # Graph represented as an adjacency list adj = [[] for _ in range(V)] for i in edges: adj[i[0]].append(i[1]) topologicalSort(adj, V)>
C# using System; using System.Collections.Generic; class Program { // Function to perform DFS and topological sorting static void TopologicalSortUtil(int v, List> adj, bool[] besøkt, Stack stack) { // Merk gjeldende node som besøkt besøkt[v] = sant; // Gjenta for alle tilstøtende hjørner foreach(int i i adj[v]) { if (!besøkt[i]) TopologicalSortUtil(i, adj, besøkt, stack); } // Skyv gjeldende toppunkt til stabelen som lagrer // resultatstabelen. Push(v); } // Funksjon for å utføre Topological Sort static void TopologicalSort(List> adj, int V) { // Stack for å lagre resultatet Stack stabel = ny stabel (); bool[] besøkt = ny bool[V]; // Kall den rekursive hjelpefunksjonen for å lagre // Topologisk sortering starter fra alle toppunktene en // etter en for (int i = 0; i< V; i++) { if (!visited[i]) TopologicalSortUtil(i, adj, visited, stack); } // Print contents of stack Console.Write('Topological sorting of the graph: '); while (stack.Count>0) { Console.Write(stack.Pop() + ' '); } } // Driver code static void Main(string[] args) { // Antall noder int V = 4; // Kantliste> kanter = ny liste>{ ny liste { 0, 1 }, ny liste { 1, 2 }, ny liste { 3, 1 }, ny liste { 3, 2 } }; // Graf representert som en tilstøtende liste Liste> adj = ny liste>(); for (int i = 0; i< V; i++) { adj.Add(new List ()); } foreach(Liste i i kanter) { adj[i[0]].Add(i[1]); } TopologiskSort(adj, V); } }>
Javascript // Function to perform DFS and topological sorting function topologicalSortUtil(v, adj, visited, stack) { // Mark the current node as visited visited[v] = true; // Recur for all adjacent vertices for (let i of adj[v]) { if (!visited[i]) topologicalSortUtil(i, adj, visited, stack); } // Push current vertex to stack which stores the result stack.push(v); } // Function to perform Topological Sort function topologicalSort(adj, V) { // Stack to store the result let stack = []; let visited = new Array(V).fill(false); // Call the recursive helper function to store // Topological Sort starting from all vertices one by // one for (let i = 0; i < V; i++) { if (!visited[i]) topologicalSortUtil(i, adj, visited, stack); } // Print contents of stack console.log('Topological sorting of the graph: '); while (stack.length>0) { console.log(stack.pop() + ' '); } } // Driverkode (() => { // Antall noder const V = 4; // Edges const edges = [[0, 1], [1, 2], [3, 1], [3, 2]]; // Graf representert som en adjacency list const adj = Array.from({ length: V }, () => []); (i[1]); } topologicalSort(adj, V })();>
Produksjon
Topological sorting of the graph: 3 0 1 2>
Tidskompleksitet: O(V+E). Algoritmen ovenfor er ganske enkelt DFS med en ekstra stabel. Så tidskompleksitet er det samme som DFS
Ekstra plass: O(V). Den ekstra plassen er nødvendig for stabelen
Topologisk sortering ved hjelp av BFS:
C++ #include #include #include using namespace std; // Class to represent a graph class Graph { int V; // No. of vertices list * adj; // Peker til en matrise som inneholder // adjacency lists public: Graph(int V); // Konstruktør void addEdge(int v, int w); // Funksjon for å legge til en kant til grafen void topologicalSort(); // skriver ut en topologisk sort av // hele grafen }; Graph::Graph(int V) { this->V = V; adj = ny liste [V]; } void Graph::addEdge(int v, int w) { adj[v].push_back(w); // Legg til w til vs liste. } // Funksjon for å utføre Topological Sort void Graph::topologicalSort() { // Lag en vektor for å lagre i-grad av alle toppunktvektorer in_degree(V, 0); // Gå gjennom tilgrensende lister for å fylle ut_grad av // toppunkter for (int v = 0; v< V; ++v) { for (auto const& w : adj[v]) in_degree[w]++; } // Create a queue and enqueue all vertices with // in-degree 0 queue q; for (int i = 0; i< V; ++i) { if (in_degree[i] == 0) q.push(i); } // Initialize count of visited vertices int count = 0; // Create a vector to store topological order vector top_order; // En etter en dekø-vertices fra køen og enqueue // tilstøtende vertices hvis in-degree of adjacent blir 0 mens (!q.empty()) { // Trekk ut foran køen (eller utfør dequeue) // og legg den til topologisk rekkefølge int u = q.front(); q.pop(); top_order.push_back(u); // Iterer gjennom alle de nærliggende nodene // av node u som ikke er i kø og reduser deres in-grad // med 1 liste ::iterator itr; for (itr = adj[u].begin(); itr != adj[u].end(); ++itr) // Hvis in-degree blir null, legg den til i køen if (--in_degree[*itr) ] == 0) q.push(*itr); telle++; } // Sjekk om det var en syklus hvis (tell != V) { cout<< 'Graph contains cycle
'; return; } // Print topological order for (int i : top_order) cout << i << ' '; } // Driver code int main() { // Create a graph given in the above diagram Graph g(6); g.addEdge(5, 2); g.addEdge(5, 0); g.addEdge(4, 0); g.addEdge(4, 1); g.addEdge(2, 3); g.addEdge(3, 1); cout << 'Following is a Topological Sort of the given ' 'graph
'; g.topologicalSort(); return 0; }>
Java import java.util.ArrayList; import java.util.LinkedList; import java.util.Queue; // Class to represent a graph class Graph { private int V; // No. of vertices private ArrayList [] adj; // Adjacency list // representasjon av // grafen // Constructor Graph(int V) { this.V = V; adj = ny ArrayList[V]; for (int i = 0; i< V; ++i) adj[i] = new ArrayList(); } // Function to add an edge to the graph void addEdge(int v, int w) { adj[v].add(w); // Add w to v’s list. } // Function to perform Topological Sort void topologicalSort() { // Create an array to store in-degree of all // vertices int[] inDegree = new int[V]; // Calculate in-degree of each vertex for (int v = 0; v < V; ++v) { for (int w : adj[v]) { inDegree[w]++; } } // Create a queue and enqueue all vertices with // in-degree 0 Queue q = new LinkedList(); for (int i = 0; i< V; ++i) { if (inDegree[i] == 0) q.add(i); } // Initialize count of visited vertices int count = 0; // Create an ArrayList to store topological order ArrayList topOrder = new ArrayList(); // En etter en dekø-vertices fra køen og // setter tilstøtende vertices hvis in-degree av // adjacent blir 0 mens (!q.isEmpty()) { // Trekk ut forsiden av køen og legg den til // topologisk rekkefølge int u = q.poll(); topOrder.add(u); telle++; // Iterer gjennom alle nabonodene til // dekøet node u og reduser deres in-degree // med 1 for (int w : adj[u]) { // Hvis in-degree blir null, legg den til // køen if (-inDegree[w] == 0) q.add(w); } } // Sjekk om det var en syklus if (tell != V) { System.out.println('Graf inneholder syklus'); komme tilbake; } // Skriv ut topologisk rekkefølge for (int i : topOrder) System.out.print(i + ' '); } } // Driverkode public class Main { public static void main(String[] args) { // Lag en graf gitt i diagrammet ovenfor Graph g = new Graph(6); g.addEdge(5, 2); g.addEdge(5, 0); g.addEdge(4, 0); g.addEdge(4, 1); g.addEdge(2, 3); g.addEdge(3, 1); System.out.println( 'Følgende er en topologisk sortering av den gitte grafen'); g.topologicalSort(); } }>
Python3 from collections import defaultdict class Graph: def __init__(self, vertices): # Number of vertices self.V = vertices # Dictionary to store adjacency lists self.adj = defaultdict(list) def addEdge(self, u, v): # Function to add an edge to the graph self.adj[u].append(v) def topologicalSort(self): # Function to perform Topological Sort # Create a list to store in-degree of all vertices in_degree = [0] * self.V # Traverse adjacency lists to fill in_degree of vertices for i in range(self.V): for j in self.adj[i]: in_degree[j] += 1 # Create a queue and enqueue all vertices with in-degree 0 q = [] for i in range(self.V): if in_degree[i] == 0: q.append(i) # Initialize count of visited vertices count = 0 # Create a list to store topological order top_order = [] # One by one dequeue vertices from queue and enqueue # adjacent vertices if in-degree of adjacent becomes 0 while q: # Extract front of queue (or perform dequeue) # and add it to topological order u = q.pop(0) top_order.append(u) # Iterate through all its neighbouring nodes # of dequeued node u and decrease their in-degree # by 1 for node in self.adj[u]: # If in-degree becomes zero, add it to queue in_degree[node] -= 1 if in_degree[node] == 0: q.append(node) count += 1 # Check if there was a cycle if count != self.V: print('Graph contains cycle') return # Print topological order print('Topological Sort:', top_order) # Driver code if __name__ == '__main__': # Create a graph given in the above diagram g = Graph(6) g.addEdge(5, 2) g.addEdge(5, 0) g.addEdge(4, 0) g.addEdge(4, 1) g.addEdge(2, 3) g.addEdge(3, 1) print('Following is a Topological Sort of the given graph') g.topologicalSort()>
JavaScript // Class to represent a graph class Graph { constructor(V) { this.V = V; // No. of vertices this.adj = new Array(V); // Array containing adjacency lists for (let i = 0; i < V; i++) { this.adj[i] = []; } } // Function to add an edge to the graph addEdge(v, w) { this.adj[v].push(w); // Add w to v’s list. } // Function to perform Topological Sort topologicalSort() { // Create a array to store in-degree of all vertices let inDegree = new Array(this.V).fill(0); // Traverse adjacency lists to fill inDegree of vertices for (let v = 0; v < this.V; v++) { for (let w of this.adj[v]) { inDegree[w]++; } } // Create a queue and enqueue all vertices with in-degree 0 let queue = []; for (let i = 0; i < this.V; i++) { if (inDegree[i] === 0) { queue.push(i); } } // Initialize count of visited vertices let count = 0; // Create an array to store topological order let topOrder = []; // One by one dequeue vertices from queue and enqueue // adjacent vertices if in-degree of adjacent becomes 0 while (queue.length !== 0) { // Extract front of queue and add it to topological order let u = queue.shift(); topOrder.push(u); // Iterate through all its neighboring nodes // of dequeued node u and decrease their in-degree by 1 for (let w of this.adj[u]) { // If in-degree becomes zero, add it to queue if (--inDegree[w] === 0) { queue.push(w); } } count++; } // Check if there was a cycle if (count !== this.V) { console.log('Graph contains cycle'); return; } // Print topological order console.log('Topological Sort of the given graph:'); console.log(topOrder.join(' ')); } } // Driver code // Create a graph given in the above diagram let g = new Graph(6); g.addEdge(5, 2); g.addEdge(5, 0); g.addEdge(4, 0); g.addEdge(4, 1); g.addEdge(2, 3); g.addEdge(3, 1); console.log('Following is a Topological Sort of the given graph:'); g.topologicalSort(); //This code is contributed by Utkarsh>
Produksjon
Following is a Topological Sort of the given graph 4 5 2 0 3 1>
Tidskompleksitet:
Tidskompleksiteten for å konstruere grafen er O(V + E), der V er antall hjørner og E er antall kanter.
Tidskompleksiteten for å utføre topologisk sortering ved bruk av BFS er også O(V + E), der V er antall toppunkter og E er antall kanter. Dette er fordi hvert toppunkt og hver kant besøkes én gang under BFS-traverseringen.
Plass kompleksitet:
Plasskompleksiteten for å lagre grafen ved hjelp av en tilstøtende liste er O(V + E), der V er antall toppunkter og E er antall kanter.
Ytterligere plass brukes til å lagre toppen av toppene, noe som krever O(V) plass.
En kø brukes for BFS-traversering, som kan inneholde på de fleste V-punktene. Dermed er plasskompleksiteten for køen O(V).
govinda
Totalt sett er romkompleksiteten til algoritmen O(V + E) på grunn av lagringen av grafen, in-degree array og køen.
Oppsummert er tidskompleksiteten til den angitte implementeringen O(V + E), og romkompleksiteten er også O(V + E).
Merk: Her kan vi også bruke en matrise i stedet for stabelen. Hvis matrisen brukes, skriv ut elementene i omvendt rekkefølge for å få den topologiske sorteringen.
Fordeler med topologisk sortering:
- Hjelper med å planlegge oppgaver eller hendelser basert på avhengigheter.
- Oppdager sykluser i en rettet graf.
- Effektiv for å løse problemer med forrangsbegrensninger.
Ulemper med topologisk sortering:
- Gjelder kun for dirigerte asykliske grafer (DAG), ikke egnet for sykliske grafer.
- Kan ikke være unik, flere gyldige topologiske rekkefølger kan eksistere.
- Ineffektiv for store grafer med mange noder og kanter.
Anvendelser av topologisk sort:
- Oppgaveplanlegging og prosjektledelse.
- Avhengighetsløsning i pakkehåndteringssystemer.
- Bestemme rekkefølgen for kompilering i programvarebyggesystemer.
- Deadlock-deteksjon i operativsystemer.
- Kursplanlegging ved universiteter.
Relaterte artikler:
- Kahns algoritme for topologisk sortering
- Alle topologiske typer av en rettet asyklisk graf