use std::collections::{VecDeque, HashMap};
fn kahn_topological_sort(graph: &HashMap<char, Vec<char>>) -> Vec<char> {
let mut in_degree = HashMap::new();
for &node in graph.keys() {
in_degree.insert(node, 0);
}
for edges in graph.values() {
for &v in edges {
*in_degree.entry(v).or_insert(0) += 1;
}
}
let mut queue = VecDeque::new();
for (&node, °) in &in_degree {
if deg == 0 {
queue.push_back(node);
}
}
let mut topo_order = Vec::new();
while let Some(u) = queue.pop_front() {
topo_order.push(u);
if let Some(neighbors) = graph.get(&u) {
for &v in neighbors {
let deg = in_degree.get_mut(&v).unwrap();
*deg -= 1;
if *deg == 0 {
queue.push_back(v);
}
}
}
}
topo_order
}
fn main() {
let mut graph = HashMap::new();
graph.insert('A', vec!['C']);
graph.insert('B', vec!['C', 'D']);
graph.insert('C', vec!['E']);
graph.insert('D', vec!['F']);
graph.insert('E', vec!['H', 'F']);
graph.insert('F', vec!['G']);
graph.insert('G', vec![]);
graph.insert('H', vec![]);
let result = kahn_topological_sort(&graph);
println!("{:?}", result);
}The algorithm starts with nodes having zero in-degree: 'A' and 'B'. It processes 'A' first (due to queue order), then 'B'. The order respects dependencies, so 'A' comes before 'C', 'B' before 'C' and 'D', and so on. The output is a valid topological order.
If some nodes never reach zero in-degree, it means they are part of a cycle. Kahn's Algorithm cannot process nodes in cycles, so the output list is shorter than the total nodes.
use std::collections::{VecDeque, HashMap};
fn kahn_sort_bug(graph: &HashMap<char, Vec<char>>) -> Vec<char> {
let mut in_degree = HashMap::new();
for &node in graph.keys() {
in_degree.insert(node, 0);
}
for edges in graph.values() {
for &v in edges {
*in_degree.entry(v).or_insert(0) += 1;
}
}
let mut queue = VecDeque::new();
for (&node, °) in &in_degree {
if deg > 0 {
queue.push_back(node);
}
}
let mut topo_order = Vec::new();
while let Some(u) = queue.pop_front() {
topo_order.push(u);
if let Some(neighbors) = graph.get(&u) {
for &v in neighbors {
let deg = in_degree.get_mut(&v).unwrap();
*deg -= 1;
if *deg == 0 {
queue.push_back(v);
}
}
}
}
topo_order
}The bug is that nodes with in-degree greater than zero are added to the queue initially, which is incorrect. Only nodes with zero in-degree should be enqueued first.
Nodes A and B have no dependencies between them, so they can appear in any order before C. The valid orders are [A, B, C] and [B, A, C], so 2 in total.
use std::collections::{VecDeque, HashMap};
fn kahn_topological_sort(graph: &HashMap<char, Vec<char>>) -> Vec<char> {
let mut in_degree = HashMap::new();
for &node in graph.keys() {
in_degree.insert(node, 0);
}
for edges in graph.values() {
for &v in edges {
*in_degree.entry(v).or_insert(0) += 1;
}
}
let mut queue = VecDeque::new();
for (&node, °) in &in_degree {
if deg == 0 {
queue.push_back(node);
}
}
let mut topo_order = Vec::new();
while let Some(u) = queue.pop_front() {
topo_order.push(u);
if let Some(neighbors) = graph.get(&u) {
for &v in neighbors {
let deg = in_degree.get_mut(&v).unwrap();
*deg -= 1;
if *deg == 0 {
queue.push_back(v);
}
}
}
}
topo_order
}
fn main() {
let mut graph = HashMap::new();
graph.insert('A', vec!['B']);
graph.insert('B', vec!['C']);
graph.insert('C', vec!['A']); // cycle A->B->C->A
let result = kahn_topological_sort(&graph);
println!("{:?}", result);
}Because of the cycle, all nodes have in-degree 1, so the initial queue is empty. The algorithm returns an empty vector indicating no valid topological order.
