Skip to content

Commit a03e327

Browse files
committed
Update bfs
1 parent c4608a4 commit a03e327

File tree

1 file changed

+41
-121
lines changed

1 file changed

+41
-121
lines changed

src/graphs/searching/bfs.js

Lines changed: 41 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -1,139 +1,59 @@
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

Comments
 (0)