adding BFS

This commit is contained in:
Pedro Caminha 2019-10-16 10:10:05 -03:00
parent dc1047df72
commit 35d1efa4bf

174
BFS.js Normal file
View File

@ -0,0 +1,174 @@
import Graph from '../../../../data-structures/Graph/Graph';
import GraphVertex from '../../../../data-structures/Graph/GraphVertex';
import GraphEdge from '../../../../data-structures/Graph/GraphEdge';
import breadthFirstSearch from '../breadthFirstSearch';
describe('breadthFirstSearch', () => {
it('should perform BFS operation on Graph', () => {
const Graph = new Graph(true);
const vertexA = new GraphVertex('A');
const vertexB = new GraphVertex('B');
const vertexC = new GraphVertex('C');
const vertexD = new GraphVertex('D');
const vertexE = new GraphVertex('E');
const vertexF = new GraphVertex('F');
const vertexG = new GraphVertex('G');
const vertexH = new GraphVertex('H');
const edgeAB = new GraphEdge(vertexA, vertexB);
const edgeBC = new GraphEdge(vertexB, vertexC);
const edgeCG = new GraphEdge(vertexC, vertexG);
const edgeAD = new GraphEdge(vertexA, vertexD);
const edgeAE = new GraphEdge(vertexA, vertexE);
const edgeEF = new GraphEdge(vertexE, vertexF);
const edgeFD = new GraphEdge(vertexF, vertexD);
const edgeDH = new GraphEdge(vertexD, vertexH);
const edgeGH = new GraphEdge(vertexG, vertexH);
Graph
.addEdge(edgeAB)
.addEdge(edgeBC)
.addEdge(edgeCG)
.addEdge(edgeAD)
.addEdge(edgeAE)
.addEdge(edgeEF)
.addEdge(edgeFD)
.addEdge(edgeDH)
.addEdge(edgeGH);
expect(Graph.toString()).toBe('A,B,C,G,D,E,F,H');
const enterVertexCallback = jest.fn();
const leaveVertexCallback = jest.fn();
// Traverse Graphs without callbacks first.
breadthFirstSearch(Graph, vertexA);
// Traverse Graph with enterVertex and leaveVertex callbacks.
breadthFirstSearch(Graph, vertexA, {
enterVertex: enterVertexCallback,
leaveVertex: leaveVertexCallback,
});
expect(enterVertexCallback).toHaveBeenCalledTimes(8);
expect(leaveVertexCallback).toHaveBeenCalledTimes(8);
const enterVertexParamsMap = [
{ currentVertex: vertexA, previousVertex: null },
{ currentVertex: vertexB, previousVertex: vertexA },
{ currentVertex: vertexD, previousVertex: vertexB },
{ currentVertex: vertexE, previousVertex: vertexD },
{ currentVertex: vertexC, previousVertex: vertexE },
{ currentVertex: vertexH, previousVertex: vertexC },
{ currentVertex: vertexF, previousVertex: vertexH },
{ currentVertex: vertexG, previousVertex: vertexF },
];
for (let callIndex = 0; callIndex < Graph.getAllVertices().length; callIndex += 1) {
const params = enterVertexCallback.mock.calls[callIndex][0];
expect(params.currentVertex).toEqual(enterVertexParamsMap[callIndex].currentVertex);
expect(params.previousVertex).toEqual(enterVertexParamsMap[callIndex].previousVertex);
}
const leaveVertexParamsMap = [
{ currentVertex: vertexA, previousVertex: null },
{ currentVertex: vertexB, previousVertex: vertexA },
{ currentVertex: vertexD, previousVertex: vertexB },
{ currentVertex: vertexE, previousVertex: vertexD },
{ currentVertex: vertexC, previousVertex: vertexE },
{ currentVertex: vertexH, previousVertex: vertexC },
{ currentVertex: vertexF, previousVertex: vertexH },
{ currentVertex: vertexG, previousVertex: vertexF },
];
for (let callIndex = 0; callIndex < Graph.getAllVertices().length; callIndex += 1) {
const params = leaveVertexCallback.mock.calls[callIndex][0];
expect(params.currentVertex).toEqual(leaveVertexParamsMap[callIndex].currentVertex);
expect(params.previousVertex).toEqual(leaveVertexParamsMap[callIndex].previousVertex);
}
});
it('should allow to create custom vertex visiting logic', () => {
const Graph = new Graph(true);
const vertexA = new GraphVertex('A');
const vertexB = new GraphVertex('B');
const vertexC = new GraphVertex('C');
const vertexD = new GraphVertex('D');
const vertexE = new GraphVertex('E');
const vertexF = new GraphVertex('F');
const vertexG = new GraphVertex('G');
const vertexH = new GraphVertex('H');
const edgeAB = new GraphEdge(vertexA, vertexB);
const edgeBC = new GraphEdge(vertexB, vertexC);
const edgeCG = new GraphEdge(vertexC, vertexG);
const edgeAD = new GraphEdge(vertexA, vertexD);
const edgeAE = new GraphEdge(vertexA, vertexE);
const edgeEF = new GraphEdge(vertexE, vertexF);
const edgeFD = new GraphEdge(vertexF, vertexD);
const edgeDH = new GraphEdge(vertexD, vertexH);
const edgeGH = new GraphEdge(vertexG, vertexH);
Graph
.addEdge(edgeAB)
.addEdge(edgeBC)
.addEdge(edgeCG)
.addEdge(edgeAD)
.addEdge(edgeAE)
.addEdge(edgeEF)
.addEdge(edgeFD)
.addEdge(edgeDH)
.addEdge(edgeGH);
expect(Graph.toString()).toBe('A,B,C,G,D,E,F,H');
const enterVertexCallback = jest.fn();
const leaveVertexCallback = jest.fn();
// Traverse Graph with enterVertex and leaveVertex callbacks.
breadthFirstSearch(Graph, vertexA, {
enterVertex: enterVertexCallback,
leaveVertex: leaveVertexCallback,
allowTraversal: ({ currentVertex, nextVertex }) => {
return !(currentVertex === vertexA && nextVertex === vertexB);
},
});
expect(enterVertexCallback).toHaveBeenCalledTimes(7);
expect(leaveVertexCallback).toHaveBeenCalledTimes(7);
const enterVertexParamsMap = [
{ currentVertex: vertexA, previousVertex: null },
{ currentVertex: vertexD, previousVertex: vertexA },
{ currentVertex: vertexE, previousVertex: vertexD },
{ currentVertex: vertexH, previousVertex: vertexE },
{ currentVertex: vertexF, previousVertex: vertexH },
{ currentVertex: vertexD, previousVertex: vertexF },
{ currentVertex: vertexH, previousVertex: vertexD },
];
for (let callIndex = 0; callIndex < 7; callIndex += 1) {
const params = enterVertexCallback.mock.calls[callIndex][0];
expect(params.currentVertex).toEqual(enterVertexParamsMap[callIndex].currentVertex);
expect(params.previousVertex).toEqual(enterVertexParamsMap[callIndex].previousVertex);
}
const leaveVertexParamsMap = [
{ currentVertex: vertexA, previousVertex: null },
{ currentVertex: vertexD, previousVertex: vertexA },
{ currentVertex: vertexE, previousVertex: vertexD },
{ currentVertex: vertexH, previousVertex: vertexE },
{ currentVertex: vertexF, previousVertex: vertexH },
{ currentVertex: vertexD, previousVertex: vertexF },
{ currentVertex: vertexH, previousVertex: vertexD },
];
for (let callIndex = 0; callIndex < 7; callIndex += 1) {
const params = leaveVertexCallback.mock.calls[callIndex][0];
expect(params.currentVertex).toEqual(leaveVertexParamsMap[callIndex].currentVertex);
expect(params.previousVertex).toEqual(leaveVertexParamsMap[callIndex].previousVertex);
}
});
});