1.0.15 • Published 6 years ago

traversals v1.0.15

Weekly downloads
26
License
MIT
Repository
github
Last release
6 years ago

traversals

Coveralls Status Build Status Dependency Status npm version License Known Vulnerabilities david-dm

Small module for graph traversals, supporting DFS and BFS with niceties added for pre- and post-order, including their reverses.

Install

npm i traversals

Usage

const 
    { DFS, BFS } = require( 'traversals' ),
    someGraph = testGraph          = [
                        [ 1, 8 ],    // start
                        [ 2, 3 ],    // a
                        [ 3 ],       // b
                        [ 4, 5 ],    // c
                        [ 6 ],       // d
                        [ 6 ],       // e
                        [ 7, 2 ],    // f
                        [ 8 ],       // g
                        []           // end
                    ];

const { preOrder, postOrder } = DFS( someGraph );

// Output the nodes in pre-order
preOrder.forEach( pre => console.log( `We saw node at index ${pre}` ) );

// ...alternatively, use a callbacks. You can use some, all, or none of these.

function record_any_edge( from, to, type )
{
    console.log( `We have an edge from ${from} to ${to} with type "${type}"` );
}

// Use the function as an object. Normally, you would need these
// individually typed callbacks. But, for the sake of completeness...
record_any_edge.tree = ( from, to ) => console.log( `tree edge from ${from} to ${to}` ); 
record_any_edge.forward = ( from, to ) => console.log( `forward edge from ${from} to ${to}` ); 
record_any_edge.back = ( from, to ) => console.log( `back edge from ${from} to ${to}` ); 
record_any_edge.cross = ( from, to ) => console.log( `cross edge from ${from} to ${to}` ); 

DFS( someGraph, { 
    pre( n ) { console.log( `pre-order: ${n}` ); }, 
    post( n ) { console.log( `post-order: ${n}` ); }, 
    rpre( n ) { console.log( `reverse pre-order: ${n}` ); }, 
    rpost( n ) { console.log( `reverse post-order: ${n}` ); },
    edge: record_any_edge
} );

// Or, if you just wanted, say, tree edges...

DFS( someGraph, { edge: { tree: ( from, to ) => console.log( `tree from ${from} to ${to}` ) } } );

// The BFS is much the same, except you get levels back but no post-order. Both have pre-order.
// BFS also has no forward edges.

For quick and easy traversals, when you just want to be called in once per node in a particular order, you can use the function shown below. The following shows various uses of the pre-order walk. The other three walks work in an identical manner.

const
    { preOrder } = require( 'traversals' ); // The other 3 functions
                                                // are: postOrder, 
                                                // rPreOrdder, and
                                                // rPostOrder

// For all of these walks, you can abort it at any stage by returning
// or calling the third argument. In the first example, however, we
// just run allthe way through.

preOrder( testGraph, ( nodeNum, preNum ) => {
    // preNum just goes from 0 to N - 1
    console.log( `Node index: ${nodeNum}, pre-order index: ${preNum}` );
} );

// In this case, we stop the walk and return a result, in this case, the
// returnValue will be 3
let returnValue = preOrder( testGraph, ( nodeNum, index, kill ) => {
    console.log( `Node index: ${nodeNum}, pre-order index: ${preNum}` );
    // Return kill to stop the walk, here we stop on node index 3
    return nodeNum === 3 && kill;
} );

const preSeq = [];

// Return value here will be 4
returnValue = preOrder( testGraph, ( nodeNum, index, kill ) => {
    // Create a list of node indices in pre-order
    preSeq.push( nodeNum );
    // When we reach node index 4, call kill to stop the walk
    nodeNum === 4 && kill();
}, 0 );

let prev, 
    nodeJustBeforeThis = 3;

// Here we stop the walk with an arbitrary value of our own choosing
// again by calling the kill function with the value.
returnValue = preOrder( testGraph, ( nodeNum, index, kill ) => {
    nodeNum === nodeJustBeforeThis && kill( prev );
    prev = nodeNum;
} );

API

Functions

Typedefs

DFS(list, opts) ⇒ DFSTraversalResult

A more involved traversal that's not as efficient as the simple walkers but provide more information. You can use this to generate pre-order, post-order (and their reverses) sequences, as well as edge information, all in a single pass.

It does not provide levels which you need to get from the BFS traversal.

Kind: global function

ParamType
listArray.<Array.<number>> | TraversalOptions
optsTraversalOptions

BFS(list, opts) ⇒ BFSTraversalResult

Much the same as the DFS function, it provides the same information and capabilities with a few exceptions.

  1. It does not provide forward edge information.
  2. It does not generate a post-order walk.

It does, however, provides levels.

Kind: global function

ParamType
listArray.<Array.<number>> | TraversalOptions
optsTraversalOptions

preOrder(nodes, fn, root)

Call this with the node list and a callback function. If the graph does not start at index 0 then add the actual start index as the third argument.

