📖 Scenario: You are managing tasks in a project where some tasks must be done before others. You want to find an order to do all tasks without breaking any rules.
🎯 Goal: Build a program that uses Kahn's Algorithm with BFS to find a valid order of tasks based on their dependencies.
📋 What You'll Learn
Create a graph using adjacency list representation with exact edges
Create an array to track the number of incoming edges (indegree) for each node
Implement Kahn's Algorithm using a queue to find the topological order
Print the final topological order of tasks
💡 Why This Matters
🌍 Real World
Topological sorting is used in project management, build systems, and scheduling where tasks have dependencies.
💼 Career
Understanding topological sort and graph algorithms is important for software engineers working on compilers, task schedulers, and dependency resolution.
Progress0 / 4 steps
1
Create the graph adjacency list
Create a variable called graph as a map[int][]int with these exact edges: 0 -> 1, 0 -> 2, 1 -> 3, 2 -> 3
DSA Go
Hint
Use a map where keys are task numbers and values are slices of tasks that depend on the key task.
2
Create the indegree array
Create a slice called indegree of length 4 with all values set to 0, then update it to count incoming edges for each node based on graph
DSA Go
Hint
Count how many tasks point to each task to find their indegree.
3
Implement Kahn's Algorithm BFS
Create a queue slice called queue and add all nodes with indegree 0. Then use a for loop to process the queue, updating indegrees and appending nodes to topoOrder slice.
DSA Go
Hint
Start with tasks that have no dependencies, then remove their edges and add new tasks with no dependencies to the queue.
4
Print the topological order
Print the topoOrder slice to show the order of tasks after applying Kahn's Algorithm.
DSA Go
Hint
The printed slice shows one valid order to complete all tasks.
Practice
(1/5)
1. What is the main purpose of Kahn's Algorithm in graph theory?
easy
A. To calculate the minimum spanning tree
B. To detect cycles in an undirected graph
C. To find the shortest path between two nodes
D. To find a topological ordering of a Directed Acyclic Graph (DAG)
Solution
Step 1: Understand Kahn's Algorithm goal
Kahn's Algorithm is designed to produce a linear ordering of vertices in a Directed Acyclic Graph (DAG) such that for every directed edge u -> v, u comes before v in the ordering.
Step 2: Compare with other graph algorithms
Other options like cycle detection, shortest path, or minimum spanning tree solve different problems unrelated to topological sorting.
Final Answer:
To find a topological ordering of a Directed Acyclic Graph (DAG) -> Option D
Quick Check:
Topological sort = Kahn's Algorithm purpose [OK]
Hint: Kahn's Algorithm always orders DAG nodes topologically [OK]
Common Mistakes:
Confusing topological sort with cycle detection
Thinking it works on undirected graphs
Assuming it finds shortest paths
2. Which Go data structure is best suited to implement the queue in Kahn's Algorithm?
easy
A. Linked list from container/list package
B. Map with keys as indices
C. Slice with append and slicing for enqueue and dequeue
D. Array with fixed size and no dynamic resizing
Solution
Step 1: Identify queue operations needed
Kahn's Algorithm requires efficient enqueue (push back) and dequeue (pop front) operations for nodes with zero indegree.
Step 2: Evaluate Go data structures
Slices can be used but dequeue from front is costly (O(n)). Maps don't maintain order. The container/list package provides a doubly linked list with O(1) enqueue and dequeue, ideal for queue.
Final Answer:
Linked list from container/list package -> Option A
Quick Check:
Efficient queue = container/list linked list [OK]
Hint: Use container/list for efficient queue in Go [OK]
Common Mistakes:
Using slice and removing front element inefficiently
Using map which is unordered
Using fixed-size array without resizing
3. What is the output of the following Go code snippet implementing Kahn's Algorithm on the graph with edges: 5->0, 5->2, 4->0, 4->1, 2->3, 3->1?
package main
import (
"container/list"
"fmt"
)
func kahnTopoSort(vertices int, edges [][2]int) []int {
indegree := make([]int, vertices)
graph := make([][]int, vertices)
for _, e := range edges {
graph[e[0]] = append(graph[e[0]], e[1])
indegree[e[1]]++
}
queue := list.New()
for i := 0; i < vertices; i++ {
if indegree[i] == 0 {
queue.PushBack(i)
}
}
var result []int
for queue.Len() > 0 {
front := queue.Remove(queue.Front()).(int)
result = append(result, front)
for _, nbr := range graph[front] {
indegree[nbr]--
if indegree[nbr] == 0 {
queue.PushBack(nbr)
}
}
}
return result
}
func main() {
edges := [][2]int{{5,0},{5,2},{4,0},{4,1},{2,3},{3,1}}
order := kahnTopoSort(6, edges)
fmt.Println(order)
}
medium
A. [4 5 0 2 3 1]
B. [5 4 0 2 3 1]
C. [4 5 2 0 3 1]
D. [5 4 2 3 0 1]
Solution
Step 1: Calculate indegrees and initial queue
Vertices: 0-5. Indegrees: 0->2 (from 4,5), 1->2 (from 3,4), 2->1 (from 5), 3->1 (from 2), 4->0, 5->0. Initial queue: nodes with indegree 0 are 4 and 5.
Step 2: Process queue in FIFO order
Queue: [4,5]. Remove 4: result=[4], decrease indegree of 0 and 1. Indegree 0=1, 1=1. Remove 5: result=[4,5], decrease indegree of 0 and 2. Indegree 0=0 (enqueue 0), 2=0 (enqueue 2). Queue: [0,2]. Remove 0: result=[4,5,0], no neighbors. Remove 2: result=[4,5,0,2], decrease indegree of 3 to 0 (enqueue 3). Queue: [3]. Remove 3: result=[4,5,0,2,3], decrease indegree of 1 to 0 (enqueue 1). Queue: [1]. Remove 1: result=[4,5,0,2,3,1].
Final Answer:
[4 5 0 2 3 1] -> Option A
Quick Check:
Topological order = [4 5 0 2 3 1] [OK]
Hint: Track indegrees and enqueue zero indegree nodes FIFO [OK]
Common Mistakes:
Mixing order of initial zero indegree nodes
Forgetting to enqueue neighbors when indegree hits zero
Confusing DFS topological sort with Kahn's BFS
4. The following Go code for Kahn's Algorithm has a bug causing an infinite loop. What is the error?
func kahnTopoSort(vertices int, edges [][2]int) []int {
indegree := make([]int, vertices)
graph := make([][]int, vertices)
for _, e := range edges {
graph[e[0]] = append(graph[e[0]], e[1])
indegree[e[1]]++
}
queue := list.New()
for i := 0; i < vertices; i++ {
if indegree[i] == 0 {
queue.PushBack(i)
}
}
var result []int
for queue.Len() > 0 {
front := queue.Front().Value.(int)
result = append(result, front)
for _, nbr := range graph[front] {
indegree[nbr]--
if indegree[nbr] == 0 {
queue.PushBack(nbr)
}
}
}
return result
}
medium
A. Indegree array is not initialized correctly
B. Graph edges are not added properly
C. Missing queue.Remove call to dequeue the front element
D. Result slice is not appended correctly
Solution
Step 1: Analyze queue usage in loop
The code uses queue.Front().Value to get the front element but never removes it from the queue, so the queue length never decreases, causing an infinite loop.
Step 2: Identify missing operation
To fix, call queue.Remove(queue.Front()) to dequeue the front element after processing it.
Final Answer:
Missing queue.Remove call to dequeue the front element -> Option C
Quick Check:
Dequeue missing = infinite loop [OK]
Hint: Always remove front element after processing in queue [OK]
Common Mistakes:
Forgetting to remove front element from queue
Assuming indegree or graph initialization causes loop
Not appending result correctly
5. Given a Directed Acyclic Graph (DAG) with 7 vertices and edges: 0->1, 0->2, 1->3, 2->3, 3->4, 4->5, 5->6, how can Kahn's Algorithm be adapted to detect if the graph contains a cycle?
hard
A. Check if any node has indegree zero at start
B. Count processed nodes; if less than total vertices, a cycle exists
C. Use DFS instead of BFS to detect cycles
D. If queue becomes empty before processing all nodes, graph is acyclic