Skip to content

Commit cd2fe96

Browse files
committed
Merge pull request kodecocodes#58 from chris-pilcher/breadth-first-search-tests
Breadth first search tests
2 parents 111469c + b6ab520 commit cd2fe96

File tree

18 files changed

+849
-29
lines changed

18 files changed

+849
-29
lines changed

Breadth-First Search/BreadthFirstSearch.playground/Pages/Shortest path example.xcplaygroundpage/Contents.swift

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1-
func breadthFirstSearchShortestPath(graph: Graph, source: Node) {
1+
func breadthFirstSearchShortestPath(graph: Graph, source: Node) -> Graph {
2+
let shortestPathGraph = graph.duplicate()
3+
24
var queue = Queue<Node>()
3-
queue.enqueue(source)
4-
source.distance = 0
5+
let sourceInShortestPathsGraph = shortestPathGraph.findNodeWithLabel(source.label)
6+
queue.enqueue(sourceInShortestPathsGraph)
7+
sourceInShortestPathsGraph.distance = 0
58

69
while !queue.isEmpty {
710
let current = queue.dequeue()!
@@ -14,9 +17,8 @@ func breadthFirstSearchShortestPath(graph: Graph, source: Node) {
1417
}
1518
}
1619

17-
print(graph.nodes)
20+
return shortestPathGraph
1821
}
19-
2022
/*:
2123
![Animated example of a breadth-first search](Animated_BFS.gif)
2224
*/
@@ -40,4 +42,5 @@ graph.addEdge(nodeC, neighbor: nodeF)
4042
graph.addEdge(nodeC, neighbor: nodeG)
4143
graph.addEdge(nodeE, neighbor: nodeH)
4244

43-
breadthFirstSearchShortestPath(graph, source: nodeA)
45+
let shortestPathGraph = breadthFirstSearchShortestPath(graph, source: nodeA)
46+
print(shortestPathGraph.nodes)

Breadth-First Search/BreadthFirstSearch.playground/Pages/Simple example.xcplaygroundpage/Contents.swift

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,24 @@
1-
func breadthFirstSearch(graph: Graph, source: Node) {
2-
var seenNodes = [source]
1+
func breadthFirstSearch(graph: Graph, source: Node) -> [String] {
32
var queue = Queue<Node>()
43
queue.enqueue(source)
54

6-
print(source.label)
5+
var nodesExplored = [source.label]
6+
source.visited = true
77

88
while !queue.isEmpty {
99
let current = queue.dequeue()!
1010
for edge in current.neighbors {
1111
let neighborNode = edge.neighbor
12-
if !seenNodes.contains(neighborNode) {
12+
if !neighborNode.visited {
1313
queue.enqueue(neighborNode)
14-
seenNodes.append(neighborNode)
15-
print(neighborNode.label)
14+
neighborNode.visited = true
15+
16+
nodesExplored.append(neighborNode.label)
1617
}
1718
}
1819
}
20+
21+
return nodesExplored
1922
}
2023

2124
/*:
@@ -42,4 +45,5 @@ graph.addEdge(nodeC, neighbor: nodeG)
4245
graph.addEdge(nodeE, neighbor: nodeH)
4346

4447

45-
breadthFirstSearch(graph, source: nodeA)
48+
let nodesExplored = breadthFirstSearch(graph, source: nodeA)
49+
print(nodesExplored)
Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
1-
public class Edge {
1+
public class Edge : Equatable {
22
public var neighbor: Node
33

44
public init(neighbor: Node) {
55
self.neighbor = neighbor
66
}
77
}
8+
9+
public func ==(lhs: Edge, rhs: Edge) -> Bool {
10+
return lhs.neighbor == rhs.neighbor
11+
}

Breadth-First Search/BreadthFirstSearch.playground/Sources/Graph.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
public class Graph : CustomStringConvertible {
1+
public class Graph : CustomStringConvertible, Equatable {
22
public private(set) var nodes: [Node]
33

44
public init() {
@@ -50,3 +50,7 @@ public class Graph : CustomStringConvertible {
5050
return duplicated
5151
}
5252
}
53+
54+
public func ==(lhs: Graph, rhs: Graph) -> Bool {
55+
return lhs.nodes == rhs.nodes
56+
}

Breadth-First Search/BreadthFirstSearch.playground/Sources/Node.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
public class Node : CustomStringConvertible, Equatable {
22
public var neighbors: [Edge]
3-
3+
44
public private(set) var label: String
55
public var distance: Int?
66
public var visited: Bool
@@ -28,5 +28,5 @@ public class Node : CustomStringConvertible, Equatable {
2828
}
2929

3030
public func ==(lhs: Node, rhs: Node) -> Bool {
31-
return lhs.label == rhs.label
31+
return lhs.label == rhs.label && lhs.neighbors == rhs.neighbors
3232
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
func breadthFirstSearch(graph: Graph, source: Node) -> [String] {
2+
var queue = Queue<Node>()
3+
queue.enqueue(source)
4+
5+
var nodesExplored = [source.label]
6+
source.visited = true
7+
8+
while !queue.isEmpty {
9+
let current = queue.dequeue()!
10+
for edge in current.neighbors {
11+
let neighborNode = edge.neighbor
12+
if !neighborNode.visited {
13+
queue.enqueue(neighborNode)
14+
neighborNode.visited = true
15+
16+
nodesExplored.append(neighborNode.label)
17+
}
18+
}
19+
}
20+
21+
return nodesExplored
22+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
func breadthFirstSearchMinimumSpanningTree(graph: Graph, source: Node) -> Graph {
2+
let minimumSpanningTree = graph.duplicate()
3+
4+
var queue = Queue<Node>()
5+
let sourceInMinimumSpanningTree = minimumSpanningTree.findNodeWithLabel(source.label)
6+
queue.enqueue(sourceInMinimumSpanningTree)
7+
sourceInMinimumSpanningTree.visited = true
8+
9+
while !queue.isEmpty {
10+
let current = queue.dequeue()!
11+
for edge in current.neighbors {
12+
let neighborNode = edge.neighbor
13+
if !neighborNode.visited {
14+
neighborNode.visited = true
15+
queue.enqueue(neighborNode)
16+
} else {
17+
current.remove(edge)
18+
}
19+
}
20+
}
21+
22+
return minimumSpanningTree
23+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
func breadthFirstSearchShortestPath(graph: Graph, source: Node) -> Graph {
2+
let shortestPathGraph = graph.duplicate()
3+
4+
var queue = Queue<Node>()
5+
let sourceInShortestPathsGraph = shortestPathGraph.findNodeWithLabel(source.label)
6+
queue.enqueue(sourceInShortestPathsGraph)
7+
sourceInShortestPathsGraph.distance = 0
8+
9+
while !queue.isEmpty {
10+
let current = queue.dequeue()!
11+
for edge in current.neighbors {
12+
let neighborNode = edge.neighbor
13+
if !neighborNode.hasDistance {
14+
queue.enqueue(neighborNode)
15+
neighborNode.distance = current.distance! + 1
16+
}
17+
}
18+
}
19+
20+
return shortestPathGraph
21+
}

Breadth-First Search/Edge.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
public class Edge : Equatable {
2+
public var neighbor: Node
3+
4+
public init(neighbor: Node) {
5+
self.neighbor = neighbor
6+
}
7+
}
8+
9+
public func ==(lhs: Edge, rhs: Edge) -> Bool {
10+
return lhs.neighbor == rhs.neighbor
11+
}

Breadth-First Search/Graph.swift

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
public class Graph : CustomStringConvertible, Equatable {
2+
public private(set) var nodes: [Node]
3+
4+
public init() {
5+
self.nodes = []
6+
}
7+
8+
public func addNode(label: String) -> Node {
9+
let node = Node(label: label)
10+
nodes.append(node)
11+
return node
12+
}
13+
14+
public func addEdge(source: Node, neighbor: Node) {
15+
let edge = Edge(neighbor: neighbor)
16+
edge.neighbor = neighbor
17+
source.neighbors.append(edge)
18+
}
19+
20+
public var description: String {
21+
var description = ""
22+
23+
for node in nodes {
24+
if !node.neighbors.isEmpty {
25+
description += "[node: \(node.label) edges: \(node.neighbors.map{ $0.neighbor.label})]"
26+
}
27+
}
28+
return description
29+
}
30+
31+
public func findNodeWithLabel(label: String) -> Node {
32+
return nodes.filter{ $0.label == label }.first!
33+
}
34+
35+
public func duplicate() -> Graph {
36+
let duplicated = Graph()
37+
38+
for node in nodes {
39+
duplicated.addNode(node.label)
40+
}
41+
42+
for node in nodes {
43+
for edge in node.neighbors {
44+
let source = duplicated.findNodeWithLabel(node.label)
45+
let neighbour = duplicated.findNodeWithLabel(edge.neighbor.label)
46+
duplicated.addEdge(source, neighbor: neighbour)
47+
}
48+
}
49+
50+
return duplicated
51+
}
52+
}
53+
54+
public func ==(lhs: Graph, rhs: Graph) -> Bool {
55+
return lhs.nodes == rhs.nodes
56+
}

0 commit comments

Comments
 (0)