mirror of
https://github.com/uutils/coreutils.git
synced 2026-06-10 15:48:22 -07:00
fix(tsort): correct minimal cycle reporting and precise back-edge removal with iterative DFS (#8786)
- Implement iterative DFS to prevent stack overflows (from PR #8737) - Fix minimal cycle reporting to show only actual cycle nodes - Remove redundant back-edge from last cycle node to first - Update test expectations for corrected cycle handling
This commit is contained in:
@@ -236,8 +236,8 @@ impl<'input> Graph<'input> {
|
||||
for &node in &cycle {
|
||||
show!(LoopNode(node));
|
||||
}
|
||||
let u = cycle[0];
|
||||
let v = cycle[1];
|
||||
let u = *cycle.last().expect("cycle must be non-empty");
|
||||
let v = cycle[0];
|
||||
self.remove_edge(u, v);
|
||||
if self.indegree(v).unwrap() == 0 {
|
||||
frontier.push_back(v);
|
||||
@@ -245,7 +245,6 @@ impl<'input> Graph<'input> {
|
||||
}
|
||||
|
||||
fn detect_cycle(&self) -> Vec<&'input str> {
|
||||
// Sort the nodes just to make this function deterministic.
|
||||
let mut nodes: Vec<_> = self.nodes.keys().collect();
|
||||
nodes.sort_unstable();
|
||||
|
||||
@@ -253,11 +252,8 @@ impl<'input> Graph<'input> {
|
||||
let mut stack = Vec::with_capacity(self.nodes.len());
|
||||
for node in nodes {
|
||||
if self.dfs(node, &mut visited, &mut stack) {
|
||||
// last element in the stack appears twice: at the begin
|
||||
// and at the end of the loop
|
||||
let (loop_entry, _) = stack.pop().expect("loop is not empty");
|
||||
|
||||
// skip the prefix which doesn't belong to the loop
|
||||
return stack
|
||||
.into_iter()
|
||||
.map(|(node, _)| node)
|
||||
|
||||
Executable
BIN
Binary file not shown.
@@ -103,7 +103,7 @@ fn test_cycle() {
|
||||
new_ucmd!()
|
||||
.pipe_in("a b b c c d c b")
|
||||
.fails_with_code(1)
|
||||
.stdout_is("a\nc\nd\nb\n")
|
||||
.stdout_is("a\nb\nc\nd\n")
|
||||
.stderr_is("tsort: -: input contains a loop:\ntsort: b\ntsort: c\n");
|
||||
}
|
||||
|
||||
@@ -119,7 +119,7 @@ fn test_two_cycles() {
|
||||
new_ucmd!()
|
||||
.pipe_in("a b b c c b b d d b")
|
||||
.fails_with_code(1)
|
||||
.stdout_is("a\nc\nd\nb\n")
|
||||
.stdout_is("a\nb\nc\nd\n")
|
||||
.stderr_is("tsort: -: input contains a loop:\ntsort: b\ntsort: c\ntsort: -: input contains a loop:\ntsort: b\ntsort: d\n");
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user