diff --git a/Algorithms.Tests/Graph/TopologicalSortTests.cs b/Algorithms.Tests/Graph/TopologicalSortTests.cs
new file mode 100644
index 00000000..944e3d7c
--- /dev/null
+++ b/Algorithms.Tests/Graph/TopologicalSortTests.cs
@@ -0,0 +1,573 @@
+using Algorithms.Graph;
+using DataStructures.Graph;
+
+namespace Algorithms.Tests.Graph;
+
+public class TopologicalSortTests
+{
+ ///
+ /// Test topological sort on a simple linear DAG: A → B → C.
+ /// Expected order: [A, B, C].
+ ///
+ [Test]
+ public void Sort_SimpleLinearGraph_ReturnsCorrectOrder()
+ {
+ // Arrange
+ var graph = new DirectedWeightedGraph(3);
+ var vertexA = graph.AddVertex("A");
+ var vertexB = graph.AddVertex("B");
+ var vertexC = graph.AddVertex("C");
+
+ graph.AddEdge(vertexA, vertexB, 1);
+ graph.AddEdge(vertexB, vertexC, 1);
+
+ var topologicalSort = new TopologicalSort();
+
+ // Act
+ var result = topologicalSort.Sort(graph);
+
+ // Assert
+ Assert.That(result.Count, Is.EqualTo(3));
+ Assert.That(result[0], Is.EqualTo(vertexA));
+ Assert.That(result[1], Is.EqualTo(vertexB));
+ Assert.That(result[2], Is.EqualTo(vertexC));
+ }
+
+ ///
+ /// Test Kahn's algorithm on a simple linear DAG: A → B → C.
+ /// Expected order: [A, B, C].
+ ///
+ [Test]
+ public void SortKahn_SimpleLinearGraph_ReturnsCorrectOrder()
+ {
+ // Arrange
+ var graph = new DirectedWeightedGraph(3);
+ var vertexA = graph.AddVertex("A");
+ var vertexB = graph.AddVertex("B");
+ var vertexC = graph.AddVertex("C");
+
+ graph.AddEdge(vertexA, vertexB, 1);
+ graph.AddEdge(vertexB, vertexC, 1);
+
+ var topologicalSort = new TopologicalSort();
+
+ // Act
+ var result = topologicalSort.SortKahn(graph);
+
+ // Assert
+ Assert.That(result.Count, Is.EqualTo(3));
+ Assert.That(result[0], Is.EqualTo(vertexA));
+ Assert.That(result[1], Is.EqualTo(vertexB));
+ Assert.That(result[2], Is.EqualTo(vertexC));
+ }
+
+ ///
+ /// Test topological sort on a DAG with multiple valid orderings.
+ /// Graph: A → C
+ /// B → C
+ /// Valid orderings: [A, B, C] or [B, A, C].
+ /// We verify that C comes after both A and B.
+ ///
+ [Test]
+ public void Sort_GraphWithMultipleValidOrderings_ReturnsValidOrder()
+ {
+ // Arrange
+ var graph = new DirectedWeightedGraph(3);
+ var vertexA = graph.AddVertex("A");
+ var vertexB = graph.AddVertex("B");
+ var vertexC = graph.AddVertex("C");
+
+ graph.AddEdge(vertexA, vertexC, 1);
+ graph.AddEdge(vertexB, vertexC, 1);
+
+ var topologicalSort = new TopologicalSort();
+
+ // Act
+ var result = topologicalSort.Sort(graph);
+
+ // Assert
+ Assert.That(result.Count, Is.EqualTo(3));
+
+ // C should come after both A and B
+ var indexA = result.IndexOf(vertexA);
+ var indexB = result.IndexOf(vertexB);
+ var indexC = result.IndexOf(vertexC);
+
+ Assert.That(indexC, Is.GreaterThan(indexA));
+ Assert.That(indexC, Is.GreaterThan(indexB));
+ }
+
+ ///
+ /// Test Kahn's algorithm on a DAG with multiple valid orderings.
+ /// Graph: A → C
+ /// B → C
+ /// Valid orderings: [A, B, C] or [B, A, C].
+ /// We verify that C comes after both A and B.
+ ///
+ [Test]
+ public void SortKahn_GraphWithMultipleValidOrderings_ReturnsValidOrder()
+ {
+ // Arrange
+ var graph = new DirectedWeightedGraph(3);
+ var vertexA = graph.AddVertex("A");
+ var vertexB = graph.AddVertex("B");
+ var vertexC = graph.AddVertex("C");
+
+ graph.AddEdge(vertexA, vertexC, 1);
+ graph.AddEdge(vertexB, vertexC, 1);
+
+ var topologicalSort = new TopologicalSort();
+
+ // Act
+ var result = topologicalSort.SortKahn(graph);
+
+ // Assert
+ Assert.That(result.Count, Is.EqualTo(3));
+
+ // C should come after both A and B
+ var indexA = result.IndexOf(vertexA);
+ var indexB = result.IndexOf(vertexB);
+ var indexC = result.IndexOf(vertexC);
+
+ Assert.That(indexC, Is.GreaterThan(indexA));
+ Assert.That(indexC, Is.GreaterThan(indexB));
+ }
+
+ ///
+ /// Test topological sort on a more complex DAG.
+ /// Graph: A → B → D
+ /// A → C → D
+ /// Valid orderings include: [A, B, C, D], [A, C, B, D].
+ /// We verify that A comes first and D comes last.
+ ///
+ [Test]
+ public void Sort_ComplexDAG_ReturnsValidOrder()
+ {
+ // Arrange
+ var graph = new DirectedWeightedGraph(4);
+ var vertexA = graph.AddVertex("A");
+ var vertexB = graph.AddVertex("B");
+ var vertexC = graph.AddVertex("C");
+ var vertexD = graph.AddVertex("D");
+
+ graph.AddEdge(vertexA, vertexB, 1);
+ graph.AddEdge(vertexA, vertexC, 1);
+ graph.AddEdge(vertexB, vertexD, 1);
+ graph.AddEdge(vertexC, vertexD, 1);
+
+ var topologicalSort = new TopologicalSort();
+
+ // Act
+ var result = topologicalSort.Sort(graph);
+
+ // Assert
+ Assert.That(result.Count, Is.EqualTo(4));
+ Assert.That(result[0], Is.EqualTo(vertexA)); // A must be first
+ Assert.That(result[3], Is.EqualTo(vertexD)); // D must be last
+
+ // B and C should come after A and before D
+ var indexB = result.IndexOf(vertexB);
+ var indexC = result.IndexOf(vertexC);
+
+ Assert.That(indexB, Is.GreaterThan(0));
+ Assert.That(indexB, Is.LessThan(3));
+ Assert.That(indexC, Is.GreaterThan(0));
+ Assert.That(indexC, Is.LessThan(3));
+ }
+
+ ///
+ /// Test Kahn's algorithm on a more complex DAG.
+ /// Graph: A → B → D
+ /// A → C → D
+ /// Valid orderings include: [A, B, C, D], [A, C, B, D].
+ /// We verify that A comes first and D comes last.
+ ///
+ [Test]
+ public void SortKahn_ComplexDAG_ReturnsValidOrder()
+ {
+ // Arrange
+ var graph = new DirectedWeightedGraph(4);
+ var vertexA = graph.AddVertex("A");
+ var vertexB = graph.AddVertex("B");
+ var vertexC = graph.AddVertex("C");
+ var vertexD = graph.AddVertex("D");
+
+ graph.AddEdge(vertexA, vertexB, 1);
+ graph.AddEdge(vertexA, vertexC, 1);
+ graph.AddEdge(vertexB, vertexD, 1);
+ graph.AddEdge(vertexC, vertexD, 1);
+
+ var topologicalSort = new TopologicalSort();
+
+ // Act
+ var result = topologicalSort.SortKahn(graph);
+
+ // Assert
+ Assert.That(result.Count, Is.EqualTo(4));
+ Assert.That(result[0], Is.EqualTo(vertexA)); // A must be first
+ Assert.That(result[3], Is.EqualTo(vertexD)); // D must be last
+
+ // B and C should come after A and before D
+ var indexB = result.IndexOf(vertexB);
+ var indexC = result.IndexOf(vertexC);
+
+ Assert.That(indexB, Is.GreaterThan(0));
+ Assert.That(indexB, Is.LessThan(3));
+ Assert.That(indexC, Is.GreaterThan(0));
+ Assert.That(indexC, Is.LessThan(3));
+ }
+
+ ///
+ /// Test topological sort on a graph with a cycle.
+ /// Graph: A → B → C → A (cycle).
+ /// Should throw InvalidOperationException.
+ ///
+ [Test]
+ public void Sort_GraphWithCycle_ThrowsInvalidOperationException()
+ {
+ // Arrange
+ var graph = new DirectedWeightedGraph(3);
+ var vertexA = graph.AddVertex("A");
+ var vertexB = graph.AddVertex("B");
+ var vertexC = graph.AddVertex("C");
+
+ graph.AddEdge(vertexA, vertexB, 1);
+ graph.AddEdge(vertexB, vertexC, 1);
+ graph.AddEdge(vertexC, vertexA, 1); // Creates a cycle
+
+ var topologicalSort = new TopologicalSort();
+
+ // Act & Assert
+ Assert.Throws(() => topologicalSort.Sort(graph));
+ }
+
+ ///
+ /// Test Kahn's algorithm on a graph with a cycle.
+ /// Graph: A → B → C → A (cycle).
+ /// Should throw InvalidOperationException.
+ ///
+ [Test]
+ public void SortKahn_GraphWithCycle_ThrowsInvalidOperationException()
+ {
+ // Arrange
+ var graph = new DirectedWeightedGraph(3);
+ var vertexA = graph.AddVertex("A");
+ var vertexB = graph.AddVertex("B");
+ var vertexC = graph.AddVertex("C");
+
+ graph.AddEdge(vertexA, vertexB, 1);
+ graph.AddEdge(vertexB, vertexC, 1);
+ graph.AddEdge(vertexC, vertexA, 1); // Creates a cycle
+
+ var topologicalSort = new TopologicalSort();
+
+ // Act & Assert
+ Assert.Throws(() => topologicalSort.SortKahn(graph));
+ }
+
+ ///
+ /// Test topological sort on a single vertex graph.
+ /// Graph: A (no edges).
+ /// Expected order: [A].
+ ///
+ [Test]
+ public void Sort_SingleVertexGraph_ReturnsSingleVertex()
+ {
+ // Arrange
+ var graph = new DirectedWeightedGraph(1);
+ var vertexA = graph.AddVertex("A");
+
+ var topologicalSort = new TopologicalSort();
+
+ // Act
+ var result = topologicalSort.Sort(graph);
+
+ // Assert
+ Assert.That(result.Count, Is.EqualTo(1));
+ Assert.That(result[0], Is.EqualTo(vertexA));
+ }
+
+ ///
+ /// Test Kahn's algorithm on a single vertex graph.
+ /// Graph: A (no edges).
+ /// Expected order: [A].
+ ///
+ [Test]
+ public void SortKahn_SingleVertexGraph_ReturnsSingleVertex()
+ {
+ // Arrange
+ var graph = new DirectedWeightedGraph(1);
+ var vertexA = graph.AddVertex("A");
+
+ var topologicalSort = new TopologicalSort();
+
+ // Act
+ var result = topologicalSort.SortKahn(graph);
+
+ // Assert
+ Assert.That(result.Count, Is.EqualTo(1));
+ Assert.That(result[0], Is.EqualTo(vertexA));
+ }
+
+ ///
+ /// Test topological sort on a disconnected DAG.
+ /// Graph: A → B (component 1)
+ /// C → D (component 2)
+ /// Valid orderings: [A, B, C, D], [A, C, B, D], [C, A, B, D], [C, D, A, B], etc.
+ /// We verify that A comes before B and C comes before D.
+ ///
+ [Test]
+ public void Sort_DisconnectedDAG_ReturnsValidOrder()
+ {
+ // Arrange
+ var graph = new DirectedWeightedGraph(4);
+ var vertexA = graph.AddVertex("A");
+ var vertexB = graph.AddVertex("B");
+ var vertexC = graph.AddVertex("C");
+ var vertexD = graph.AddVertex("D");
+
+ graph.AddEdge(vertexA, vertexB, 1);
+ graph.AddEdge(vertexC, vertexD, 1);
+
+ var topologicalSort = new TopologicalSort();
+
+ // Act
+ var result = topologicalSort.Sort(graph);
+
+ // Assert
+ Assert.That(result.Count, Is.EqualTo(4));
+
+ // A should come before B
+ var indexA = result.IndexOf(vertexA);
+ var indexB = result.IndexOf(vertexB);
+ Assert.That(indexB, Is.GreaterThan(indexA));
+
+ // C should come before D
+ var indexC = result.IndexOf(vertexC);
+ var indexD = result.IndexOf(vertexD);
+ Assert.That(indexD, Is.GreaterThan(indexC));
+ }
+
+ ///
+ /// Test Kahn's algorithm on a disconnected DAG.
+ /// Graph: A → B (component 1)
+ /// C → D (component 2)
+ /// Valid orderings: [A, B, C, D], [A, C, B, D], [C, A, B, D], [C, D, A, B], etc.
+ /// We verify that A comes before B and C comes before D.
+ ///
+ [Test]
+ public void SortKahn_DisconnectedDAG_ReturnsValidOrder()
+ {
+ // Arrange
+ var graph = new DirectedWeightedGraph(4);
+ var vertexA = graph.AddVertex("A");
+ var vertexB = graph.AddVertex("B");
+ var vertexC = graph.AddVertex("C");
+ var vertexD = graph.AddVertex("D");
+
+ graph.AddEdge(vertexA, vertexB, 1);
+ graph.AddEdge(vertexC, vertexD, 1);
+
+ var topologicalSort = new TopologicalSort();
+
+ // Act
+ var result = topologicalSort.SortKahn(graph);
+
+ // Assert
+ Assert.That(result.Count, Is.EqualTo(4));
+
+ // A should come before B
+ var indexA = result.IndexOf(vertexA);
+ var indexB = result.IndexOf(vertexB);
+ Assert.That(indexB, Is.GreaterThan(indexA));
+
+ // C should come before D
+ var indexC = result.IndexOf(vertexC);
+ var indexD = result.IndexOf(vertexD);
+ Assert.That(indexD, Is.GreaterThan(indexC));
+ }
+
+ ///
+ /// Test topological sort on a real-world scenario: course prerequisites.
+ /// Graph represents course dependencies:
+ /// - Intro to CS (A) is a prerequisite for Data Structures (B) and Algorithms (C).
+ /// - Data Structures (B) is a prerequisite for Advanced Algorithms (D).
+ /// - Algorithms (C) is a prerequisite for Advanced Algorithms (D).
+ /// Expected: A must come first, D must come last.
+ ///
+ [Test]
+ public void Sort_CoursePrerequisitesScenario_ReturnsValidOrder()
+ {
+ // Arrange
+ var graph = new DirectedWeightedGraph(4);
+ var introCS = graph.AddVertex("Intro to CS");
+ var dataStructures = graph.AddVertex("Data Structures");
+ var algorithms = graph.AddVertex("Algorithms");
+ var advancedAlgorithms = graph.AddVertex("Advanced Algorithms");
+
+ graph.AddEdge(introCS, dataStructures, 1);
+ graph.AddEdge(introCS, algorithms, 1);
+ graph.AddEdge(dataStructures, advancedAlgorithms, 1);
+ graph.AddEdge(algorithms, advancedAlgorithms, 1);
+
+ var topologicalSort = new TopologicalSort();
+
+ // Act
+ var result = topologicalSort.Sort(graph);
+
+ // Assert
+ Assert.That(result.Count, Is.EqualTo(4));
+ Assert.That(result[0], Is.EqualTo(introCS)); // Must take Intro to CS first
+ Assert.That(result[3], Is.EqualTo(advancedAlgorithms)); // Advanced Algorithms must be last
+
+ // Data Structures and Algorithms should be in the middle
+ var indexDS = result.IndexOf(dataStructures);
+ var indexAlgo = result.IndexOf(algorithms);
+
+ Assert.That(indexDS, Is.GreaterThan(0));
+ Assert.That(indexDS, Is.LessThan(3));
+ Assert.That(indexAlgo, Is.GreaterThan(0));
+ Assert.That(indexAlgo, Is.LessThan(3));
+ }
+
+ ///
+ /// Test Kahn's algorithm on a real-world scenario: course prerequisites.
+ /// Graph represents course dependencies:
+ /// - Intro to CS (A) is a prerequisite for Data Structures (B) and Algorithms (C).
+ /// - Data Structures (B) is a prerequisite for Advanced Algorithms (D).
+ /// - Algorithms (C) is a prerequisite for Advanced Algorithms (D).
+ /// Expected: A must come first, D must come last.
+ ///
+ [Test]
+ public void SortKahn_CoursePrerequisitesScenario_ReturnsValidOrder()
+ {
+ // Arrange
+ var graph = new DirectedWeightedGraph(4);
+ var introCS = graph.AddVertex("Intro to CS");
+ var dataStructures = graph.AddVertex("Data Structures");
+ var algorithms = graph.AddVertex("Algorithms");
+ var advancedAlgorithms = graph.AddVertex("Advanced Algorithms");
+
+ graph.AddEdge(introCS, dataStructures, 1);
+ graph.AddEdge(introCS, algorithms, 1);
+ graph.AddEdge(dataStructures, advancedAlgorithms, 1);
+ graph.AddEdge(algorithms, advancedAlgorithms, 1);
+
+ var topologicalSort = new TopologicalSort();
+
+ // Act
+ var result = topologicalSort.SortKahn(graph);
+
+ // Assert
+ Assert.That(result.Count, Is.EqualTo(4));
+ Assert.That(result[0], Is.EqualTo(introCS)); // Must take Intro to CS first
+ Assert.That(result[3], Is.EqualTo(advancedAlgorithms)); // Advanced Algorithms must be last
+
+ // Data Structures and Algorithms should be in the middle
+ var indexDS = result.IndexOf(dataStructures);
+ var indexAlgo = result.IndexOf(algorithms);
+
+ Assert.That(indexDS, Is.GreaterThan(0));
+ Assert.That(indexDS, Is.LessThan(3));
+ Assert.That(indexAlgo, Is.GreaterThan(0));
+ Assert.That(indexAlgo, Is.LessThan(3));
+ }
+
+ ///
+ /// Test topological sort with integer vertices.
+ /// Graph: 1 → 2 → 3.
+ /// Expected order: [1, 2, 3].
+ ///
+ [Test]
+ public void Sort_IntegerVertices_ReturnsCorrectOrder()
+ {
+ // Arrange
+ var graph = new DirectedWeightedGraph(3);
+ var vertex1 = graph.AddVertex(1);
+ var vertex2 = graph.AddVertex(2);
+ var vertex3 = graph.AddVertex(3);
+
+ graph.AddEdge(vertex1, vertex2, 1);
+ graph.AddEdge(vertex2, vertex3, 1);
+
+ var topologicalSort = new TopologicalSort();
+
+ // Act
+ var result = topologicalSort.Sort(graph);
+
+ // Assert
+ Assert.That(result.Count, Is.EqualTo(3));
+ Assert.That(result[0], Is.EqualTo(vertex1));
+ Assert.That(result[1], Is.EqualTo(vertex2));
+ Assert.That(result[2], Is.EqualTo(vertex3));
+ }
+
+ ///
+ /// Test Kahn's algorithm with integer vertices.
+ /// Graph: 1 → 2 → 3.
+ /// Expected order: [1, 2, 3].
+ ///
+ [Test]
+ public void SortKahn_IntegerVertices_ReturnsCorrectOrder()
+ {
+ // Arrange
+ var graph = new DirectedWeightedGraph(3);
+ var vertex1 = graph.AddVertex(1);
+ var vertex2 = graph.AddVertex(2);
+ var vertex3 = graph.AddVertex(3);
+
+ graph.AddEdge(vertex1, vertex2, 1);
+ graph.AddEdge(vertex2, vertex3, 1);
+
+ var topologicalSort = new TopologicalSort();
+
+ // Act
+ var result = topologicalSort.SortKahn(graph);
+
+ // Assert
+ Assert.That(result.Count, Is.EqualTo(3));
+ Assert.That(result[0], Is.EqualTo(vertex1));
+ Assert.That(result[1], Is.EqualTo(vertex2));
+ Assert.That(result[2], Is.EqualTo(vertex3));
+ }
+
+ ///
+ /// Test topological sort on a graph with self-loop (cycle).
+ /// Graph: A → A (self-loop).
+ /// Should throw InvalidOperationException.
+ ///
+ [Test]
+ public void Sort_GraphWithSelfLoop_ThrowsInvalidOperationException()
+ {
+ // Arrange
+ var graph = new DirectedWeightedGraph(1);
+ var vertexA = graph.AddVertex("A");
+
+ graph.AddEdge(vertexA, vertexA, 1); // Self-loop
+
+ var topologicalSort = new TopologicalSort();
+
+ // Act & Assert
+ Assert.Throws(() => topologicalSort.Sort(graph));
+ }
+
+ ///
+ /// Test Kahn's algorithm on a graph with self-loop (cycle).
+ /// Graph: A → A (self-loop).
+ /// Should throw InvalidOperationException.
+ ///
+ [Test]
+ public void SortKahn_GraphWithSelfLoop_ThrowsInvalidOperationException()
+ {
+ // Arrange
+ var graph = new DirectedWeightedGraph(1);
+ var vertexA = graph.AddVertex("A");
+
+ graph.AddEdge(vertexA, vertexA, 1); // Self-loop
+
+ var topologicalSort = new TopologicalSort();
+
+ // Act & Assert
+ Assert.Throws(() => topologicalSort.SortKahn(graph));
+ }
+}
diff --git a/Algorithms/Graph/TopologicalSort.cs b/Algorithms/Graph/TopologicalSort.cs
new file mode 100644
index 00000000..ac542ce6
--- /dev/null
+++ b/Algorithms/Graph/TopologicalSort.cs
@@ -0,0 +1,363 @@
+using DataStructures.Graph;
+
+namespace Algorithms.Graph;
+
+///
+/// Topological Sort is a linear ordering of vertices in a Directed Acyclic Graph (DAG)
+/// such that for every directed edge (u, v), vertex u comes before vertex v in the ordering.
+///
+/// KEY CONCEPTS:
+/// 1. Only applicable to Directed Acyclic Graphs (DAGs) - graphs with no cycles.
+/// 2. A DAG can have multiple valid topological orderings.
+/// 3. Used in dependency resolution, task scheduling, build systems, and course prerequisites.
+///
+/// ALGORITHM APPROACHES:
+/// 1. DFS-based (Depth-First Search): Uses post-order traversal and reverses the result.
+/// 2. Kahn's Algorithm: Uses in-degree counting and processes vertices with zero in-degree.
+///
+/// TIME COMPLEXITY: O(V + E) where V is vertices and E is edges.
+/// SPACE COMPLEXITY: O(V) for the visited set and result stack.
+///
+/// Reference: "Introduction to Algorithms" (CLRS) by Cormen, Leiserson, Rivest, and Stein.
+/// Also covered in "Algorithm Design Manual" by Steven Skiena.
+///
+/// Vertex data type.
+public class TopologicalSort where T : IComparable
+{
+ ///
+ /// Performs topological sort on a directed acyclic graph using DFS-based approach.
+ ///
+ /// ALGORITHM STEPS (DFS-based approach):
+ /// 1. Initialize a visited set to track processed vertices.
+ /// 2. Initialize a stack to store the topological ordering.
+ /// 3. For each unvisited vertex in the graph:
+ /// a) Perform DFS from that vertex.
+ /// b) After visiting all descendants, push the vertex to the stack.
+ /// 4. The stack now contains vertices in reverse topological order.
+ /// 5. Pop all vertices from the stack to get the topological ordering.
+ ///
+ /// WHY IT WORKS:
+ /// - In DFS, we push a vertex to the stack only after visiting all its descendants.
+ /// - This ensures that all vertices that depend on the current vertex are processed first.
+ /// - Reversing this order gives us the topological sort.
+ ///
+ /// EXAMPLE:
+ /// Graph: A → B → C
+ /// A → D
+ /// D → C
+ /// Valid topological orderings: [A, B, D, C] or [A, D, B, C].
+ ///
+ /// USE CASES:
+ /// - Build systems (compile dependencies).
+ /// - Task scheduling with dependencies.
+ /// - Course prerequisite ordering.
+ /// - Package dependency resolution.
+ ///
+ /// The directed acyclic graph to sort.
+ /// A list of vertices in topological order.
+ ///
+ /// Thrown when the graph contains a cycle (not a DAG).
+ ///
+ public List> Sort(IDirectedWeightedGraph graph)
+ {
+ // Stack to store vertices in reverse topological order.
+ // We use a stack because DFS naturally gives us reverse topological order.
+ var stack = new Stack>();
+
+ // Track visited vertices to avoid reprocessing and detect cycles.
+ var visited = new HashSet>();
+
+ // Track vertices currently in the recursion stack to detect cycles.
+ // If we encounter a vertex that's in the recursion stack, we have a cycle.
+ var recursionStack = new HashSet>();
+
+ // Process all vertices in the graph.
+ // We need to iterate through all vertices because the graph might be disconnected.
+ for (int i = 0; i < graph.Count; i++)
+ {
+ var vertex = graph.Vertices[i];
+
+ // Skip null vertices (shouldn't happen in a well-formed graph).
+ if (vertex == null)
+ {
+ continue;
+ }
+
+ // If vertex hasn't been visited, perform DFS from it.
+ if (!visited.Contains(vertex))
+ {
+ DfsTopologicalSort(graph, vertex, visited, recursionStack, stack);
+ }
+ }
+
+ // Convert stack to list. The stack contains vertices in reverse topological order,
+ // so we need to reverse it to get the correct topological ordering.
+ var result = new List>(stack.Count);
+ while (stack.Count > 0)
+ {
+ result.Add(stack.Pop());
+ }
+
+ return result;
+ }
+
+ ///
+ /// Performs topological sort using Kahn's Algorithm (BFS-based approach).
+ ///
+ /// ALGORITHM STEPS (Kahn's Algorithm):
+ /// 1. Calculate in-degree (number of incoming edges) for each vertex.
+ /// 2. Add all vertices with in-degree 0 to a queue.
+ /// 3. While the queue is not empty:
+ /// a) Remove a vertex from the queue and add it to the result.
+ /// b) For each neighbor of this vertex:
+ /// - Decrease its in-degree by 1.
+ /// - If in-degree becomes 0, add it to the queue.
+ /// 4. If all vertices are processed, return the result.
+ /// 5. If not all vertices are processed, the graph has a cycle.
+ ///
+ /// WHY IT WORKS:
+ /// - Vertices with in-degree 0 have no dependencies and can be processed first.
+ /// - After processing a vertex, we "remove" its outgoing edges by decreasing
+ /// the in-degree of its neighbors.
+ /// - This gradually reveals more vertices with in-degree 0.
+ ///
+ /// ADVANTAGES OVER DFS:
+ /// - More intuitive for understanding dependencies.
+ /// - Easier to detect cycles (if not all vertices are processed).
+ /// - Better for parallel processing scenarios.
+ ///
+ /// The directed acyclic graph to sort.
+ /// A list of vertices in topological order.
+ ///
+ /// Thrown when the graph contains a cycle (not a DAG).
+ ///
+ public List> SortKahn(IDirectedWeightedGraph graph)
+ {
+ // Calculate in-degree for each vertex.
+ var inDegree = CalculateInDegrees(graph);
+
+ // Queue to process vertices with in-degree 0.
+ var queue = InitializeQueueWithZeroInDegreeVertices(inDegree);
+
+ // Process vertices in topological order.
+ var result = ProcessVerticesInTopologicalOrder(graph, inDegree, queue);
+
+ // Verify all vertices were processed (no cycles).
+ ValidateNoCycles(graph, result);
+
+ return result;
+ }
+
+ ///
+ /// Calculates the in-degree for each vertex in the graph.
+ /// In-degree is the number of incoming edges to a vertex.
+ ///
+ /// The graph to analyze.
+ /// Dictionary mapping each vertex to its in-degree.
+ private Dictionary, int> CalculateInDegrees(IDirectedWeightedGraph graph)
+ {
+ var inDegree = new Dictionary, int>();
+
+ // Initialize in-degree for all vertices to 0.
+ for (int i = 0; i < graph.Count; i++)
+ {
+ var vertex = graph.Vertices[i];
+ if (vertex != null)
+ {
+ inDegree[vertex] = 0;
+ }
+ }
+
+ // Calculate actual in-degrees by examining all edges.
+ for (int i = 0; i < graph.Count; i++)
+ {
+ var vertex = graph.Vertices[i];
+ if (vertex != null)
+ {
+ IncrementNeighborInDegrees(graph, vertex, inDegree);
+ }
+ }
+
+ return inDegree;
+ }
+
+ ///
+ /// Increments the in-degree for all neighbors of a given vertex.
+ ///
+ /// The graph containing the vertices.
+ /// The vertex whose neighbors' in-degrees should be incremented.
+ /// Dictionary tracking in-degrees.
+ private void IncrementNeighborInDegrees(
+ IDirectedWeightedGraph graph,
+ Vertex vertex,
+ Dictionary, int> inDegree)
+ {
+ foreach (var neighbor in graph.GetNeighbors(vertex))
+ {
+ if (neighbor != null)
+ {
+ inDegree[neighbor]++;
+ }
+ }
+ }
+
+ ///
+ /// Initializes a queue with all vertices that have in-degree 0.
+ /// These vertices have no dependencies and can be processed first.
+ ///
+ /// Dictionary mapping vertices to their in-degrees.
+ /// Queue containing all vertices with in-degree 0.
+ private Queue> InitializeQueueWithZeroInDegreeVertices(Dictionary, int> inDegree)
+ {
+ var queue = new Queue>();
+
+ foreach (var kvp in inDegree)
+ {
+ if (kvp.Value == 0)
+ {
+ queue.Enqueue(kvp.Key);
+ }
+ }
+
+ return queue;
+ }
+
+ ///
+ /// Processes vertices in topological order using Kahn's algorithm.
+ /// Dequeues vertices with in-degree 0 and decreases in-degrees of their neighbors.
+ ///
+ /// The graph being sorted.
+ /// Dictionary tracking in-degrees.
+ /// Queue of vertices with in-degree 0.
+ /// List of vertices in topological order.
+ private List> ProcessVerticesInTopologicalOrder(
+ IDirectedWeightedGraph graph,
+ Dictionary, int> inDegree,
+ Queue> queue)
+ {
+ var result = new List>();
+
+ while (queue.Count > 0)
+ {
+ var vertex = queue.Dequeue();
+ result.Add(vertex);
+
+ ProcessNeighbors(graph, vertex, inDegree, queue);
+ }
+
+ return result;
+ }
+
+ ///
+ /// Processes neighbors of a vertex by decreasing their in-degrees.
+ /// If a neighbor's in-degree becomes 0, it's added to the queue.
+ ///
+ /// The graph being sorted.
+ /// The vertex whose neighbors are being processed.
+ /// Dictionary tracking in-degrees.
+ /// Queue of vertices with in-degree 0.
+ private void ProcessNeighbors(
+ IDirectedWeightedGraph graph,
+ Vertex vertex,
+ Dictionary, int> inDegree,
+ Queue> queue)
+ {
+ foreach (var neighbor in graph.GetNeighbors(vertex))
+ {
+ if (neighbor != null)
+ {
+ inDegree[neighbor]--;
+
+ if (inDegree[neighbor] == 0)
+ {
+ queue.Enqueue(neighbor);
+ }
+ }
+ }
+ }
+
+ ///
+ /// Validates that all vertices were processed, ensuring no cycles exist.
+ ///
+ /// The graph being sorted.
+ /// The list of processed vertices.
+ ///
+ /// Thrown when not all vertices were processed (cycle detected).
+ ///
+ private void ValidateNoCycles(IDirectedWeightedGraph graph, List> result)
+ {
+ if (result.Count != graph.Count)
+ {
+ throw new InvalidOperationException(
+ "Graph contains a cycle. Topological sort is only possible for Directed Acyclic Graphs (DAGs).");
+ }
+ }
+
+ ///
+ /// Helper method for DFS-based topological sort.
+ /// Recursively visits vertices and adds them to the stack in post-order.
+ ///
+ /// POST-ORDER TRAVERSAL:
+ /// - Visit all descendants first.
+ /// - Then process the current vertex.
+ /// - This ensures dependencies are processed before dependents.
+ ///
+ /// CYCLE DETECTION:
+ /// - We maintain a recursion stack to track the current DFS path.
+ /// - If we encounter a vertex that's already in the recursion stack,
+ /// we've found a back edge, indicating a cycle.
+ ///
+ /// The graph being sorted.
+ /// The current vertex being processed.
+ /// Set of all visited vertices.
+ /// Set of vertices in the current DFS path.
+ /// Stack to store vertices in reverse topological order.
+ ///
+ /// Thrown when a cycle is detected.
+ ///
+ private void DfsTopologicalSort(
+ IDirectedWeightedGraph graph,
+ Vertex vertex,
+ HashSet> visited,
+ HashSet> recursionStack,
+ Stack> stack)
+ {
+ // CYCLE DETECTION:
+ // If the vertex is in the recursion stack, we've encountered it again
+ // in the current DFS path, which means there's a cycle.
+ if (recursionStack.Contains(vertex))
+ {
+ throw new InvalidOperationException(
+ $"Graph contains a cycle involving vertex: {vertex}. " +
+ "Topological sort is only possible for Directed Acyclic Graphs (DAGs).");
+ }
+
+ // If already visited, no need to process again.
+ if (visited.Contains(vertex))
+ {
+ return;
+ }
+
+ // Mark vertex as visited and add to recursion stack.
+ visited.Add(vertex);
+ recursionStack.Add(vertex);
+
+ // Recursively visit all neighbors (descendants).
+ // This ensures all dependencies are processed first.
+ foreach (var neighbor in graph.GetNeighbors(vertex))
+ {
+ if (neighbor != null)
+ {
+ DfsTopologicalSort(graph, neighbor, visited, recursionStack, stack);
+ }
+ }
+
+ // Remove from recursion stack as we're done with this DFS path.
+ recursionStack.Remove(vertex);
+
+ // POST-ORDER: Add vertex to stack after visiting all descendants.
+ // This ensures that all vertices that depend on the current vertex
+ // are already in the stack (deeper in the stack).
+ stack.Push(vertex);
+ }
+}
diff --git a/README.md b/README.md
index 93ea4e25..26fe0749 100644
--- a/README.md
+++ b/README.md
@@ -52,6 +52,7 @@ find more than one implementation for the same objective but using different alg
* [Dijkstra Shortest Path](./Algorithms/Graph/Dijkstra/DijkstraAlgorithm.cs)
* [FloydWarshall](./Algorithms/Graph/FloydWarshall.cs)
* [Kosaraju](./Algorithms/Graph/Kosaraju.cs)
+ * [Topological Sort](./Algorithms/Graph/TopologicalSort.cs)
* [Knapsack problem](./Algorithms/Knapsack)
* [Naive solver](./Algorithms/Knapsack/NaiveKnapsackSolver.cs)
* [Dynamic Programming solver](./Algorithms/Knapsack/DynamicProgrammingKnapsackSolver.cs)