/** * Computes a topological order by Kahn's algorithm. * * Args: * graph: Directed graph stored by adjacency list. * topoOrder: Output array. topoOrder[i] is the i-th vertex in the order. * * Returns: * true if a topological order exists. * false if the graph contains a directed cycle. */ boolTopologicalSort(const ALGraph *graph, int topoOrder[]) { int inDegree[MAX_VERTEX_NUM] = {0}; Stack zeroInDegree; int count = 0;
InitStack(&zeroInDegree);
/* Compute in-degree of every vertex by scanning all outgoing edges. */ for (int from = 0; from < graph->vexNum; ++from) { for (int edgeIndex = graph->head[from]; edgeIndex != -1; edgeIndex = graph->edges[edgeIndex].next) { int to = graph->edges[edgeIndex].to; ++inDegree[to]; } }
/* Vertices with in-degree 0 can be output immediately. */ for (int v = 0; v < graph->vexNum; ++v) { if (inDegree[v] == 0) { Push(&zeroInDegree, v); } }
while (!IsEmpty(&zeroInDegree)) { int current = Pop(&zeroInDegree); topoOrder[count++] = current;
/* Deleting current means all its outgoing constraints are removed. */ for (int edgeIndex = graph->head[current]; edgeIndex != -1; edgeIndex = graph->edges[edgeIndex].next) { int next = graph->edges[edgeIndex].to; --inDegree[next];
if (inDegree[next] == 0) { Push(&zeroInDegree, next); } } }
typedefstructEdgeNode { int to; int next; } EdgeNode;
typedefstruct { int vexNum; int edgeNum; int head[MAX_VERTEX_NUM]; EdgeNode edges[MAX_EDGE_NUM]; } ALGraph;
/** * DFS helper for reverse topological order. * * Args: * graph: Directed graph stored by adjacency list. * vertex: Current vertex. * state: Visit states for cycle detection. * reverseOrder: Output array for reverse topological order. * count: Number of vertices already written into reverseOrder. * * Returns: * true if no directed cycle is found in this DFS branch. * false if an edge points to a VISITING vertex, which means a cycle exists. */ staticboolDfsReverseTopo(const ALGraph *graph, int vertex, VisitState state[], int reverseOrder[], int *count) { state[vertex] = VISITING;
for (int edgeIndex = graph->head[vertex]; edgeIndex != -1; edgeIndex = graph->edges[edgeIndex].next) { int next = graph->edges[edgeIndex].to;
if (state[next] == VISITING) { returnfalse; }
if (state[next] == UNVISITED) { if (!DfsReverseTopo(graph, next, state, reverseOrder, count)) { returnfalse; } } }
/** * Computes reverse topological order by DFS. * * Args: * graph: Directed graph stored by adjacency list. * reverseOrder: Output array. Vertices are written in reverse topological order. * * Returns: * true if the graph is a DAG. * false if a directed cycle exists. */ boolReverseTopologicalSortByDfs(const ALGraph *graph, int reverseOrder[]) { VisitState state[MAX_VERTEX_NUM]; int count = 0;
for (int v = 0; v < graph->vexNum; ++v) { state[v] = UNVISITED; }
for (int v = 0; v < graph->vexNum; ++v) { if (state[v] == UNVISITED) { if (!DfsReverseTopo(graph, v, state, reverseOrder, &count)) { returnfalse; } } }