11( function ( exports ) {
2-
32 'use strict' ;
43
5- /**
6- * Breadth-first search algorithm for matrix representation of graph.
7- * The algorithm finds whether there's a path between two given nodes.
8- */
9- var breadthFirstSearch = ( function ( ) {
10-
11- var visited = [ ] ,
12- queue = [ ] ,
13- target ,
14- graph ;
15-
16- /**
17- * Initializes the algorithm
18- *
19- * @private
20- * @param {array } inputGraph The input matrix of the graph
21- * @param {array } destination The destination
22- */
23- function init ( inputGraph , destination ) {
24- graph = inputGraph ;
25- target = destination ;
26- queue = [ ] ;
27- visited = { } ;
28- }
29-
30- /**
31- * Adds a valid node to the queue
32- * @param {array } node Node to be added to the queue
33- */
34- function addNode ( node ) {
35- if ( visited [ node ] ||
36- node [ 0 ] < 0 || node [ 1 ] < 0 ||
37- node [ 0 ] >= graph . length || node [ 1 ] >= graph [ 0 ] . length ||
38- ! graph [ node [ 0 ] ] [ node [ 1 ] ] ) {
39- return ;
40- }
41- queue . push ( node ) ;
42- }
43-
44- /**
45- * Process given node
46- *
47- * @param {array } destination The destionation, which should be reached
48- * @param {array } current The current node
49- */
50- function processNode ( destination , current ) {
51- if ( destination . toString ( ) === current . toString ( ) ) {
52- return true ;
53- } else {
54- addNode ( [ current [ 0 ] , current [ 1 ] + 1 ] ) ;
55- addNode ( [ current [ 0 ] , current [ 1 ] - 1 ] ) ;
56- addNode ( [ current [ 0 ] + 1 , current [ 1 ] ] ) ;
57- addNode ( [ current [ 0 ] - 1 , current [ 1 ] ] ) ;
58- return false ;
59- }
60- }
4+ var bfs = ( function ( ) {
615
62- /**
63- * Validates the params
64- *
65- * @param {array } graph A matrix representation of the graph
66- * @param {array } source The source node
67- * @param {array } destination The destination node
68- */
69- function validateParams ( graph , source , destination ) {
70- if ( ! graph ) {
71- throw new Error ( 'The graph should be represented as a matrix' ) ;
6+ function buildPath ( parents , targetNode ) {
7+ var result = [ targetNode ] ;
8+ while ( parents [ targetNode ] !== null ) {
9+ targetNode = parents [ targetNode ] ;
10+ result . push ( targetNode ) ;
7211 }
73- if ( graph [ 0 ] === undefined ) {
74- throw new Error ( 'The graph should be represented as ' +
75- 'a matrix, with size at least 1x1' ) ;
76- }
77- var width = graph [ 0 ] . length ;
78- for ( var i = 1 ; i < graph . length ; i += 1 ) {
79- if ( graph [ i ] . length !== width ) {
80- throw new Error ( 'The graph should be represented as a matrix' ) ;
81- }
82- }
83- source . concat ( destination ) . filter ( function ( c , i ) {
84- if ( c < 0 ) {
85- throw new Error ( 'The source and destination coordinates ' +
86- 'should be above zero' ) ;
87- }
88- if ( i % 2 === 0 ) {
89- if ( c >= graph . length ) {
90- throw new Error ( 'The source and destination coordinates ' +
91- 'should not be above graph\'s size' ) ;
92- }
93- } else {
94- if ( c >= graph [ 0 ] . length ) {
95- throw new Error ( 'The source and destination coordinates ' +
96- 'should not be above graph\'s size' ) ;
97- }
98- }
99- } ) ;
100- return true ;
12+ return result . reverse ( ) ;
10113 }
10214
10315 /**
104- * Finds whether there's a path between a given start node
105- * to given destination
16+ * Returns the shortest path between
17+ * startNode and targetNode.
18+ * Time complexity O(|V|*|V|), because we use adjust matrix.
10619 *
107- * @public
108- * @param {array } graph A matrix representation of the graph
109- * @param {array } source The source node
110- * @param {array } destination The destination node
111- * @returns {boolean } true/false depending whether there's
112- * a path between the nodes
20+ * @param {array } graph The adjust matrix, which represents the graph
21+ * @param {number } startNode The start node
22+ * @param {number } targetNode The target, which should be reached
23+ * @returns {array } The shortest path from startNode to targetNode
11324 */
114- return function ( graph , source , destination ) {
115- validateParams ( graph , source , destination ) ;
116- init ( graph , destination ) ;
117- var current ;
118- queue . push ( source ) ;
119- while ( queue . length > 0 ) {
25+ return function ( graph , startNode , targetNode ) {
26+ var parents = [ ] ,
27+ queue = [ ] ,
28+ visited = [ ] ,
29+ current ;
30+ queue . push ( startNode ) ;
31+ parents [ startNode ] = null ;
32+ visited [ startNode ] = true ;
33+ while ( queue . length ) {
12034 current = queue . shift ( ) ;
121- visited [ current ] = true ;
122- if ( graph [ current [ 0 ] ] [ current [ 1 ] ] ) {
123- var result = processNode ( destination , current ) ;
124- if ( result ) {
125- return true ;
35+ if ( current === targetNode ) {
36+ return buildPath ( parents , targetNode ) ;
37+ }
38+ for ( var i = 0 ; i < graph . length ; i += 1 ) {
39+ if ( i !== current && graph [ current ] [ i ] && ! visited [ i ] ) {
40+ parents [ i ] = current ;
41+ visited [ i ] = true ;
42+ queue . push ( i ) ;
12643 }
12744 }
12845 }
129- visited = null ;
130- queue = null ;
131- target = - 1 ;
132- graph = null ;
133- return false ;
46+ return null ;
13447 } ;
13548 } ( ) ) ;
13649
137- exports . breadthFirstSearch = breadthFirstSearch ;
50+ exports . bfs = bfs ;
51+
52+ } ( ( typeof window === 'undefined' ) ? module . exports : window ) ) ;
13853
139- } ( typeof exports === 'undefined' ? window : exports ) ) ;
54+ console . log ( exports . bfs (
55+ [ [ 0 , 0 , 0 , 0 , 1 ] ,
56+ [ 0 , 0 , 0 , 1 , 0 ] ,
57+ [ 0 , 0 , 0 , 0 , 0 ] ,
58+ [ 1 , 0 , 1 , 0 , 0 ] ,
59+ [ 0 , 1 , 0 , 1 , 0 ] ] , 0 , 2 ) ) ;
0 commit comments