Security News
Oracle Drags Its Feet in the JavaScript Trademark Dispute
Oracle seeks to dismiss fraud claims in the JavaScript trademark dispute, delaying the case and avoiding questions about its right to the name.
graphs-for-js
Advanced tools
Some JavaScript and TypeScript implementation of a graph data structure. Features: - Insert and remove nodes. - Connect and disconnect nodes. - Algorithms for graph structures.
Implementations of graph data structures for JavaScript and TypeScript
Features:
- Insert and remove nodes.
- Create edges by connecting and disconnecting nodes.
- Algorithms for graph data structures.
Table of contents generated with markdown-toc
$ npm install --save graphs-for-js
Import the Graph
class to initialize a graph.
The library supports 4 types of graphs:
For each of the above graph types, there are also readonly, immutable versions.
// With require()
const {Graph} = require('graphs-for-js')
// With import syntax
import {Graph} from 'graphs-for-js'
Because JavaScript does not natively hash/map objects and their contents to unique values as object keys, the GraphBuilder accepts a function for mapping a node value to a string key.
If a Key Function is not given, then the default behaviors on node values are the following:
{a: 32, b: 23}
is mapped as '{a:32,b:23}'
toString()
, normally '[object Object]'
const weightedGraph = new Graph()
.keyFn(i => `${i}`).directed.weighted()
const unweightedGraph = new Graph()
.noKey().directed.unweighted()
Use the type parameters to specify the type of the nodes and of the edge values (if weighted).
const weightedGraph = new Graph<string, number>()
.noKey().directed.weighted()
const unweightedGraph = new Graph<string>()
.noKey().directed.unweighted()
You can also initiate a readonly graph which cannot be modified.
const weightedGraph = new Graph<number, number>()
.noKey().readonly.directed
.weighted([[1, 2, 5], [2, 3, 6]])
// Specify edges and implicitly the nodes
const unweightedGraph = new Graph<number>()
.noKey().readonly.directed
.unweighted([], [2, 3, 4, 5])
// No edges, followed by an array of extra nodes.
For the following examples, assume the nodes of graph
are numbers.
The examples show the differences among each type of graph when necessary.
graph.insert(0) // Insert a single node
graph.insert(1, 2, 3) // Insert multiple nodes
const result = graph.insert(...[4,5,6,7]) // Use spread syntax for array inputs
console.log(result) // The number of nodes inserted
graph.remove(0) // Remove a single node
graph.remove(1, 2, 3) // Removes multiple nodes
const result = graph.remove(...[4,5,6,7]) // Use spread syntax for array inputs
console.log(result) // The number of nodes removed
graph.count()
unweightedGraph.connect(1, 2) // Creates an edge from node 1 to node 2
weightedGraph.connect(1, 2, 0.5) // Creates an edge from node 1 to node 2 with weight 0.5
unweightedGraph.disconnect(1, 2) // Removes the edge from node 1 to node 2
weightedGraph.disconnect(1, 2) // Removes the edge from node 1 to node 2
weightedGraph.disconnect(1, 2, 0.5) // Removes the edge from node 1 to node 2 only if the weight of that edge is 0.5
undirectedGraph.connect(1, 2)
undirectedGraph.disconnect(2, 1) // Will remove the edge from node 1 to node 2 in a unweighted graph.
graph.nodes() // Returns an array of node values
graph.edges() // Returns an array of edges
/*
type Edge<V, E> = {
source: V,
target: V,
value: E,
undirected: boolean
}
*/
graph.outgoingEdgesOf(2) // Returns an array of edges whose source nodes are node 2
graph.incomingEdgesOf(2) // Returns an array of edges whose target nodes are node 2
graph.degreeOf(2) // Degree of node 2
graph.inDegreeOf(2) // In-Degree of node 2
graph.outDegreeOf(2) // Out-Degree of node 2
graph.contains(1) // Contains node 1
graph.contains(1, 2, 3) // Contains all three nodes
unweightedGraph.hasEdge(1, 2) // Has edge from node 1 to node 2
weightedGraph.hasEdge(1, 2) // Has edge from node 1 to node 2
weightedGraph.hasEdge(1, 2, 0.5) // Returns true if there is an edge from node 1 to node 2 AND edge value is 0.5
undirectedGraph.hasEdge(x, y) === undirectedGraph.hasEdge(y, x) // true
weightedGraph.weightOf(1, 4)
// Returns the value of the edge from nodes 1 to 4, if it exists.
// If it does not exist, it returns undefined.
The GraphUtil
module contains some helper functions/algorithms that can be used on the graphs.
hasCycle(graph)
findShortestPath(graph, start, end)
start
to the node end
. Returns an object with the fields path
and pathLength
. If there exists a path, then path
is an array of nodes in that path in order from start
to end
, and pathLength
is the length of that path, i.e. the number of edges. If a path is not found, then path
is an empty array, and pathLength
is -1
.clone(graph)
graph
. The type of graph returned is the same type of graph given, e.g. if an undirected, unweighted graph is given, then the cloned graph will also be undirected and unweighted.topologicalSort(graph)
undefined
if the given graph is not a DAG. Otherwise, it returns an array of nodes in topologically sorted order.toAdjacencyMatrix(graph)
graph
into an adjacency matrix. Returns an object with 5 values:type Result<V, E> = {
// matrix[i][j] is true if there is an edge from node i to node j. Otherwise, it is false
matrix: boolean[][]
// valueMatrix[i][j] returns the value/weight on the edge from node i to j.
// If there is no value or the edge does not exist, it is undefined.
valueMatrix: (E | undefined)[][]
// For each node n, nodeToIndex maps toKeyFn(n) to its index on the adjacency matrix
nodeToIndex: Record<string, number>
// Maps the index number on the adjacency matrix to the actual node value.
indexToNode: V[]
// An array of pairs, the node value and its index on the adjacency matrix.
nodeIndexPairs: {node: V, index: number}[]
}
functional
utility functions:
subset(graph, nodes)
nodes
.subset
is the same as the return type for clone
.mapNodes(graph, callback, newKeyFn?)
callback
function on each node in the given graph
.newKeyFn
or the default key function if not given.mapEdges(graph, callback)
callback
function on each edge value in the given graph
.serialize
utility functions:
stringify(graph)
parse(json)
const {Graph, GraphUtil} = require('graphs-for-js')
const graph = new Graph().noKey().directed.unweighted()
// Returns true if there exists a cycle in `graph`. Otherwise false
GraphUtil.hasCycle(graph)
/*
Finds the shortest path from the start node to the end node.
Where V is the type of the node
return type: {
path: Array<V> // The nodes in the discovered path. If no path is found, then this array is empty.
pathLength: number // The number of edges in the discovered path. If no path is found, then this is -1.
}
*/
GraphUtil.findShortestPath(graph, 1, 2)
Feel free to contribute by adding changes to the graph implementation or by writing implementations for graph algorithms in GraphUtil
! You can also add suggestions or issues here
If you'd like to make changes to the graph implementation or for GraphUtil
:
Fork this repository
Create a feature branch
Make changes 🛠
Make a PR to merge into this repo
ISC © Anthony Yang
FAQs
Some JavaScript and TypeScript implementation of a graph data structure. Features: - Insert and remove nodes. - Connect and disconnect nodes. - Algorithms for graph structures.
The npm package graphs-for-js receives a total of 0 weekly downloads. As such, graphs-for-js popularity was classified as not popular.
We found that graphs-for-js demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Oracle seeks to dismiss fraud claims in the JavaScript trademark dispute, delaying the case and avoiding questions about its right to the name.
Security News
The Linux Foundation is warning open source developers that compliance with global sanctions is mandatory, highlighting legal risks and restrictions on contributions.
Security News
Maven Central now validates Sigstore signatures, making it easier for developers to verify the provenance of Java packages.