Ordenació topològica per Gràfic acíclic dirigit (DAG) és una ordenació lineal de vèrtexs tal que per a cada aresta dirigida u-v, vèrtex en ve abans en en l'ordenació.
Nota: L'ordenació topològica d'un gràfic no és possible si el gràfic no és a DIA .
Exemple:
Pràctica recomanadaSolució basada en DFS per trobar una classificació topològica ja s'ha parlat.Entrada: Gràfic :
números de l'alfabetExemple
Sortida: 5 4 2 3 1 0
Explicació: El primer vèrtex en l'ordenació topològica és sempre un vèrtex amb un grau d'entrada de 0 (un vèrtex sense arestes entrants). Una ordenació topològica del gràfic següent és 5 4 2 3 1 0. Pot haver-hi més d'una ordenació topològica per a un gràfic. Una altra ordenació topològica del gràfic següent és 4 5 2 3 1 0.
L'ordre topològic pot no ser únic:
Ordenació topològica és un problema de dependència en què la realització d'una tasca depèn de la realització d'altres tasques l'ordre de les quals pot variar. Entenem aquest concepte amb un exemple:
Suposem que la nostra tasca és arribar a la nostra Escola i per arribar-hi, primer ens hem de vestir. Les dependències per portar roba es mostren al gràfic de dependències següent. Per exemple, no pots portar sabates abans de posar-te mitjons.
A partir de la imatge de dalt, ja hauríeu adonat que existeixen múltiples maneres de vestir-vos, la imatge de sota mostra algunes d'aquestes maneres.
Pots enumerar tot l'ordenament topològic possible de vestir-se per al gràfic de dependència anterior?
Algorisme per a l'ordenació topològica mitjançant DFS:
A continuació, es mostra un algorisme pas a pas per a l'ordenació topològica mitjançant Depth First Search (DFS):
- Crea un gràfic amb n vèrtexs i m - vores dirigides.
- Inicialitzar una pila i una matriu de mida visitada n .
- Per a cada vèrtex no visitat del gràfic, feu el següent:
- Truqueu a la funció DFS amb el vèrtex com a paràmetre.
- A la funció DFS, marqueu el vèrtex com a visitat i truqueu recursivament a la funció DFS per a tots els veïns no visitats del vèrtex.
- Un cop visitats tots els veïns, empènyer el vèrtex a la pila.
- Després de tot, s'han visitat els vèrtexs, extreu elements de la pila i afegiu-los a la llista de sortida fins que la pila estigui buida.
- La llista resultant és l'ordre topològicament ordenat del gràfic.
Il·lustració Algorisme d'ordenació topològica:
La imatge següent és una il·lustració de l'enfocament anterior:

