( graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: DijkstraConfig<E> )
| 2378 | * @category algorithms |
| 2379 | */ |
| 2380 | export const dijkstra = <N, E, T extends Kind = "directed">( |
| 2381 | graph: Graph<N, E, T> | MutableGraph<N, E, T>, |
| 2382 | config: DijkstraConfig<E> |
| 2383 | ): Option.Option<PathResult<E>> => { |
| 2384 | const { cost, source, target } = config |
| 2385 | // Validate that source and target nodes exist |
| 2386 | if (!graph.nodes.has(source)) { |
| 2387 | throw missingNode(source) |
| 2388 | } |
| 2389 | if (!graph.nodes.has(target)) { |
| 2390 | throw missingNode(target) |
| 2391 | } |
| 2392 | |
| 2393 | // Early return if source equals target |
| 2394 | if (source === target) { |
| 2395 | return Option.some({ |
| 2396 | path: [source], |
| 2397 | distance: 0, |
| 2398 | costs: [] |
| 2399 | }) |
| 2400 | } |
| 2401 | |
| 2402 | // Distance tracking and priority queue simulation |
| 2403 | const distances = new Map<NodeIndex, number>() |
| 2404 | const previous = new Map<NodeIndex, { node: NodeIndex; edgeData: E } | null>() |
| 2405 | const visited = new Set<NodeIndex>() |
| 2406 | |
| 2407 | // Initialize distances |
| 2408 | // Iterate directly over node keys |
| 2409 | for (const node of graph.nodes.keys()) { |
| 2410 | distances.set(node, node === source ? 0 : Infinity) |
| 2411 | previous.set(node, null) |
| 2412 | } |
| 2413 | |
| 2414 | // Simple priority queue using array (can be optimized with proper heap) |
| 2415 | const priorityQueue: Array<{ node: NodeIndex; distance: number }> = [ |
| 2416 | { node: source, distance: 0 } |
| 2417 | ] |
| 2418 | |
| 2419 | while (priorityQueue.length > 0) { |
| 2420 | // Find minimum distance node (priority queue extract-min) |
| 2421 | let minIndex = 0 |
| 2422 | for (let i = 1; i < priorityQueue.length; i++) { |
| 2423 | if (priorityQueue[i].distance < priorityQueue[minIndex].distance) { |
| 2424 | minIndex = i |
| 2425 | } |
| 2426 | } |
| 2427 | |
| 2428 | const current = priorityQueue.splice(minIndex, 1)[0] |
| 2429 | const currentNode = current.node |
| 2430 | |
| 2431 | // Skip if already visited (can happen with duplicate entries) |
| 2432 | if (visited.has(currentNode)) { |
| 2433 | continue |
| 2434 | } |
| 2435 | |
| 2436 | visited.add(currentNode) |
| 2437 |
nothing calls this directly
no test coverage detected