Kind: global function

ParamTypeDefault
nodesArray.<Array.<number>>
fnSimpleWalkerCallback
rootnumber0

postOrder(nodes, fn, root)

Call this with the node list and a callback function. If the graph does not start at index 0 then add the actual start index as the third argument.

Kind: global function

ParamTypeDefault
nodesArray.<Array.<number>>
fnSimpleWalkerCallback
rootnumber0

rPreOrder(nodes, fn, root)

Call this with the node list and a callback function. If the graph does not start at index 0 then add the actual start index as the third argument.

Kind: global function

ParamTypeDefault
nodesArray.<Array.<number>>
fnSimpleWalkerCallback
rootnumber0

rPostOrder(nodes, fn, root)

Call this with the node list and a callback function. If the graph does not start at index 0 then add the actual start index as the third argument.

Kind: global function

ParamTypeDefault
nodesArray.<Array.<number>>
fnSimpleWalkerCallback
rootnumber0

TraversalOptions : object

Kind: global typedef
Properties

NameTypeDefaultDescription
nodesArray.<Array.<number>>Optionally, you can put your array of nodes here
startIndexnumber0Where to start, defaults to zero
preNodeWalkerCallbackCallback in pre-order
postNodeWalkerCallbackCallback in post-order
rpreNodeWalkerCallbackCallback in reverse pre-order
rpostNodeWalkerCallbackCallback in reverse post-order
edgeEdgeCBCallback for every edge or each type, see EdgeCB below
spanningTreebooleantrueA strongly connected graph with all nodes reachable from a common root
flatbooleanfalseUse an iterative walker, not recursive
excludeRootbooleanfalseDo not invoke a callback for the root node
preOrderbooleantrueReturn an array of node indices in pre-order
postOrderbooleantrueReturn an array of node indices in post-order
rPreOrderbooleanfalseReturn an array of node indices in reverse pre-order
rPostOrderbooleanfalseReturn an array of node indices in reverse post-order
edgesbooleantrueReturn edge information in the results object
trustedbooleanfalseSet trusted to true if you know your input is valid, i.e. an array where each element is either a number or an array of numbers.

EdgeCB : EdgeCallback | Object

You can define the edge field as a normal function and it will be called on each discovered edge with the from and to node numbers, as well as the edge type. Alternatively, yuou can also just set the field to an object.

The function or object can have four optional fields, one for each edge type. These will be called on the discovery of their respective types. If you added these fields to a function, the main function will be called, in addition to these.

Kind: global typedef
Properties

NameTypeDescription
treeEdgeTypeCallbackCallback for each tree edge
forwardEdgeTypeCallbackCallback for each forward edge (not applicable for BFS)
backEdgeTypeCallbackCallback for each back edge
crossEdgeTypeCallbackCallback for each cross edge

Example

// For each backedge
DFS( nodes, {
    edge: { back: ( from, to ) => console.log( `back edge from ${from} to ${to}` )
    // ...
} );

Example

// For all edges and one just for tree edges
function everyEdge( from, to, type )
{
    console.log( `Discovered ${type} edge from ${from} to ${to}` );
}

everyEdge.tree = ( from, to ) => console.log( `Discovered a tree edge from ${from} to ${to}` );

DFS( nodes, {
    edge: everyEdge
    // ...
} );

DFSTraversalResult : object

Kind: global typedef
Properties

NameType
preOrderArray.<number>
postOrderArray.<number>
rPreOrderArray.<number>
rPostOrderArray.<number>
edgesDFSEdges

BFSTraversalResult : object

Kind: global typedef
Properties

NameType
preOrderArray.<number>
rPreOrderArray.<number>
levelsArray.<number>
edgesBFSEdges

SimpleWalkerCallback

Kind: global typedef

ParamTypeDescription
nodeIndexnumberThe index of the node input the input array
orderedIndexnumberThe index into the ordered walk, goes from 0 to N - 1
killfunctionReturn this or call it, with or without a value, to stop the walk

NodeWalkerCallback

Kind: global typedef

ParamTypeDescription
nodeIndexnumberThe index of the node in the original input array
orderedIndexnumberThe sequence number of the node in order, goes 0 to N - 1
orderedSequenceArray.<number>The entire ordered sequence

EdgeTypeCallback

Kind: global typedef
Properties

NameType
fromnumber
tonumber

EdgeCallback

Kind: global typedef

ParamType
fromnumber
tonumber
typestring
1.0.15

6 years ago

1.0.14

6 years ago

1.0.13

6 years ago

1.0.12

6 years ago

1.0.11

6 years ago

1.0.9

6 years ago

1.0.8

6 years ago

1.0.7

6 years ago

1.0.6

6 years ago

1.0.5

6 years ago

1.0.4

6 years ago

1.0.3

6 years ago

1.0.2

6 years ago

1.0.1

6 years ago

1.0.0

6 years ago