Skip to content

Commit 4f23cf4

Browse files
author
Gunawan Nur Ahmad
committed
add BFS algo
1 parent cbbcef7 commit 4f23cf4

File tree

5 files changed

+99
-30
lines changed

5 files changed

+99
-30
lines changed

src/algorithms/BFS.js

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,45 @@
1-
export function BFS(grid, startNode, finishNode) {}
1+
export function BFS(grid, startNode, finishNode) {
2+
const queue = [];
3+
const visitedNodes = [];
4+
startNode.distance = 0;
5+
queue.push(startNode);
6+
while (queue.length != 0) {
7+
let currNode = queue.shift();
8+
if (currNode.isVisited || currNode.isWall) continue;
9+
currNode.isVisited = true;
10+
if (currNode.distance == Infinity) return visitedNodes;
11+
visitedNodes.push(currNode);
12+
if (currNode == finishNode) return visitedNodes;
13+
updateUnvisitedNeighbours(currNode, grid, queue);
14+
}
15+
return visitedNodes;
16+
}
17+
18+
function updateUnvisitedNeighbours(node, grid, queue) {
19+
const unvisitedNeighbours = getUnvisistedNeighbours(node, grid);
20+
for (let neighbour of unvisitedNeighbours) {
21+
neighbour.distance = node.distance + 1;
22+
neighbour.previousNode = node;
23+
queue.push(neighbour);
24+
}
25+
}
26+
27+
function getUnvisistedNeighbours(node, grid) {
28+
const neighbours = [];
29+
const { col, row } = node;
30+
if (row > 0) neighbours.push(grid[row - 1][col]);
31+
if (col > 0) neighbours.push(grid[row][col - 1]);
32+
if (row < grid.length - 1) neighbours.push(grid[row + 1][col]);
33+
if (col < grid[0].length - 1) neighbours.push(grid[row][col + 1]);
34+
return neighbours.filter((node) => !node.isVisited);
35+
}
36+
37+
export function findTheShortestPathFromBFS(finishNode) {
38+
const nodesInShortesPathOrder = [];
39+
let currNode = finishNode;
40+
while (currNode !== null) {
41+
nodesInShortesPathOrder.unshift(currNode);
42+
currNode = currNode.previousNode;
43+
}
44+
return nodesInShortesPathOrder;
45+
}

src/algorithms/bidirectionalDijkstra.js

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,21 @@
1-
const unvisitedNodesFromStart = [];
2-
const unvisitedNodesFromFinish = [];
3-
const visitedNodesFromFinish = [];
4-
const visitedNodesFromStart = [];
5-
let found = false;
1+
let unvisitedNodesFromStart = [];
2+
let unvisitedNodesFromFinish = [];
3+
let visitedNodesFromFinish = [];
4+
let visitedNodesFromStart = [];
5+
let foundByBothTarget = false;
66
let foundNode = null;
77
let lastNode = null;
8-
let last = undefined;
8+
let lastFrom = undefined;
99