Flux de treball global de l'ordenació topològica
Pas 1:
- Iniciem DFS des del node 0 perquè té zero nodes entrants
- Empengem el node 0 a la pila i passem al següent node amb un nombre mínim de nodes adjacents, és a dir, el node 1.
Pas 2:
- En aquest pas, com que no hi ha cap adjacent d'aquest node, premeu el node 1 a la pila i aneu al següent node.
Pas 3:
- En aquest pas, escollim el node 2 perquè té un nombre mínim de nodes adjacents després de 0 i 1.
- Anomenem DFS per al node 2 i empenyem tots els nodes que es recorren des del node 2 en ordre invers.
- Així que premeu 3 i després premeu 2.
Pas 4:
- Ara anomenem DFS per al node 4
- Com que el 0 i l'1 ja estan presents a la pila, només hem d'empènyer el node 4 a la pila i tornar.
Pas 5:
- En aquest pas, perquè tots els nodes adjacents de 5 ja estan a la pila, empenyem el node 5 a la pila i tornem.
llista d'enllaços en javaPas 6: Aquest és l'últim pas de l'ordenació topològica en la qual extraïm tot l'element de la pila i l'imprimim en aquest ordre.
A continuació es mostra la implementació de l'enfocament anterior:
C++ #include using namespace std; // Function to perform DFS and topological sorting void topologicalSortUtil(int v, vector>& adj, vector & visitat, apilar & Stack) { // Marca el node actual com a visitat visitat[v] = true; // Es repeteix per a tots els vèrtexs adjacents per a (int i : adj[v]) { if (!visited[i]) topologicalSortUtil(i, adj, visited, Stack); } // Empènyer el vèrtex actual a la pila que emmagatzema el resultat Stack.push(v); } // Funció per realitzar l'ordenació topològica void topologicalSort (vector>& adj, int V) { pila pila; // Apilar per emmagatzemar el vector resultat visitat(V, fals); // Crida la funció d'ajuda recursiva per emmagatzemar // Ordenació topològica començant per tots els vèrtexs un per // un per (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> vores = { { 0, 1 }, { 1, 2 }, { 3, 1 }, { 3, 2 } }; // Gràfic representat com un vector de llista d'adjacència> adj(V); per (auto i: vores) { 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, booleà[] visitat, Stack stack) { // Marca el node actual com a visitat visitat[v] = true; // Es repeteix per a tots els vèrtexs adjacents per a (int i : adj.get(v)) { if (!visited[i]) topologicalSortUtil(i, adj, visited, stack); } // Empènyer el vèrtex actual a la pila que emmagatzema el // resultat stack.push(v); } // Funció per realitzar l'ordenació topològica static void topologicalSort(Lista> adj, int V) { // Stack per emmagatzemar el resultat Stack pila = nova pila (); booleà[] visitat = booleà nou[V]; // Crida la funció d'ajuda recursiva per emmagatzemar // Ordenació topològica començant per tots els vèrtexs un // per un per (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> vores = new ArrayList(); edges.add(Matrius.asList(0, 1)); edges.add(Matrius.asList(1, 2)); edges.add(Matrius.asList(3, 1)); edges.add(Matrius.asList(3, 2)); // Gràfic representat com una llista d'adjacència> adj = new ArrayList (V); per (int i = 0; i< V; i++) { adj.add(new ArrayList()); } for (List i : vores) { adj.get(i.get(0)).add(i.get(1)); } TopologicalSort(adj, V); } }>>>Python 3
C# using System; using System.Collections.Generic; class Program { // Function to perform DFS and topological sorting static void TopologicalSortUtil(int v, List> adj, bool[] visitat, Stack stack) { // Marca el node actual com a visitat visitat[v] = true; // Es repeteix per a tots els vèrtexs adjacents foreach(int i in adj[v]) { if (!visited[i]) TopologicalSortUtil(i, adj, visited, stack); } // Empènyer el vèrtex actual a la pila que emmagatzema // la pila de resultats. Push(v); } // Funció per realitzar l'ordenació topològica static void TopologicalSort(Lista> adj, int V) { // Stack per emmagatzemar el resultat Stack pila = pila nova (); bool[] visitat = bool[V] nou; // Crida la funció d'ajuda recursiva per emmagatzemar // Ordenació topològica començant per tots els vèrtexs un // per un per (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() + ' '); } } // Codi del controlador static void Main(string[] args) { // Nombre de nodes int V = 4; // Llista de vores> vores = nova llista>{ nova llista {0, 1}, llista nova {1, 2}, llista nova { 3, 1 }, llista nova { 3, 2 } }; // Gràfic representat com a llista d'adjacència> adj = llista nova>(); per (int i = 0; i< V; i++) { adj.Add(new List ()); } foreach(Llista i a les vores) { adj[i[0]].Afegir(i[1]); } TopologicalSort(adj, V); } }>>>Javascript0) { console.log(stack.pop() + ' '); } } // Codi del controlador (() => { // Nombre de nodes const V = 4; // Vores const arestes = [[0, 1], [1, 2], [3, 1], [3, 2]]; // Gràfic representat com una llista d'adjacència const adj = Array.from({longitud: V }, () => []); (i[1]);>>>
Sortida Topological sorting of the graph: 3 0 1 2>
Complexitat temporal: O(V+E). L'algorisme anterior és simplement DFS amb una pila addicional. Per tant, la complexitat del temps és la mateixa que DFS
Espai auxiliar: O (V). Es necessita l'espai addicional per a la pila
Ordenació topològica mitjançant BFS:
C++ #include #include #include using namespace std; // Class to represent a graph class Graph { int V; // No. of vertices list * adj; // Apuntador a una matriu que conté // llistes d'adjacència públiques: Graph(int V); // Constructor void addEdge(int v, int w); // Funció per afegir una vora al gràfic void topologicalSort(); // imprimeix un tipus topològic de // el gràfic complet }; Graph::Graph(int V) { this->V = V; adj = llista nova [V]; } void Graph::addEdge(int v, int w) { adj[v].push_back(w); // Afegeix w a la llista de v. } // Funció per dur a terme l'ordenació topològica void Graph::topologicalSort() { // Crea un vector per emmagatzemar el vector en grau de tots els vèrtexs en_graus (V, 0); // Travessa llistes d'adjacència per omplir_degree de // vèrtexs per (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; per (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 ordre_superior; // Treu els vèrtexs de la cua un per un // els vèrtexs adjacents si el grau d'adjacent passa a 0 mentre que (!q.empty()) { // Extreu la part davantera de la cua (o realitza la retirada de la cua) // i afegeix-ho a ordre topològic int u = q.front(); q.pop(); top_order.push_back(u); // Iterar per tots els seus nodes veïns // del node u fora de cua i disminuir el seu grau // en 1 llista ::iterador itr; for (itr = adj[u].begin(); itr != adj[u].end(); ++itr) // Si in-degree passa a zero, afegiu-lo a la cua si (--in_degree[*itr ] == 0) q.push(*itr); comptar++; } // Comprova si hi ha hagut un cicle if (count != 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; // Llista d'adjacència // representació de // el gràfic // Constructor Graph(int V) { this.V = V; adj = nova ArrayList[V]; per (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(); per (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(); // Treu els vèrtexs de la cua un per un i // col·loqueu els vèrtexs adjacents si el grau de // adjacent es converteix en 0 mentre que (!q.isEmpty()) { // Extreu el front de la cua i afegiu-lo a // ordre topològic int u = q.poll(); topOrder.add(u); comptar++; // Itera per tots els seus nodes veïns del // node u de cua i disminueix el seu grau // en 1 per a (int w : adj[u]) { // Si el grau es converteix en zero, afegiu-lo a la // cua if (--inDegree[w] == 0) q.add(w); } } // Comprova si hi ha hagut un cicle if (compte != V) { System.out.println('El gràfic conté el cicle'); tornar; } // Imprimeix l'ordre topològic per a (int i : topOrder) System.out.print(i + ' '); } } // Codi del controlador public class Main { public static void main(String[] args) { // Creeu un gràfic donat al diagrama anterior 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('El següent és una classificació topològica del gràfic donat'); g.topologicalSort(); } }>>>Python 3
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>
Sortida
La complexitat temporal per construir el gràfic és O(V + E), on V és el nombre de vèrtexs i E és el nombre d'arestes.
La complexitat temporal per realitzar l'ordenació topològica mitjançant BFS també és O(V + E), on V és el nombre de vèrtexs i E és el nombre d'arestes. Això es deu al fet que cada vèrtex i cada aresta es visita una vegada durant el recorregut BFS.
Complexitat espacial:
b més arbre
La complexitat espacial per emmagatzemar el gràfic utilitzant una llista d'adjacència és O(V + E), on V és el nombre de vèrtexs i E és el nombre d'arestes.
S'utilitza espai addicional per emmagatzemar el grau de vèrtexs, que requereix espai O(V).
S'utilitza una cua per a la travessia BFS, que pot contenir com a màxim V vèrtexs. Així, la complexitat espacial de la cua és O(V).
En general, la complexitat espacial de l'algorisme és O (V + E) a causa de l'emmagatzematge del gràfic, la matriu en graus i la cua.
En resum, la complexitat temporal de la implementació proporcionada és O (V + E) i la complexitat espacial també és O (V + E).
Nota: Aquí, també podem utilitzar una matriu en lloc de la pila. Si s'utilitza la matriu, imprimiu els elements en ordre invers per obtenir l'ordenació topològica.
Avantatges de l'ordenació topològica:
- Ajuda en la programació de tasques o esdeveniments basats en dependències.
- Detecta cicles en un gràfic dirigit.
- Eficient per resoldre problemes amb restriccions de precedència.
Desavantatges de l'ordenació topològica:
- Només aplicable a gràfics acíclics dirigits (DAG), no aptes per a gràfics cíclics.
- Pot no ser únic, poden existir múltiples ordenacions topològiques vàlides.
- Ineficient per a gràfics grans amb molts nodes i arestes.
Aplicacions de l'ordenació topològica:
- Programació de tasques i gestió de projectes.
- Resolució de dependències en sistemes de gestió de paquets.
- Determinació de l'ordre de compilació en sistemes de creació de programari.
- Detecció de bloqueig en sistemes operatius.
- Programació de cursos a les universitats.
Articles relacionats:
- Algorisme de Kahn per a l'ordenació topològica
- Tots els tipus topològics d'un gràfic acíclic dirigit