You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
			
				
					70 lines
				
				1.5 KiB
			
		
		
			
		
	
	
					70 lines
				
				1.5 KiB
			| 
								 
											4 years ago
										 
									 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * Topological sorting function
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param {Array} edges
							 | 
						||
| 
								 | 
							
								 * @returns {Array}
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								module.exports = function(edges){
							 | 
						||
| 
								 | 
							
								  return toposort(uniqueNodes(edges), edges)
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								module.exports.array = toposort
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function toposort(nodes, edges) {
							 | 
						||
| 
								 | 
							
								  var cursor = nodes.length
							 | 
						||
| 
								 | 
							
								    , sorted = new Array(cursor)
							 | 
						||
| 
								 | 
							
								    , visited = {}
							 | 
						||
| 
								 | 
							
								    , i = cursor
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  while (i--) {
							 | 
						||
| 
								 | 
							
								    if (!visited[i]) visit(nodes[i], i, [])
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return sorted
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  function visit(node, i, predecessors) {
							 | 
						||
| 
								 | 
							
								    if(predecessors.indexOf(node) >= 0) {
							 | 
						||
| 
								 | 
							
								      var nodeRep 
							 | 
						||
| 
								 | 
							
								      try {
							 | 
						||
| 
								 | 
							
								        nodeRep = ", node was:" + JSON.stringify(node)
							 | 
						||
| 
								 | 
							
								      } catch(e) {
							 | 
						||
| 
								 | 
							
								        nodeRep = ""
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      throw new Error('Cyclic dependency' + nodeRep)
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (!~nodes.indexOf(node)) {
							 | 
						||
| 
								 | 
							
								      throw new Error('Found unknown node. Make sure to provided all involved nodes. Unknown node: '+JSON.stringify(node))
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (visited[i]) return;
							 | 
						||
| 
								 | 
							
								    visited[i] = true
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // outgoing edges
							 | 
						||
| 
								 | 
							
								    var outgoing = edges.filter(function(edge){
							 | 
						||
| 
								 | 
							
								      return edge[0] === node
							 | 
						||
| 
								 | 
							
								    })
							 | 
						||
| 
								 | 
							
								    if (i = outgoing.length) {
							 | 
						||
| 
								 | 
							
								      var preds = predecessors.concat(node)
							 | 
						||
| 
								 | 
							
								      do {
							 | 
						||
| 
								 | 
							
								        var child = outgoing[--i][1]
							 | 
						||
| 
								 | 
							
								        visit(child, nodes.indexOf(child), preds)
							 | 
						||
| 
								 | 
							
								      } while (i)
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    sorted[--cursor] = node
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function uniqueNodes(arr){
							 | 
						||
| 
								 | 
							
								  var res = []
							 | 
						||
| 
								 | 
							
								  for (var i = 0, len = arr.length; i < len; i++) {
							 | 
						||
| 
								 | 
							
								    var edge = arr[i]
							 | 
						||
| 
								 | 
							
								    if (res.indexOf(edge[0]) < 0) res.push(edge[0])
							 | 
						||
| 
								 | 
							
								    if (res.indexOf(edge[1]) < 0) res.push(edge[1])
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  return res
							 | 
						||
| 
								 | 
							
								}
							 |