CS 411 Fall 2025 > Outline & Supplemental Notes for September 19, 2025
CS 411 Fall 2025
Outline & Supplemental Notes
for September 19, 2025
Outline
Topological Sort [L 4.2]
- Digraphs
- Directed graph (digraph): like a graph, but each edge oriented from one endpoint to the other. Draw a directed edge (or arc) as an arrow.
- An arc \(xy\) points from vertex \(x\) (the tail) to vertex \(y\) (the head).
- Represent a digraph in same ways as a graph:
- Adjacency matrix.
- Adjacency lists.
- Can do DFS or BFS on a digraph. Be careful: distinguish arc \(xy\) from arc \(yx\). Our DFS/BFS code works as-is for digraphs.
- Topological Sort
- Topological sort of a digraph: ordering of vertices so that every arc of digraph points from earlier to later vertex.
- Example: digraph shows course prerequisite structure. Topological sort is ordering of courses in which each course comes after prerequisites.
- A digraph with a directed cycle has no topological sort.
- Directed acyclic graph (DAG): digraph with no directed cycle.
- Fact. A digraph has a topological sort precisely if it is a DAG.
- Topological Sort Algorithm #1: Based on DFS
- Alter a recursive DFS (which we did not write code for) to output a vertex when we pop it off the stack (i.e., when it becomes a dead end).
- Result is a different vertex ordering. Reversed, this is a topological sort, if one exists.
- We can tell if a topological sort exists by checking as we go for back edges: directed edges that point from a vertex \(v\) to another vertex that is below \(v\) on the stack at the time \(v\) is being processed.
- Topological Sort Algorithm #2: Find-Source
- Source in a digraph: vertex with no arc pointing toward it.
- A topological sort algorithm using Decrease and Conquer:
- If digraph has no vertices, then end (success).
- Try to find a source.
- If there is no source, then digraph is not a DAG; end (failure).
- If there is a source \(s\), then output \(s\), remove \(s\) from digraph, and do a topological sort for what remains.
- Algorithm is stated in recursive form. We can write it iteratively and analyze it. (See Supplemental Notes.)
Supplemental Notes
Topological Sort via Find-Source
The time-consuming part of the find-source method is finding a source. An idea of A.B. Kahn [1962] is to keep track of the set of all sources and update it when we remove a vertex from the digraph. When we remove a vertex \(s\), the only possible new sources are its out-neighbors: vertices that are heads of arcs whose tail is \(s\).
An efficient way to handle updating the set of sources is to keep track of each vertex’s in-degree: the number of arcs pointing to that vertex. Having found a source \(s\), we remove it from the digraph by:
- removing \(s\) from the set of sources, and
- decrementing the in-degree of each out-neighbor of \(s\).
Whenever a vertex’s in-degree reaches zero, we add it to the set of sources.
Here is our algorithm in more detail. We are given a digraph with \(V\) vertices.
- Begin with an empty set of sources.
- For each vertex \(x\) in the digraph:
- Find the in-degree of \(x\) and store it in the in-degree array.
- If the stored in-degree of \(x\) is zero, then add \(x\) to the set of sources.
- Iterate \(V\) times.
- If the set of sources is empty, then the digraph is not a DAG, and there is no topological sort. END.
- Let \(s\) be a vertex in the set of sources.
- Remove \(s\) from the set of sources.
- Add \(s\) to the end of the topological sort.
- For each out-neighbor \(y\) of \(s\):
- Decrement the stored in-degree of \(y\).
- If the stored in-degree of \(y\) is zero, then add \(y\) to the set of sources.
If the above algorithm does not exit early, then it constructs a topological sort for the given digraph.
See
topological_sort.cpp
for an implementation of the find-source
topological sort algorithm
in iterative form.
We conclude by analyzing the above algorithm. Our input size will be written in terms of the number of vertices (\(V\)) and the number of arcs (\(E\)). Our basic operations will all single operations on vertices or arcs. We will assume that all single-item operations on the set of sources are constant-time (which is true if the set is implemented using, for example, a linked-list-based queue).
If the digraph is represented using an ajacency matrix, then we have two sets of nested loops. In each case, both loops execute at most \(V\) times. Thus, \(\Theta(V^2)\) basic operations are performed in the worst case.
If the digraph is represented using adjacency lists, then the inner loops go through all edges at most once, over all iterations of the outer loops. The outer loops both execute at most \(V\) times. Thus, \(\Theta(V + E)\) basic operations are performed in the worst case.
Note that in both cases, the order of this algorithm is the same as that of our DFS and BFS algorithms.