(
graph: Graph<N, E, T> | MutableGraph<N, E, T>,
config: SearchConfig = {}
)
| 3339 | * @category iterators |
| 3340 | */ |
| 3341 | export const bfs = <N, E, T extends Kind = "directed">( |
| 3342 | graph: Graph<N, E, T> | MutableGraph<N, E, T>, |
| 3343 | config: SearchConfig = {} |
| 3344 | ): NodeWalker<N> => { |
| 3345 | const start = config.start ?? [] |
| 3346 | const direction = config.direction ?? "outgoing" |
| 3347 | |
| 3348 | // Validate that all start nodes exist |
| 3349 | for (const nodeIndex of start) { |
| 3350 | if (!hasNode(graph, nodeIndex)) { |
| 3351 | throw missingNode(nodeIndex) |
| 3352 | } |
| 3353 | } |
| 3354 | |
| 3355 | return new Walker((f) => ({ |
| 3356 | [Symbol.iterator]: () => { |
| 3357 | const queue = [...start] |
| 3358 | const discovered = new Set<NodeIndex>() |
| 3359 | |
| 3360 | const nextMapped = () => { |
| 3361 | while (queue.length > 0) { |
| 3362 | const current = queue.shift()! |
| 3363 | |
| 3364 | if (!discovered.has(current)) { |
| 3365 | discovered.add(current) |
| 3366 | |
| 3367 | const neighbors = getTraversalNeighbors(graph, current, direction) |
| 3368 | for (const neighbor of neighbors) { |
| 3369 | if (!discovered.has(neighbor)) { |
| 3370 | queue.push(neighbor) |
| 3371 | } |
| 3372 | } |
| 3373 | |
| 3374 | const nodeData = getNode(graph, current) |
| 3375 | if (Option.isSome(nodeData)) { |
| 3376 | return { done: false, value: f(current, nodeData.value) } |
| 3377 | } |
| 3378 | return nextMapped() |
| 3379 | } |
| 3380 | } |
| 3381 | |
| 3382 | return { done: true, value: undefined } as const |
| 3383 | } |
| 3384 | |
| 3385 | return { next: nextMapped } |
| 3386 | } |
| 3387 | })) |
| 3388 | } |
| 3389 | |
| 3390 | /** |
| 3391 | * Configuration options for topological sort iterator. |
nothing calls this directly
no test coverage detected