topoSort.js 1.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243
  1. exports = function(edges) {
  2. return sort(uniqueNodes(edges), edges);
  3. };
  4. function uniqueNodes(arr) {
  5. var ret = [];
  6. for (var i = 0, len = arr.length; i < len; i++) {
  7. var edge = arr[i];
  8. if (ret.indexOf(edge[0]) < 0) ret.push(edge[0]);
  9. if (ret.indexOf(edge[1]) < 0) ret.push(edge[1]);
  10. }
  11. return ret;
  12. }
  13. function sort(nodes, edges) {
  14. var cursor = nodes.length;
  15. var sorted = new Array(cursor);
  16. var visited = {};
  17. var i = cursor;
  18. while (i--) {
  19. if (!visited[i]) visit(nodes[i], i, []);
  20. }
  21. function visit(node, i, predecessors) {
  22. if (predecessors.indexOf(node) >= 0) {
  23. throw new Error('Cyclic dependency: ' + JSON.stringify(node));
  24. }
  25. if (visited[i]) return;
  26. visited[i] = true;
  27. var outgoing = edges.filter(function(edge) {
  28. return edge[0] === node;
  29. });
  30. if ((i = outgoing.length)) {
  31. var preds = predecessors.concat(node);
  32. do {
  33. var child = outgoing[--i][1];
  34. visit(child, nodes.indexOf(child), preds);
  35. } while (i);
  36. }
  37. sorted[--cursor] = node;
  38. }
  39. return sorted;
  40. }
  41. module.exports = exports;