(
graph: Graph<N, E, T> | MutableGraph<N, E, T>,
config: SearchConfig = {}
)
| 3254 | * @category iterators |
| 3255 | */ |
| 3256 | export const dfs = <N, E, T extends Kind = "directed">( |
| 3257 | graph: Graph<N, E, T> | MutableGraph<N, E, T>, |
| 3258 | config: SearchConfig = {} |
| 3259 | ): NodeWalker<N> => { |
| 3260 | const start = config.start ?? [] |
| 3261 | const direction = config.direction ?? "outgoing" |
| 3262 | |
| 3263 | // Validate that all start nodes exist |
| 3264 | for (const nodeIndex of start) { |
| 3265 | if (!hasNode(graph, nodeIndex)) { |
| 3266 | throw missingNode(nodeIndex) |
| 3267 | } |
| 3268 | } |
| 3269 | |
| 3270 | return new Walker((f) => ({ |
| 3271 | [Symbol.iterator]: () => { |
| 3272 | const stack = [...start] |
| 3273 | const discovered = new Set<NodeIndex>() |
| 3274 | |
| 3275 | const nextMapped = () => { |
| 3276 | while (stack.length > 0) { |
| 3277 | const current = stack.pop()! |
| 3278 | |
| 3279 | if (discovered.has(current)) { |
| 3280 | continue |
| 3281 | } |
| 3282 | |
| 3283 | discovered.add(current) |
| 3284 | |
| 3285 | const nodeDataOption = graph.nodes.get(current) |
| 3286 | if (nodeDataOption === undefined) { |
| 3287 | continue |
| 3288 | } |
| 3289 | |
| 3290 | const neighbors = getTraversalNeighbors(graph, current, direction) |
| 3291 | for (let i = neighbors.length - 1; i >= 0; i--) { |
| 3292 | const neighbor = neighbors[i] |
| 3293 | if (!discovered.has(neighbor)) { |
| 3294 | stack.push(neighbor) |
| 3295 | } |
| 3296 | } |
| 3297 | |
| 3298 | return { done: false, value: f(current, nodeDataOption) } |
| 3299 | } |
| 3300 | |
| 3301 | return { done: true, value: undefined } as const |
| 3302 | } |
| 3303 | |
| 3304 | return { next: nextMapped } |
| 3305 | } |
| 3306 | })) |
| 3307 | } |
| 3308 | |
| 3309 | /** |
| 3310 | * Creates a new BFS iterator with optional configuration. |
nothing calls this directly
no test coverage detected