Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 68 additions & 0 deletions Graphs/BidirectionalSearch.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
Bidirectional search is a graph search algorithm that finds a shortest path from an initial vertex to a goal vertex in a directed graph.
It runs two simultaneous searches: one forward from the initial state, and one backward from the goal, stopping when the two meet.
The reason for this approach is that in many cases it is faster: for instance, in a simplified model of search problem complexity in which both searches expand a tree with branching factor b, and the distance from start to goal is d, each of the two searches has complexity O(b^(d/2)),
and the sum of these two search times is much less than the O(b^d) complexity that would result from a single search from the beginning to the goal.

Reference:
https://en.wikipedia.org/wiki/Bidirectional_search
*/


class BidirectionalSearch {
constructor() {
this.adjList = new Map();
}

addVertex(vertex) {
if (!this.adjList.has(vertex)) {
this.adjList.set(vertex, []);
}
}

addEdge(vertex1, vertex2) {
this.adjList.get(vertex1).push(vertex2);
this.adjList.get(vertex2).push(vertex1);
}

bidirectionalSearch(startVertex, endVertex) {
if (!this.adjList.has(startVertex) || !this.adjList.has(endVertex)) {
return null; // One of the vertices is not in the graph
}

const visitedStart = new Set();
const visitedEnd = new Set();
const queueStart = [startVertex];
const queueEnd = [endVertex];

visitedStart.add(startVertex);
visitedEnd.add(endVertex);

while (queueStart.length > 0 && queueEnd.length > 0) {
const currentStart = queueStart.shift();
const currentEnd = queueEnd.shift();

if (visitedEnd.has(currentStart) || visitedStart.has(currentEnd)) {
return true; // There is a path between the two vertices
}

for (const neighbor of this.adjList.get(currentStart) || []) {
if (!visitedStart.has(neighbor)) {
visitedStart.add(neighbor);
queueStart.push(neighbor);
}
}

for (const neighbor of this.adjList.get(currentEnd) || []) {
if (!visitedEnd.has(neighbor)) {
visitedEnd.add(neighbor);
queueEnd.push(neighbor);
}
}
}

return false; // No path found between the two vertices
}
}

module.exports = BidirectionalSearch;
30 changes: 30 additions & 0 deletions Graphs/test/BidirectionalSearch.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import BidirectionalSearch from "../BidirectionalSearch";

describe('Bidirectional Search', () => {
it('should find a path between two connected vertices', () => {
const graph = new BidirectionalSearch();
graph.addVertex('A');
graph.addVertex('B');
graph.addEdge('A', 'B');

expect(graph.bidirectionalSearch('A', 'B')).toBe(true);
});

it('should not find a path between two unconnected vertices', () => {
const graph = new BidirectionalSearch();
graph.addVertex('A');
graph.addVertex('B');
graph.addVertex('C');
graph.addEdge('A', 'B');

expect(graph.bidirectionalSearch('A', 'C')).toBe(false);
});

it('should handle missing vertices gracefully', () => {
const graph = new BidirectionalSearch();
graph.addVertex('A');
graph.addVertex('B');

expect(graph.bidirectionalSearch('A', 'C')).toBe(null);
});
});