@@ -6,61 +6,85 @@ use crate::prelude::*;
6
6
7
7
pub fn bfs_directed < NI , G > (
8
8
graph : & G ,
9
- node_id : NI ,
9
+ node_ids : impl IntoIterator < Item = NI > ,
10
10
direction : Direction ,
11
11
) -> DirectedBreadthFirst < ' _ , G , NI >
12
12
where
13
13
NI : Idx + Hash ,
14
14
G : Graph < NI > + DirectedDegrees < NI > + DirectedNeighbors < NI > + Sync ,
15
15
{
16
- DirectedBreadthFirst :: new ( graph, node_id , direction)
16
+ DirectedBreadthFirst :: new ( graph, node_ids , direction)
17
17
}
18
18
19
19
pub struct DirectedBreadthFirst < ' a , G , NI > {
20
20
graph : & ' a G ,
21
+ seen : BitVec < usize > ,
21
22
visited : BitVec < usize > ,
22
23
queue : VecDeque < NI > ,
23
24
direction : Direction ,
24
25
}
25
26
26
27
impl < ' a , G , NI > DirectedBreadthFirst < ' a , G , NI >
27
28
where
28
- NI : Idx + Hash ,
29
+ NI : Idx + Hash + std :: fmt :: Debug ,
29
30
G : Graph < NI > + DirectedNeighbors < NI > + Sync ,
30
31
{
31
- pub fn new ( graph : & ' a G , node_id : NI , direction : Direction ) -> Self {
32
+ pub fn new ( graph : & ' a G , node_ids : impl IntoIterator < Item = NI > , direction : Direction ) -> Self {
33
+ let bitvec = BitVec :: repeat ( false , graph. node_count ( ) . index ( ) ) ;
34
+ let visited = bitvec. clone ( ) ;
35
+
36
+ let mut seen = bitvec;
37
+ let mut queue = VecDeque :: new ( ) ;
38
+ Self :: enqueue_into ( & mut seen, & mut queue, node_ids) ;
39
+
32
40
Self {
33
41
graph,
34
- visited : BitVec :: repeat ( false , graph. node_count ( ) . index ( ) ) ,
35
- queue : VecDeque :: from_iter ( [ node_id] ) ,
42
+ seen,
43
+ visited,
44
+ queue,
36
45
direction,
37
46
}
38
47
}
39
48
40
49
fn dequeue ( & mut self ) -> Option < NI > {
41
50
loop {
42
51
let node_id = self . queue . pop_front ( ) ?;
43
-
44
52
if !self . visited . replace ( node_id. index ( ) , true ) {
45
53
return Some ( node_id) ;
46
54
}
47
55
}
48
56
}
49
57
50
- fn enqueue_out_neighbors ( & mut self , node_id : NI ) {
51
- let neighbors = self
58
+ fn enqueue_into (
59
+ seen : & mut BitVec < usize > ,
60
+ queue : & mut VecDeque < NI > ,
61
+ node_ids : impl IntoIterator < Item = NI > ,
62
+ ) {
63
+ for node_id in node_ids {
64
+ if !seen. replace ( node_id. index ( ) , true ) {
65
+ queue. push_back ( node_id) ;
66
+ }
67
+ }
68
+ }
69
+
70
+ fn enqueue_out_neighbors_of ( & mut self , node_id : NI ) {
71
+ let node_ids = self
52
72
. graph
53
73
. out_neighbors ( node_id)
54
- . filter ( |& node_id| !self . visited [ node_id. index ( ) ] ) ;
55
- self . queue . extend ( neighbors) ;
74
+ . copied ( )
75
+ . filter ( |node_id| !self . visited [ node_id. index ( ) ] ) ;
76
+
77
+ Self :: enqueue_into ( & mut self . seen , & mut self . queue , node_ids) ;
56
78
}
57
79
58
- fn enqueue_in_neighbors ( & mut self , node_id : NI ) {
59
- let neighbors = self
80
+ fn enqueue_in_neighbors_of ( & mut self , node_id : NI ) {
81
+ let node_ids = self
60
82
. graph
61
83
. in_neighbors ( node_id)
62
- . filter ( |& node_id| !self . visited [ node_id. index ( ) ] ) ;
63
- self . queue . extend ( neighbors) ;
84
+ . copied ( )
85
+ . filter ( |node_id| !self . visited [ node_id. index ( ) ] ) ;
86
+
87
+ Self :: enqueue_into ( & mut self . seen , & mut self . queue , node_ids) ;
64
88
}
65
89
}
66
90
@@ -75,28 +99,32 @@ where
75
99
let node_id = self . dequeue ( ) ?;
76
100
77
101
match self . direction {
78
- Direction :: Outgoing => self . enqueue_out_neighbors ( node_id) ,
79
- Direction :: Incoming => self . enqueue_in_neighbors ( node_id) ,
102
+ Direction :: Outgoing => self . enqueue_out_neighbors_of ( node_id) ,
103
+ Direction :: Incoming => self . enqueue_in_neighbors_of ( node_id) ,
80
104
Direction :: Undirected => {
81
- self . enqueue_out_neighbors ( node_id) ;
82
- self . enqueue_in_neighbors ( node_id) ;
105
+ self . enqueue_out_neighbors_of ( node_id) ;
106
+ self . enqueue_in_neighbors_of ( node_id) ;
83
107
}
84
108
}
85
109
86
110
Some ( node_id)
87
111
}
88
112
}
89
113
90
- pub fn bfs_undirected < NI , G > ( graph : & G , node_id : NI ) -> UndirectedBreadthFirst < ' _ , G , NI >
114
+ pub fn bfs_undirected < NI , G > (
115
+ graph : & G ,
116
+ node_ids : impl IntoIterator < Item = NI > ,
117
+ ) -> UndirectedBreadthFirst < ' _ , G , NI >
91
118
where
92
119
NI : Idx + Hash ,
93
120
G : Graph < NI > + UndirectedDegrees < NI > + UndirectedNeighbors < NI > + Sync ,
94
121
{
95
- UndirectedBreadthFirst :: new ( graph, node_id )
122
+ UndirectedBreadthFirst :: new ( graph, node_ids )
96
123
}
97
124
98
125
pub struct UndirectedBreadthFirst < ' a , G , NI > {
99
126
graph : & ' a G ,
127
+ seen : BitVec < usize > ,
100
128
visited : BitVec < usize > ,
101
129
queue : VecDeque < NI > ,
102
130
}
@@ -106,11 +134,19 @@ where
106
134
NI : Idx + Hash + std:: fmt:: Debug ,
107
135
G : Graph < NI > + UndirectedNeighbors < NI > + Sync ,
108
136
{
109
- pub fn new ( graph : & ' a G , node_id : NI ) -> Self {
137
+ pub fn new ( graph : & ' a G , node_ids : impl IntoIterator < Item = NI > ) -> Self {
138
+ let bitvec = BitVec :: repeat ( false , graph. node_count ( ) . index ( ) ) ;
139
+ let visited = bitvec. clone ( ) ;
140
+
141
+ let mut seen = bitvec;
142
+ let mut queue = VecDeque :: new ( ) ;
143
+ Self :: enqueue_into ( & mut seen, & mut queue, node_ids) ;
144
+
110
145
Self {
111
146
graph,
112
- visited : BitVec :: repeat ( false , graph. node_count ( ) . index ( ) ) ,
113
- queue : VecDeque :: from_iter ( [ node_id] ) ,
147
+ seen,
148
+ visited,
149
+ queue,
114
150
}
115
151
}
116
152
@@ -124,15 +160,26 @@ where
124
160
}
125
161
}
126
162
127
- fn enqueue_neighbors ( & mut self , node_id : NI ) {
128
- let neighbors = self
163
+ fn enqueue_into (
164
+ seen : & mut BitVec < usize > ,
165
+ queue : & mut VecDeque < NI > ,
166
+ node_ids : impl IntoIterator < Item = NI > ,
167
+ ) {
168
+ for node_id in node_ids {
169
+ if !seen. replace ( node_id. index ( ) , true ) {
170
+ queue. push_back ( node_id) ;
171
+ }
172
+ }
173
+ }
174
+
175
+ fn enqueue_neighbors_of ( & mut self , node_id : NI ) {
176
+ let node_ids = self
129
177
. graph
130
178
. neighbors ( node_id)
179
+ . copied ( )
131
180
. filter ( |& node_id| !self . visited [ node_id. index ( ) ] ) ;
132
181
133
- let neighbors: Vec < _ > = neighbors. collect ( ) ;
134
-
135
- self . queue . extend ( neighbors) ;
182
+ Self :: enqueue_into ( & mut self . seen , & mut self . queue , node_ids) ;
136
183
}
137
184
}
138
185
@@ -146,18 +193,18 @@ where
146
193
fn next ( & mut self ) -> Option < Self :: Item > {
147
194
let node_id = self . dequeue ( ) ?;
148
195
149
- self . enqueue_neighbors ( node_id) ;
196
+ self . enqueue_neighbors_of ( node_id) ;
150
197
151
198
Some ( node_id)
152
199
}
153
200
}
154
201
155
202
#[ cfg( test) ]
156
203
mod tests {
157
- use super :: * ;
158
- use crate :: prelude:: { CsrLayout , GraphBuilder } ;
204
+ use graph:: prelude:: { CsrLayout , GraphBuilder } ;
159
205
160
206
use super :: * ;
207
+
161
208
mod directed {
162
209
use super :: * ;
163
210
@@ -168,7 +215,7 @@ mod tests {
168
215
. edges ( vec ! [ ( 0 , 1 ) , ( 0 , 2 ) , ( 1 , 2 ) , ( 1 , 3 ) , ( 2 , 3 ) , ( 2 , 1 ) , ( 3 , 1 ) ] )
169
216
. build ( ) ;
170
217
171
- let actual: Vec < usize > = bfs_directed ( & graph, 0 , Direction :: Outgoing ) . collect ( ) ;
218
+ let actual: Vec < usize > = bfs_directed ( & graph, [ 0 ] , Direction :: Outgoing ) . collect ( ) ;
172
219
let expected: Vec < usize > = vec ! [ 0 , 1 , 2 , 3 ] ;
173
220
174
221
assert_eq ! ( actual, expected) ;
@@ -181,7 +228,7 @@ mod tests {
181
228
. edges ( vec ! [ ( 0 , 1 ) , ( 0 , 2 ) , ( 1 , 2 ) , ( 1 , 3 ) , ( 2 , 1 ) , ( 2 , 1 ) , ( 3 , 1 ) ] )
182
229
. build ( ) ;
183
230
184
- let actual: Vec < usize > = bfs_directed ( & graph, 0 , Direction :: Outgoing ) . collect ( ) ;
231
+ let actual: Vec < usize > = bfs_directed ( & graph, [ 0 ] , Direction :: Outgoing ) . collect ( ) ;
185
232
let expected: Vec < usize > = vec ! [ 0 , 1 , 2 , 3 ] ;
186
233
187
234
assert_eq ! ( actual, expected) ;
@@ -195,7 +242,7 @@ mod tests {
195
242
. edges ( vec ! [ ( 0 , 1 ) , ( 0 , 2 ) , ( 1 , 2 ) , ( 1 , 3 ) , ( 2 , 3 ) , ( 2 , 1 ) , ( 3 , 1 ) ] )
196
243
. build ( ) ;
197
244
198
- let actual: Vec < usize > = bfs_undirected ( & graph, 0 ) . collect ( ) ;
245
+ let actual: Vec < usize > = bfs_undirected ( & graph, [ 0 ] ) . collect ( ) ;
199
246
let expected: Vec < usize > = vec ! [ 0 , 1 , 2 , 3 ] ;
200
247
201
248
assert_eq ! ( actual, expected) ;
0 commit comments