Skip to content

Commit

Permalink
Implement Breadth-first Search (#45)
Browse files Browse the repository at this point in the history
* Fix Queue implementation

* Add Breadth-first Search implementation
  • Loading branch information
yangshun authored Mar 4, 2018
1 parent 2b0b550 commit 30bc873
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 1 deletion.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ Data Structures and Algorithms library for JavaScript. Pretty much still WIP but
- [Heap Sort](lib/algorithms/heapSort.js)
- Timsort (TODO)
- Topological Sort (TODO)
- Breadth First Search (TODO)
- [Breadth-first Search](lib/algorithms/breadthFirstSearch.js)
- Depth First Search (TODO)
- Djikstra's Algorithm (TODO)
- Bellman-Ford Algorithm (TODO)
Expand Down
75 changes: 75 additions & 0 deletions lib/algorithms/__tests__/breadthFirstSearch.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import breadthFirstSearch from '../breadthFirstSearch';

describe('breadthFirstSearch', () => {
test('empty graph', () => {
expect(breadthFirstSearch({}, null)).toEqual([]);
});

test('graphs with one node', () => {
expect(breadthFirstSearch({ 1: [] }, 1)).toEqual([1]);
expect(breadthFirstSearch({ 1: [1] }, 1)).toEqual([1]);
});

test('graphs with two nodes', () => {
expect(breadthFirstSearch({ 1: [2], 2: [] }, 1)).toEqual([1, 2]);
expect(breadthFirstSearch({ 1: [1, 2], 2: [] }, 1)).toEqual([1, 2]);
expect(breadthFirstSearch({ 1: [1, 2], 2: [] }, 2)).toEqual([2]);
expect(breadthFirstSearch({ 1: [1, 2], 2: [1] }, 2)).toEqual([2, 1]);
});

test('graphs with multiple nodes', () => {
expect(breadthFirstSearch({ 1: [2], 2: [3], 3: [] }, 1)).toEqual([1, 2, 3]);
expect(breadthFirstSearch({ 1: [2, 3], 2: [], 3: [] }, 1)).toEqual([
1,
2,
3,
]);
expect(
breadthFirstSearch({ 1: [2, 3], 2: [], 3: [], 4: [2], 5: [3] }, 1),
).toEqual([1, 2, 3]);
expect(
breadthFirstSearch({ 1: [4, 5], 2: [], 3: [], 4: [2], 5: [3] }, 1),
).toEqual([1, 4, 5, 2, 3]);
expect(
breadthFirstSearch(
{ 1: [4, 5], 2: [1, 2, 3, 4, 5], 3: [], 4: [2], 5: [3] },
1,
),
).toEqual([1, 4, 5, 2, 3]);
expect(
breadthFirstSearch(
{ 1: [1, 2, 3, 4, 5], 2: [], 3: [], 4: [2], 5: [3] },
1,
),
).toEqual([1, 2, 3, 4, 5]);
// Graph taken from https://www.geeksforgeeks.org/breadth-first-traversal-for-a-graph/
const graph = {
1: [2, 3],
2: [1, 4, 5],
3: [1, 5],
4: [2, 5, 6],
5: [2, 3, 4, 6],
6: [4, 5],
};
expect(breadthFirstSearch(graph, 1)).toEqual([1, 2, 3, 4, 5, 6]);
expect(breadthFirstSearch(graph, 2)).toEqual([2, 1, 4, 5, 3, 6]);
expect(breadthFirstSearch(graph, 3)).toEqual([3, 1, 5, 2, 4, 6]);
expect(breadthFirstSearch(graph, 4)).toEqual([4, 2, 5, 6, 1, 3]);
expect(breadthFirstSearch(graph, 5)).toEqual([5, 2, 3, 4, 6, 1]);
expect(breadthFirstSearch(graph, 6)).toEqual([6, 4, 5, 2, 3, 1]);
});

test('disjoint graphs', () => {
expect(breadthFirstSearch({ 1: [2], 2: [], 3: [], 4: [3] }, 1)).toEqual([
1,
2,
]);
expect(breadthFirstSearch({ 1: [2], 2: [], 3: [], 4: [3] }, 3)).toEqual([
3,
]);
expect(breadthFirstSearch({ 1: [2], 2: [], 3: [], 4: [3] }, 4)).toEqual([
4,
3,
]);
});
});
30 changes: 30 additions & 0 deletions lib/algorithms/breadthFirstSearch.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/**
* Performs a breadth-first search on a graph given a starting node.
* @param {Object} graph Node to array of neighboring nodes.
* @param {number} source Source node to start traversal from. It has to exist as a node in the graph.
* @return {number[]} A BFS-traversed order of nodes.
*/
import { Queue } from '../';

function breadthFirstSearch(graph, source) {
if (Object.keys(graph).length === 0) {
return [];
}
let queue = new Queue();
queue.enqueue(source);
const visited = new Set([source]);
while (!queue.isEmpty()) {
const node = queue.dequeue();
visited.add(node);
graph[node].forEach(neighbor => {
if (visited.has(neighbor)) {
return;
}
queue.enqueue(neighbor);
});
}

return Array.from(visited);
}

export default breadthFirstSearch;
2 changes: 2 additions & 0 deletions lib/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// Algorithms
import binarySearch from './algorithms/binarySearch';
import breadthFirstSearch from './algorithms/breadthFirstSearch';
import heapSort from './algorithms/heapSort';
import mergeSort from './algorithms/mergeSort';
import quickSelect from './algorithms/quickSelect';
Expand All @@ -17,6 +18,7 @@ import Trie from './data-structures/Trie';
export {
// Algorithms
binarySearch,
breadthFirstSearch,
heapSort,
mergeSort,
quickSelect,
Expand Down

0 comments on commit 30bc873

Please sign in to comment.