Resolve and order task dependencies using post-order DFS (dependencies come before the task). Β β± Time
O(V+E)Β πΎ SpaceO(V)
Model tasks as a graph where each task lists its dependencies. Run DFS: recursively resolve all dependencies before adding the current task to the output. Post-order traversal naturally produces a dependency-first order.
Algorithm:
def dfs(task):
name, deps = task
for dep in deps:
dfs(dep) β resolve dependencies first
if name not in output:
output.append(name) β then add this task
Result: tasks in dependency-first order (topological order)
Task dependencies:
A (no deps)
B depends on A
C depends on A, B
D depends on A, B, C
DFS(C):
β DFS(A): A has no deps β output: [A]
β DFS(B):
β DFS(A): already in output β skip
β output: [A, B]
β output: [A, B, C]
DFS(D) β [A, B, C, D] β
This pattern is essentially topological sort via DFS, the algorithm underlying every build system and package manager. make (1976), npm, pip, gradle, and cargo all use variants of this to determine the correct build/install order.
- This is topological sort with memoisation β the
if name not in outputguard prevents duplicate processing - Post-order DFS = "finish all dependencies before yourself"
- For circular dependencies (cycles), this will infinite-loop β add cycle detection with a "in-progress" set
- The duplicate guard means each task is added at most once, even if depended on by many tasks
- Recognise this pattern when you see: "build X before Y", "install A before B"
- Build systems (Makefile, CMake, Gradle, Bazel)
- Package managers (npm install, pip install, cargo build)
- CI/CD pipeline stage ordering
- Database migration ordering
- Module loading order in bundlers (webpack, rollup)
- Topological Sort β canonical topological sort algorithm
- Detect Cycle β circular dependency detection
- DFS β the underlying traversal