tarjan.js 952 B

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
  1. var _ = require('../lodash')
  2. module.exports = tarjan
  3. function tarjan (g) {
  4. let index = 0
  5. const stack = []
  6. const visited = {} // node id -> { onStack, lowlink, index }
  7. const results = []
  8. function dfs (v) {
  9. var entry = visited[v] = {
  10. onStack: true,
  11. lowlink: index,
  12. index: index++
  13. }
  14. stack.push(v)
  15. g.successors(v).forEach(function (w) {
  16. if (!_.has(visited, w)) {
  17. dfs(w)
  18. entry.lowlink = Math.min(entry.lowlink, visited[w].lowlink)
  19. } else if (visited[w].onStack) {
  20. entry.lowlink = Math.min(entry.lowlink, visited[w].index)
  21. }
  22. })
  23. if (entry.lowlink === entry.index) {
  24. const cmpt = []
  25. let w
  26. do {
  27. w = stack.pop()
  28. visited[w].onStack = false
  29. cmpt.push(w)
  30. } while (v !== w)
  31. results.push(cmpt)
  32. }
  33. }
  34. g.nodes().forEach(function (v) {
  35. if (!_.has(visited, v)) {
  36. dfs(v)
  37. }
  38. })
  39. return results
  40. }