Fix stack overflows due to recursion in Forest::find (#358)

This commit is contained in:
Daniel Lubarov 2021-11-15 10:11:16 -08:00 committed by GitHub
parent 239c795a9d
commit 9aafa447f8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -45,15 +45,23 @@ impl Forest {
}
/// Path compression method, see https://en.wikipedia.org/wiki/Disjoint-set_data_structure#Finding_set_representatives.
pub fn find(&mut self, x_index: usize) -> usize {
let x_parent = self.parents[x_index];
if x_parent != x_index {
let root_index = self.find(x_parent);
self.parents[x_index] = root_index;
root_index
} else {
x_index
pub fn find(&mut self, mut x_index: usize) -> usize {
// Note: We avoid recursion here since the chains can be long, causing stack overflows.
// First, find the representative of the set containing `x_index`.
let mut representative = x_index;
while self.parents[representative] != representative {
representative = self.parents[representative];
}
// Then, update each node in this chain to point directly to the representative.
while self.parents[x_index] != x_index {
let old_parent = self.parents[x_index];
self.parents[x_index] = representative;
x_index = old_parent;
}
representative
}
/// Merge two sets.