Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve comments, add doctests for kahns_algorithm_topo.py #11668

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 46 additions & 21 deletions graphs/kahns_algorithm_topo.py
Original file line number Diff line number Diff line change
@@ -1,36 +1,61 @@
def topological_sort(graph):
def topological_sort(graph: dict[int, list[int]]) -> list[int] | None:
"""
Kahn's Algorithm is used to find Topological ordering of Directed Acyclic Graph
using BFS
Perform topological sorting of a Directed Acyclic Graph (DAG)
using Kahn's Algorithm via Breadth-First Search (BFS).

Topological sorting is a linear ordering of vertices in a graph such that for
every directed edge u → v, vertex u comes before vertex v in the ordering.

Parameters:
graph: Adjacency list representing the directed graph where keys are
vertices, and values are lists of adjacent vertices.

Returns:
The topologically sorted order of vertices if the graph is a DAG.
Returns None if the graph contains a cycle.

Example:
>>> graph = {0: [1, 2], 1: [3], 2: [3], 3: [4, 5], 4: [], 5: []}
>>> topological_sort(graph)
[0, 1, 2, 3, 4, 5]

>>> graph_with_cycle = {0: [1], 1: [2], 2: [0]}
>>> topological_sort(graph_with_cycle)
"""

indegree = [0] * len(graph)
queue = []
topo = []
cnt = 0
topo_order = []
processed_vertices_count = 0

# Calculate the indegree of each vertex
for values in graph.values():
for i in values:
indegree[i] += 1

# Add all vertices with 0 indegree to the queue
for i in range(len(indegree)):
if indegree[i] == 0:
queue.append(i)

# Perform BFS
while queue:
vertex = queue.pop(0)
cnt += 1
topo.append(vertex)
for x in graph[vertex]:
indegree[x] -= 1
if indegree[x] == 0:
queue.append(x)

if cnt != len(graph):
print("Cycle exists")
else:
print(topo)


# Adjacency List of Graph
graph = {0: [1, 2], 1: [3], 2: [3], 3: [4, 5], 4: [], 5: []}
topological_sort(graph)
processed_vertices_count += 1
topo_order.append(vertex)

# Traverse neighbors
for neighbor in graph[vertex]:
indegree[neighbor] -= 1
if indegree[neighbor] == 0:
queue.append(neighbor)

if processed_vertices_count != len(graph):
return None # no topological ordering exists due to cycle
return topo_order # valid topological ordering


if __name__ == "__main__":
import doctest

doctest.testmod()