mirror of
https://github.com/trekhleb/javascript-algorithms.git
synced 2025-12-08 19:06:00 +00:00
60 lines
1.9 KiB
JavaScript
60 lines
1.9 KiB
JavaScript
import depthFirstSearch from '../depth-first-search/depthFirstSearch';
|
|
|
|
/**
|
|
* Detect cycle in undirected graph using Depth First Search.
|
|
*
|
|
* @param {Graph} graph
|
|
*/
|
|
export default function detectUndirectedCycle(graph) {
|
|
let cycle = null;
|
|
|
|
// List of vertices that we have visited.
|
|
const visitedVertices = {};
|
|
|
|
// List of parents vertices for every visited vertex.
|
|
const parents = {};
|
|
|
|
// Callbacks for DFS traversing.
|
|
const callbacks = {
|
|
allowTraversal: ({ currentVertex, nextVertex }) => {
|
|
// Don't allow further traversal in case if cycle has been detected.
|
|
if (cycle) {
|
|
return false;
|
|
}
|
|
|
|
// Don't allow traversal from child back to its parent.
|
|
const currentVertexParent = parents[currentVertex.getKey()];
|
|
const currentVertexParentKey = currentVertexParent ? currentVertexParent.getKey() : null;
|
|
|
|
return currentVertexParentKey !== nextVertex.getKey();
|
|
},
|
|
enterVertex: ({ currentVertex, previousVertex }) => {
|
|
if (visitedVertices[currentVertex.getKey()]) {
|
|
// Compile cycle path based on parents of previous vertices.
|
|
cycle = {};
|
|
|
|
let currentCycleVertex = currentVertex;
|
|
let previousCycleVertex = previousVertex;
|
|
|
|
while (previousCycleVertex.getKey() !== currentVertex.getKey()) {
|
|
cycle[currentCycleVertex.getKey()] = previousCycleVertex;
|
|
currentCycleVertex = previousCycleVertex;
|
|
previousCycleVertex = parents[previousCycleVertex.getKey()];
|
|
}
|
|
|
|
cycle[currentCycleVertex.getKey()] = previousCycleVertex;
|
|
} else {
|
|
// Add next vertex to visited set.
|
|
visitedVertices[currentVertex.getKey()] = currentVertex;
|
|
parents[currentVertex.getKey()] = previousVertex;
|
|
}
|
|
},
|
|
};
|
|
|
|
// Start DFS traversing.
|
|
const startVertex = graph.getAllVertices()[0];
|
|
depthFirstSearch(graph, startVertex, callbacks);
|
|
|
|
return cycle;
|
|
}
|