From d5a79e77cea8b668010a83891a03c5d64deb7e6d Mon Sep 17 00:00:00 2001 From: raj_mathe Date: Thu, 14 Apr 2022 12:26:53 +0200 Subject: [PATCH] master > master: code-rust - algorithmus sauberer + Kommentare --- code/rust/src/graphs/tarjan.rs | 57 ++++++++++++++++------------------ 1 file changed, 27 insertions(+), 30 deletions(-) diff --git a/code/rust/src/graphs/tarjan.rs b/code/rust/src/graphs/tarjan.rs index 1637fe5..dcba891 100644 --- a/code/rust/src/graphs/tarjan.rs +++ b/code/rust/src/graphs/tarjan.rs @@ -35,51 +35,48 @@ pub fn tarjan_algorithm(gph: &Graph, debug: bool) -> Vec> let mut ctx = Context::new(&gph, debug); for u in gph.nodes.iter() { - tarjan_visit(gph, u, &mut ctx); + if ctx.get_state(&u) == State::UNTOUCHED { + tarjan_visit(gph, &u, &mut ctx); + } } return ctx.components; } -/// recursive depth-first search algorithm to compute components -fn tarjan_visit(gph: &Graph, v: &T, ctx: &mut Context) +/// Recursive depth-first search algorithm to compute strongly components of a graph. +fn tarjan_visit(gph: &Graph, &u: &T, ctx: &mut Context) where T: Eq + Hash + Clone + Copy + Display { - // do nothing, if v already visited - if !(ctx.get_state(v) == State::UNTOUCHED) { return; } + // Place node on stack + initialise visit-index + component-index. + ctx.max_index += 1; + ctx.push(&u); + ctx.set_root(&u, ctx.max_index); + ctx.set_index(&u, ctx.max_index); + ctx.set_state(&u, State::PENDING); /**************** - * First visit of v. - * - Place v on stack. - * - Initialise visit-index + component-index. - * - After each rekursiv call, only those all + * Compute strongly connected components of each child node. + * NOTE: Child nodes remain on stack, if and only if parent is in same component. ****************/ - ctx.max_index += 1; - ctx.push(v); - ctx.set_root(v, ctx.max_index); - ctx.set_index(v, ctx.max_index); - ctx.set_state(v, State::PENDING); - - // depth first search: - for u in gph.successors(&v) { - tarjan_visit(gph, &u, ctx); - /**** - * u is in the same component as v, if and only if u is still on the stack. - * In this case, update the associated component-index of v: - ****/ - if ctx.stack.contains(&u) { - ctx.set_root(v, value_min!(ctx.get_root(v), ctx.get_root(&u))); + for v in gph.successors(&u) { + // Visit child node only if untouched: + if ctx.get_state(&v) == State::UNTOUCHED { + tarjan_visit(gph, &v, ctx); + } + // Update associated component-index of parent node, if in same component as child: + if ctx.stack.contains(&v) { + ctx.set_root(&u, value_min!(ctx.get_root(&u), ctx.get_root(&v))); } } - ctx.set_state(v, State::FINISHED); - ctx.log_info(&v); + ctx.set_state(&u, State::FINISHED); + ctx.log_info(&u); - if ctx.get_index(v) == ctx.get_root(v) { + if ctx.get_index(&u) == ctx.get_root(&u) { let mut component: Vec = Vec::new(); loop { - let u = ctx.top(); + let v = ctx.top(); ctx.pop(); - component.push(u.clone()); - if u == *v { break; } + component.push(v.clone()); + if u == v { break; } } ctx.components.push(component); }