(graph)
| 15 | * @return {Object} |
| 16 | */ |
| 17 | export default function graphBridges(graph) { |
| 18 | // Set of vertices we've already visited during DFS. |
| 19 | const visitedSet = {}; |
| 20 | |
| 21 | // Set of bridges. |
| 22 | const bridges = {}; |
| 23 | |
| 24 | // Time needed to discover to the current vertex. |
| 25 | let discoveryTime = 0; |
| 26 | |
| 27 | // Peek the start vertex for DFS traversal. |
| 28 | const startVertex = graph.getAllVertices()[0]; |
| 29 | |
| 30 | const dfsCallbacks = { |
| 31 | /** |
| 32 | * @param {GraphVertex} currentVertex |
| 33 | */ |
| 34 | enterVertex: ({ currentVertex }) => { |
| 35 | // Tick discovery time. |
| 36 | discoveryTime += 1; |
| 37 | |
| 38 | // Put current vertex to visited set. |
| 39 | visitedSet[currentVertex.getKey()] = new VisitMetadata({ |
| 40 | discoveryTime, |
| 41 | lowDiscoveryTime: discoveryTime, |
| 42 | }); |
| 43 | }, |
| 44 | /** |
| 45 | * @param {GraphVertex} currentVertex |
| 46 | * @param {GraphVertex} previousVertex |
| 47 | */ |
| 48 | leaveVertex: ({ currentVertex, previousVertex }) => { |
| 49 | if (previousVertex === null) { |
| 50 | // Don't do anything for the root vertex if it is already current (not previous one). |
| 51 | return; |
| 52 | } |
| 53 | |
| 54 | // Check if current node is connected to any early node other then previous one. |
| 55 | visitedSet[currentVertex.getKey()].lowDiscoveryTime = currentVertex.getNeighbors() |
| 56 | .filter((earlyNeighbor) => earlyNeighbor.getKey() !== previousVertex.getKey()) |
| 57 | .reduce( |
| 58 | /** |
| 59 | * @param {number} lowestDiscoveryTime |
| 60 | * @param {GraphVertex} neighbor |
| 61 | */ |
| 62 | (lowestDiscoveryTime, neighbor) => { |
| 63 | const neighborLowTime = visitedSet[neighbor.getKey()].lowDiscoveryTime; |
| 64 | return neighborLowTime < lowestDiscoveryTime ? neighborLowTime : lowestDiscoveryTime; |
| 65 | }, |
| 66 | visitedSet[currentVertex.getKey()].lowDiscoveryTime, |
| 67 | ); |
| 68 | |
| 69 | // Compare low discovery times. In case if current low discovery time is less than the one |
| 70 | // in previous vertex then update previous vertex low time. |
| 71 | const currentLowDiscoveryTime = visitedSet[currentVertex.getKey()].lowDiscoveryTime; |
| 72 | const previousLowDiscoveryTime = visitedSet[previousVertex.getKey()].lowDiscoveryTime; |
| 73 | if (currentLowDiscoveryTime < previousLowDiscoveryTime) { |
| 74 | visitedSet[previousVertex.getKey()].lowDiscoveryTime = currentLowDiscoveryTime; |
no test coverage detected