diff --git a/README.md b/README.md index 153f9ca..f9f2f84 100644 --- a/README.md +++ b/README.md @@ -1 +1,2 @@ # Algorithms +this is an algorithm diff --git a/breadthFirstSearch.js b/breadthFirstSearch.js new file mode 100644 index 0000000..4309754 --- /dev/null +++ b/breadthFirstSearch.js @@ -0,0 +1,55 @@ +import Queue from '../../../data-structures/queue/Queue'; + +function initCallbacks(callbacks = {}) { + const initiatedCallback = callbacks; + + const stubCallback = () => {}; + + const allowTraversalCallback = ( + () => { + const seen = {}; + return ({ nextVertex }) => { + if (!seen[nextVertex.getKey()]) { + seen[nextVertex.getKey()] = true; + return true; + } + return false; + }; + } + )(); + + initiatedCallback.allowTraversal = callbacks.allowTraversal || allowTraversalCallback; + initiatedCallback.enterVertex = callbacks.enterVertex || stubCallback; + initiatedCallback.leaveVertex = callbacks.leaveVertex || stubCallback; + + return initiatedCallback; +} + + +export default function breadthFirstSearch(graph, startVertex, originalCallbacks) { + const callbacks = initCallbacks(originalCallbacks); + const vertexQueue = new Queue(); + + // Do initial queue setup. + vertexQueue.enqueue(startVertex); + + let previousVertex = null; + + // Traverse all vertices from the queue. + while (!vertexQueue.isEmpty()) { + const currentVertex = vertexQueue.dequeue(); + callbacks.enterVertex({ currentVertex, previousVertex }); + + // Add all neighbors to the queue for future traversals. + graph.getNeighbors(currentVertex).forEach((nextVertex) => { + if (callbacks.allowTraversal({ previousVertex, currentVertex, nextVertex })) { + vertexQueue.enqueue(nextVertex); + } + }); + + callbacks.leaveVertex({ currentVertex, previousVertex }); + + // Memorize current vertex before next loop. + previousVertex = currentVertex; + } +}