Skip to content

Commit b443124

Browse files
Merge pull request #513 from evenfurther/issue-511
fix(dfs_reach): visit nodes in the documented order
2 parents d703ba6 + 1dc3c0e commit b443124

2 files changed

Lines changed: 29 additions & 9 deletions

File tree

src/directed/dfs.rs

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -117,28 +117,29 @@ where
117117
FN: FnMut(&N) -> IN,
118118
IN: IntoIterator<Item = N>,
119119
{
120-
let (to_see, mut seen) = (vec![start.clone()], HashSet::new());
121-
seen.insert(start);
122120
DfsReachable {
123-
to_see,
124-
seen,
121+
to_see: vec![start],
122+
visited: HashSet::new(),
125123
successors,
126124
}
127125
}
128126

129127
/// Struct returned by [`dfs_reach`].
130128
pub struct DfsReachable<N, FN> {
131129
to_see: Vec<N>,
132-
seen: HashSet<N>,
130+
visited: HashSet<N>,
133131
successors: FN,
134132
}
135133

136-
impl<N, FN> DfsReachable<N, FN> {
134+
impl<N, FN> DfsReachable<N, FN>
135+
where
136+
N: Eq + Hash,
137+
{
137138
/// Return a lower bound on the number of remaining reachable
138139
/// nodes. Not all nodes are necessarily known in advance, and
139140
/// new reachable nodes may be discovered while using the iterator.
140141
pub fn remaining_nodes_low_bound(&self) -> usize {
141-
self.to_see.len()
142+
self.to_see.iter().collect::<HashSet<_>>().len()
142143
}
143144
}
144145

@@ -152,11 +153,14 @@ where
152153

153154
fn next(&mut self) -> Option<Self::Item> {
154155
let n = self.to_see.pop()?;
156+
if self.visited.contains(&n) {
157+
return self.next();
158+
}
159+
self.visited.insert(n.clone());
155160
let mut to_insert = Vec::new();
156161
for s in (self.successors)(&n) {
157-
if !self.seen.contains(&s) {
162+
if !self.visited.contains(&s) {
158163
to_insert.push(s.clone());
159-
self.seen.insert(s);
160164
}
161165
}
162166
self.to_see.extend(to_insert.into_iter().rev());

tests/dfs-reach.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
use pathfinding::directed::dfs::dfs_reach;
2+
3+
#[test]
4+
fn issue_511() {
5+
let it = dfs_reach(0, |&n| [n + 1, n + 5].into_iter().filter(|&x| x <= 10));
6+
assert_eq!(
7+
vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
8+
it.collect::<Vec<_>>()
9+
);
10+
}
11+
12+
#[test]
13+
fn issue_511_branches() {
14+
let it = dfs_reach(0, |&n| [n + 2, n + 5].into_iter().filter(|&x| x <= 10));
15+
assert_eq!(vec![0, 2, 4, 6, 8, 10, 9, 7, 5], it.collect::<Vec<_>>());
16+
}

0 commit comments

Comments
 (0)