From 3046ccc6a798b5a72ca7aa8a0404f620c7f2a177 Mon Sep 17 00:00:00 2001 From: YISH Date: Wed, 28 Feb 2024 15:32:00 +0800 Subject: [PATCH] Fix the logic error of `getStartingNodes` --- packages/server/src/utils/index.ts | 41 ++++++++++-------------------- 1 file changed, 14 insertions(+), 27 deletions(-) diff --git a/packages/server/src/utils/index.ts b/packages/server/src/utils/index.ts index 8092fbd8467..cab482e6ad5 100644 --- a/packages/server/src/utils/index.ts +++ b/packages/server/src/utils/index.ts @@ -162,39 +162,22 @@ export const constructGraphs = ( * @param {string} endNodeId */ export const getStartingNodes = (graph: INodeDirectedGraph, endNodeId: string) => { - const visited = new Set() - const queue: Array<[string, number]> = [[endNodeId, 0]] const depthQueue: IDepthQueue = { [endNodeId]: 0 } - let maxDepth = 0 - let startingNodeIds: string[] = [] - - while (queue.length > 0) { - const [currentNode, depth] = queue.shift()! - - if (visited.has(currentNode)) { - continue - } - - visited.add(currentNode) - - if (depth > maxDepth) { - maxDepth = depth - startingNodeIds = [currentNode] - } else if (depth === maxDepth) { - startingNodeIds.push(currentNode) - } - - for (const neighbor of graph[currentNode]) { - if (!visited.has(neighbor)) { - queue.push([neighbor, depth + 1]) - depthQueue[neighbor] = depth + 1 - } - } + // Assuming that this is a directed acyclic graph, there will be no infinite loop problem. + const walkGraph = (nodeId: string) => { + const depth = depthQueue[nodeId] + graph[nodeId].flatMap((id) => { + depthQueue[id] = Math.max(depthQueue[id] ?? 0, depth + 1) + walkGraph(id) + }) } + walkGraph(endNodeId) + + const maxDepth = Math.max(...Object.values(depthQueue)) const depthQueueReversed: IDepthQueue = {} for (const nodeId in depthQueue) { if (Object.prototype.hasOwnProperty.call(depthQueue, nodeId)) { @@ -202,6 +185,10 @@ export const getStartingNodes = (graph: INodeDirectedGraph, endNodeId: string) = } } + const startingNodeIds = Object.entries(depthQueueReversed) + .filter(([_, depth]) => depth === 0) + .map(([id, _]) => id) + return { startingNodeIds, depthQueue: depthQueueReversed } }