UNPKG

@dagrejs/graphlib

Version:

A directed and undirected multi-graph library

68 lines (58 loc) 1.68 kB
module.exports = dfs; /* * A helper that preforms a pre- or post-order traversal on the input graph * and returns the nodes in the order they were visited. If the graph is * undirected then this algorithm will navigate using neighbors. If the graph * is directed then this algorithm will navigate using successors. * * If the order is not "post", it will be treated as "pre". */ function dfs(g, vs, order) { if (!Array.isArray(vs)) { vs = [vs]; } var navigation = g.isDirected() ? v => g.successors(v) : v => g.neighbors(v); var orderFunc = order === "post" ? postOrderDfs : preOrderDfs; var acc = []; var visited = {}; vs.forEach(v => { if (!g.hasNode(v)) { throw new Error("Graph does not have node: " + v); } orderFunc(v, navigation, visited, acc); }); return acc; } function postOrderDfs(v, navigation, visited, acc) { var stack = [[v, false]]; while (stack.length > 0) { var curr = stack.pop(); if (curr[1]) { acc.push(curr[0]); } else { if (!Object.hasOwn(visited, curr[0])) { visited[curr[0]] = true; stack.push([curr[0], true]); forEachRight(navigation(curr[0]), w => stack.push([w, false])); } } } } function preOrderDfs(v, navigation, visited, acc) { var stack = [v]; while (stack.length > 0) { var curr = stack.pop(); if (!Object.hasOwn(visited, curr)) { visited[curr] = true; acc.push(curr); forEachRight(navigation(curr), w => stack.push(w)); } } } function forEachRight(array, iteratee) { var length = array.length; while (length--) { iteratee(array[length], length, array); } return array; }