1010
export function bidirectionalDijkstra(grid, startNode, finishNode) {
11+
unvisitedNodesFromStart = [];
12+
unvisitedNodesFromFinish = [];
13+
visitedNodesFromFinish = [];
14+
visitedNodesFromStart = [];
15+
foundByBothTarget = false;
16+
foundNode = null;
17+
lastNode = null;
18+
lastFrom = null;
1119
startNode.distance = 0;
1220
finishNode.distance = 0;
1321
const visistedNodesInOrder = [];
@@ -28,8 +36,8 @@ export function bidirectionalDijkstra(grid, startNode, finishNode) {
2836
currNodeStart.isVisited = true;
2937
visistedNodesInOrder.push(currNodeStart);
3038
visitedNodesFromStart.push(currNodeStart);
31-
if (found) {
32-
if (last == "start") {
39+
if (foundByBothTarget) {
40+
if (lastFrom == "start") {
3341
sortNodesByDistance(visitedNodesFromStart);
3442

3543
lastNode = visitedNodesFromStart[visitedNodesFromStart.length - 1];
@@ -51,8 +59,8 @@ export function bidirectionalDijkstra(grid, startNode, finishNode) {
5159
currNodeFinish.isVisited = true;
5260
visistedNodesInOrder.push(currNodeFinish);
5361
visitedNodesFromFinish.push(currNodeFinish);
54-
if (found) {
55-
if (last == "start") {
62+
if (foundByBothTarget) {
63+
if (lastFrom == "start") {
5664
sortNodesByDistance(visitedNodesFromStart);
5765

5866
lastNode = visitedNodesFromStart[visitedNodesFromStart.length - 1];
@@ -76,7 +84,7 @@ export function bidirectionalDijkstra(grid, startNode, finishNode) {
7684
return visistedNodesInOrder;
7785
}
7886
}
79-
if (last == "start") {
87+
if (lastFrom == "start") {
8088
sortNodesByDistance(visitedNodesFromStart);
8189
lastNode = visitedNodesFromStart[visitedNodesFromStart.length - 1];
8290
} else {
@@ -102,17 +110,17 @@ function updateUnvisitedNeighbours(
102110
for (let neighbour of unvisitedNeighbours) {
103111
if (isFromStart) {
104112
if (visitedNodesFromFinish.includes(neighbour)) {
105-
last = "start";
113+
lastFrom = "start";
106114

107115
foundNode = neighbour;
108-
found = true;
116+
foundByBothTarget = true;
109117
return;
110118
}
111119
} else if (isFromFinish) {
112120
if (visitedNodesFromStart.includes(neighbour)) {
113121
foundNode = neighbour;
114-
last = "finish";
115-
found = true;
122+
lastFrom = "finish";
123+
foundByBothTarget = true;
116124
return;
117125
}
118126
}

src/components/Navbar.vue

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
<ul class="ul-list" v-if="isShowingAlgoList">
1212
<li @click="changeSelectedAlgo('A* Search')">A* Search</li>
1313
<li @click="changeSelectedAlgo('Dijkstra')">Dijkstra</li>
14+
<li @click="changeSelectedAlgo('BFS')">BFS</li>
1415
<li @click="changeSelectedAlgo('Bidirectional Dijkstra')">
1516
Bidirectional Dijkstra
1617
</li>
@@ -67,8 +68,8 @@ export default {
6768
this.$refs.triangle.classList.remove("flip");
6869
},
6970
openAlgoList() {
70-
this.isShowingAlgoList = true;
71-
this.$refs.triangle.classList.add("flip");
71+
this.isShowingAlgoList = !this.isShowingAlgoList;
72+
this.$refs.triangle.classList.toggle("flip");
7273
},
7374
},
7475
};

src/components/PathfindingVisualizer.vue

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
<template>
22
<div class="container" ref="container">
3-
<button @click="runBidirectional">Bidirectional</button>
43
<div class="grid" v-for="(row, rowIndex) in grid" :key="rowIndex">
54
<Node
65
v-for="(col, colIndex) in row"
@@ -22,6 +21,7 @@ import {
2221
bidirectionalDijkstra,
2322
findTheShortestPathFromBidirectional,
2423
} from "../algorithms/bidirectionalDijkstra";
24+
import { BFS, findTheShortestPathFromBFS } from "../algorithms/BFS";
2525
export default {
2626
components: { Node },
2727
data() {
@@ -59,30 +59,43 @@ export default {
5959
distance: Infinity,
6060
};
6161
},
62+
runBFS() {
63+
const startNode = this.grid[this.$store.state.startNode.row][
64+
this.$store.state.startNode.col
65+
];
66+
const finishNode = this.grid[this.$store.state.finishNode.row][
67+
this.$store.state.finishNode.col
68+
];
69+
let visistedNodes = BFS(this.grid, startNode, finishNode);
70+
let shortestPath = findTheShortestPathFromBFS(finishNode);
71+
this.visualizeAlgo(visistedNodes, shortestPath);
72+
},
6273
runBidirectional() {
6374
const startNode = this.grid[this.$store.state.startNode.row][
6475
this.$store.state.startNode.col
6576
];
6677
const finishNode = this.grid[this.$store.state.finishNode.row][
6778
this.$store.state.finishNode.col
6879
];
69-
let test = bidirectionalDijkstra(this.grid, startNode, finishNode);
70-
let path = findTheShortestPathFromBidirectional();
71-
this.visualizeAlgo(test, path);
80+
let visitedNodes = bidirectionalDijkstra(
81+
this.grid,
82+
startNode,
83+
finishNode
84+
);
85+
let shortestPath = findTheShortestPathFromBidirectional();
86+
this.visualizeAlgo(visitedNodes, shortestPath);
7287
},
7388
runPathfindingAlgo() {
7489
this.resetVisitedGrid();
75-
if (this.$store.state.selectedAlgorithm.toLowerCase() === "a* search") {
90+
let selectedAlgo = this.$store.state.selectedAlgorithm.toLowerCase();
91+
if (selectedAlgo === "a* search") {
7692
this.runAstarAlgo();
77-
} else if (
78-
this.$store.state.selectedAlgorithm.toLowerCase() === "dijkstra"
79-
) {
93+
} else if (selectedAlgo === "dijkstra") {
8094
this.runDijkstraAlgo();
81-
} else if (
82-
this.$store.state.selectedAlgorithm.toLowerCase() ===
83-
"bidirectional dijkstra"
84-
) {
95+
} else if (selectedAlgo === "bidirectional dijkstra") {
8596
this.runBidirectional();
97+
} else if (selectedAlgo === "bfs") {
98+
this.runBFS();
8699
}
87100
},
88101
runAstarAlgo() {
@@ -186,6 +199,7 @@ export default {
186199
this.grid[i][j].isVisited = false;
187200
this.grid[i][j].distance = Infinity;
188201
this.grid[i][j].isWall = false;
202+
this.grid[i][j].previousNode = null;
189203
}
190204
}
191205
let visitedNodes = document.querySelectorAll(".node");

src/scss/Navbar.scss

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,10 @@
5252
overflow: hidden;
5353
left: 0;
5454
right: 0;
55+
width: auto;
5556
border-radius: 10px;
5657
min-width: 150px;
58+
z-index: 99;
5759

5860
li {
5961
padding: 0.5rem 1rem;

0 commit comments

Comments
 (0)