JSPM

  • Created
  • Published
  • Downloads 323065
  • Score
    100M100P100Q220266F
  • License MIT

A graph data structure with topological sort.

Package Exports

  • graph-data-structure

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (graph-data-structure) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

graph-data-structure

A graph data structure with topological sort.

NPM NPM Build Status

This library provides a minimalist implementation of a directed graph data structure. Nodes are represented by unique strings. Internally, an adjacency list is used to represent nodes and edges.

The primary use case for this library is in implementing dataflow programming or reactive programming. The key algorithm necessary for these is topological sorting, to get an ordering of nodes such that for each edge (u -> v), u comes before v in the sorted order. The topological sorting algorithm exposed here has modifications useful for computing the order in which functions in a data flow graph should be executed, namely specifying source nodes for propagation and specifying to exclude the source nodes themselves from the result.

To create a graph instance, invoke Graph as a constructor function.

var graph = Graph();

Add some nodes and edges with addNode and addEdge.

graph.addNode("a");
graph.addNode("b");
graph.addEdge("a", "b");

Nodes are added implicitly when edges are added.

graph.addEdge("b", "c");

Topological sorting can be done by invoking topologicalSort like this.

graph.topologicalSort(); // Returns ["a", "b", "c"]

Here's an example of topological sort with getting dressed (from Cormen et al. "Introduction to Algorithms" page 550).

var graph = Graph();

// Shoes depend on socks.
// Socks need to be put on before shoes.
graph.addEdge("socks", "shoes");

graph.addEdge("shirt", "belt");
graph.addEdge("shirt", "tie");
graph.addEdge("tie", "jacket");
graph.addEdge("belt", "jacket");
graph.addEdge("pants", "shoes");
graph.addEdge("underpants", "pants");
graph.addEdge("pants", "belt");

// prints [ "underpants", "pants", "shirt", "tie", "belt", "jacket", "socks", "shoes" ]
console.log(graph.topologicalSort());

For more detailed example code that shows more methods, have a look at the tests.

Installation

This library is distributed only via NPM. Install by running

npm install graph-data-structure

Require it in your code like this.

var Graph = require("graph-data-structure");

API Reference

Creating a Graph

# Graph([serialized])

Constructs an instance of the graph data structure.

The optional argument serialized is a serialized graph that may have been generated by serialize. If serialized is present, it is deserialized by invoking deserialize.

Adding and Removing Nodes

# graph.addNode(node)

Adds a node to the graph. The argument node is a string identifier that uniquely identifies the node within this graph instance. If a node with the same identifier was already added to the graph, this function does nothing.

# graph.removeNode(node)

Removes the specified node. The argument node is a string identifier for the node to remove. This function also removes all edges connected to the specified node, both incoming and outgoing.

Adding and Removing Edges

# graph.addEdge(u, v)

Adds an edge from node u to node v. The arguments u and v are string identifiers for nodes. This function also adds u and v as nodes if they were not already added.

# graph.removeEdge(u, v)

Removes the edge from node u to node v. The arguments u and v are string identifiers for nodes. This function does not remove the nodes u and v. Does nothing if the edge does not exist.

Querying the Graph

# graph.nodes()

List all nodes in the graph. Returns an array of node identifier strings.

# graph.adjacent(node)

Gets the adjacent node list for the specified node. The argument node is a string identifier for a node. Returns an array of node identifier strings.

The "adjacent node list" is the set of nodes for which there is an incoming edge from the given node. In other words, for all edges (u -> v) where u is the specified node, all values for v are in the adjacent node list.

# graph.serialize()

Serializes the graph. Returns an object with the following properties.

  • nodes An array of node identifier strings.
  • links An array of edge objects with the following properties.
    • source An integer, the index of the source node (u) in the nodes array.
    • target An integer, the index of the target node (v) in the nodes array.

Here's example code for serializing a graph.

var graph = Graph();
graph.addEdge("a", "b");
graph.addEdge("b", "c");
var serialized = graph.serialize();

The following will be the value of serialized.

 {
    "nodes": ["a", "b", "c"],
    "links": [
      { "source": 0, "target": 1 },
      { "source": 1, "target": 2 }
    ]
  }

This representation conforms to the convention of graph representation when working with D3.js force layouts. See also d3.simulation.nodes and d3.forceLinks.

# graph.deserialize(serialized)

Deserializes the given serialized graph. The argument serialized is a graph representation with the structure described in serialize. This function iterates over the serialized graph and adds the nodes and links it represents by invoking addNode and addEdge.

Graph Algorithms

# graph.depthFirstSearch([sourceNodes][, includeSourceNodes])

Performs Depth-first Search. Returns an array of node identifier strings. The returned array includes nodes visited by the algorithm in the order in which they were visited. Implementation inspired by pseudocode from Cormen et al. "Introduction to Algorithms" 3rd Ed. p. 604.

Arguments:

  • sourceNodes (optional) - An array of node identifier strings. This specifies the subset of nodes to use as the sources of the depth-first search. If sourceNodes is not specified, all nodes in the graph are used as source nodes.
  • includeSourceNodes (optional) - A boolean specifying whether or not to include the source nodes in the returned array. If includeSourceNodes is not specified, it is treated as true (all source nodes are included in the returned array).

# graph.topologicalSort([sourceNodes][, includeSourceNodes])

Performs Topological Sort. Returns an array of node identifier strings. The returned array includes nodes in topologically sorted order. This means that for each visited edge (u -> v), u comes before v in the topologically sorted order. Amazingly, this comes from simply reversing the result from depth first search. Inspired by by Cormen et al. "Introduction to Algorithms" 3rd Ed. p. 613.

See depthFirstSearch for documentation of the arguments sourceNodes and includeSourceNodes.