use crate::VectorType;
use crate::node::NodeId;
use crate::storage::memtable::MemTable;
use std::collections::HashMap;
struct UnionFind {
parent: HashMap<NodeId, NodeId>,
rank: HashMap<NodeId, usize>,
}
impl UnionFind {
fn new(nodes: &[NodeId]) -> Self {
let mut parent = HashMap::with_capacity(nodes.len());
let mut rank = HashMap::with_capacity(nodes.len());
for &id in nodes {
parent.insert(id, id);
rank.insert(id, 0);
}
Self { parent, rank }
}
fn find(&mut self, x: NodeId) -> NodeId {
let p = self.parent[&x];
if p != x {
let root = self.find(p);
self.parent.insert(x, root);
root
} else {
x
}
}
fn union(&mut self, a: NodeId, b: NodeId) {
let ra = self.find(a);
let rb = self.find(b);
if ra == rb {
return;
}
let rank_a = self.rank[&ra];
let rank_b = self.rank[&rb];
if rank_a < rank_b {
self.parent.insert(ra, rb);
} else if rank_a > rank_b {
self.parent.insert(rb, ra);
} else {
self.parent.insert(rb, ra);
*self.rank.get_mut(&ra).unwrap() += 1;
}
}
}
pub fn weakly_connected_components<T: VectorType>(mt: &MemTable<T>) -> Vec<Vec<NodeId>> {
let all_ids = mt.all_node_ids();
if all_ids.is_empty() {
return Vec::new();
}
let mut uf = UnionFind::new(&all_ids);
for &src in &all_ids {
if let Some(edges) = mt.get_edges(src) {
for edge in edges {
uf.union(src, edge.target_id);
}
}
}
let mut components: HashMap<NodeId, Vec<NodeId>> = HashMap::new();
for &id in &all_ids {
let root = uf.find(id);
components.entry(root).or_default().push(id);
}
let mut result: Vec<Vec<NodeId>> = components.into_values().collect();
result.sort_by(|a, b| b.len().cmp(&a.len()));
result
}