Skip to content

Commit d5c5780

Browse files
authored
Correct BFS algorithm and tests (#279)
* Revise BFS algorithm implementation. * Test for BFS * Fix: Edit package name and structure Fix: Improve documenting * Fix: rename function and file name (Breadthfirstsearch -> BFS) * Fix: revert renaming function and file name (BFS -> BreadthFirstSearch)
1 parent 04f4572 commit d5c5780

File tree

3 files changed

+111
-73
lines changed

3 files changed

+111
-73
lines changed

graphs/breathfirstsearch/breathfirstsearch.go

Lines changed: 0 additions & 73 deletions
This file was deleted.

graphs/search/breadthFirstSearch.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Package search Graph search algorithms
2+
// reference: https://en.wikipedia.org/wiki/Tree_traversal
3+
package search
4+
5+
/*BreadthFirstSearch is an algorithm for traversing and searching graph data structures.
6+
It starts at an arbitrary node of a graph, and explores all of the neighbor nodes
7+
at the present depth prior to moving on to the nodes at the next depth level.
8+
Worst-case performance O(|V|+|E|)=O(b^{d})}O(|V|+|E|)=O(b^{d})
9+
Worst-case space complexity O(|V|)=O(b^{d})}O(|V|)=O(b^{d})
10+
reference: https://en.wikipedia.org/wiki/Breadth-first_search
11+
*/
12+
func BreadthFirstSearch(start, end, nodes int, edges [][]int) (isConnected bool, distance int) {
13+
queue := make([]int, 0)
14+
discovered := make([]int, nodes)
15+
discovered[start] = 1
16+
queue = append(queue, start)
17+
for len(queue) > 0 {
18+
v := queue[0]
19+
if len(queue) > 0 {
20+
queue = queue[1:]
21+
}
22+
for i := 0; i < len(edges[v]); i++ {
23+
if discovered[i] == 0 && edges[v][i] > 0 {
24+
if i == end {
25+
return true, discovered[v]
26+
}
27+
discovered[i] = discovered[v] + 1
28+
queue = append(queue, i)
29+
}
30+
}
31+
}
32+
return false, 0
33+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package search
2+
3+
import (
4+
"testing"
5+
)
6+
7+
func TestBreadthFirstSearch(t *testing.T) {
8+
var bfsTestData = []struct {
9+
description string
10+
start int
11+
end int
12+
nodes int
13+
edges [][]int
14+
expected1 bool
15+
expected2 int
16+
}{
17+
{
18+
"test 1 connected with distance 2",
19+
0,
20+
5,
21+
6,
22+
[][]int{
23+
{0, 1, 1, 0, 0, 0},
24+
{1, 0, 0, 1, 0, 1},
25+
{1, 0, 0, 1, 0, 0},
26+
{0, 1, 1, 0, 1, 0},
27+
{0, 0, 0, 1, 0, 0},
28+
{0, 1, 0, 0, 0, 0},
29+
},
30+
true,
31+
2,
32+
},
33+
{
34+
"test 2 connected with distance 4",
35+
0,
36+
5,
37+
6,
38+
[][]int{
39+
{0, 1, 1, 0, 0, 0},
40+
{1, 0, 0, 1, 0, 0},
41+
{1, 0, 0, 1, 0, 0},
42+
{0, 1, 1, 0, 1, 0},
43+
{0, 0, 0, 1, 0, 1},
44+
{0, 0, 0, 0, 1, 0},
45+
},
46+
true,
47+
4,
48+
},
49+
{
50+
"test 2 not connected",
51+
0,
52+
5,
53+
6,
54+
[][]int{
55+
{0, 1, 1, 0, 0, 0},
56+
{1, 0, 0, 1, 0, 0},
57+
{1, 0, 0, 1, 0, 0},
58+
{0, 1, 1, 0, 1, 0},
59+
{0, 0, 0, 1, 0, 0},
60+
{0, 0, 0, 0, 0, 0},
61+
},
62+
false,
63+
0,
64+
},
65+
}
66+
for _, test := range bfsTestData {
67+
t.Run(test.description, func(t *testing.T) {
68+
r1, r2 := BreadthFirstSearch(test.start, test.end,
69+
test.nodes, test.edges)
70+
if r1 != test.expected1 || r2 != test.expected2 {
71+
t.Logf("FAIL: %s", test.description)
72+
t.Fatalf("Nodes '%v' and Edges '%v' start from '%d' and end in '%d' "+
73+
"was expecting '%v' with distance '%d' but result was '%v','%d'",
74+
test.nodes, test.edges, test.start, test.end, test.expected1, test.expected2, r1, r2)
75+
}
76+
})
77+
}
78+
}

0 commit comments

Comments
 (0)