Skip to content

Commit 32ac84b

Browse files
author
Chris Pilcher
committed
BFS Added test project with implementation files.
1 parent 87d798d commit 32ac84b

10 files changed

+501
-0
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
func breadthFirstSearch(graph: Graph, source: Node) {
2+
var queue = Queue<Node>()
3+
queue.enqueue(source)
4+
5+
print(source.label)
6+
7+
while !queue.isEmpty {
8+
let current = queue.dequeue()!
9+
for edge in current.neighbors {
10+
let neighborNode = edge.neighbor
11+
if !neighborNode.visited {
12+
queue.enqueue(neighborNode)
13+
neighborNode.visited = true
14+
print(neighborNode.label)
15+
}
16+
}
17+
}
18+
}
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: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
func breadthFirstSearchShortestPath(graph: Graph, source: Node) {
2+
var queue = Queue<Node>()
3+
queue.enqueue(source)
4+
source.distance = 0
5+
6+
while !queue.isEmpty {
7+
let current = queue.dequeue()!
8+
for edge in current.neighbors {
9+
let neighborNode = edge.neighbor
10+
if !neighborNode.hasDistance {
11+
queue.enqueue(neighborNode)
12+
neighborNode.distance = current.distance! + 1
13+
}
14+
}
15+
}
16+
17+
print(graph.nodes)
18+
}

Breadth-First Search/Edge.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
public class Edge {
2+
public var neighbor: Node
3+
4+
public init(neighbor: Node) {
5+
self.neighbor = neighbor
6+
}
7+
}

Breadth-First Search/Graph.swift

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
public class Graph : CustomStringConvertible {
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+
}

Breadth-First Search/Node.swift

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
public class Node : CustomStringConvertible, Equatable {
2+
public var neighbors: [Edge]
3+
4+
public private(set) var label: String
5+
public var distance: Int?
6+
public var visited: Bool
7+
8+
public init(label: String) {
9+
self.label = label
10+
neighbors = []
11+
visited = false
12+
}
13+
14+
public var description: String {
15+
if let distance = distance {
16+
return "Node(label: \(label), distance: \(distance))"
17+
}
18+
return "Node(label: \(label), distance: infinity)"
19+
}
20+
21+
public var hasDistance: Bool {
22+
return distance != nil
23+
}
24+
25+
public func remove(edge: Edge) {
26+
neighbors.removeAtIndex(neighbors.indexOf{ $0 === edge }!)
27+
}
28+
}
29+
30+
public func ==(lhs: Node, rhs: Node) -> Bool {
31+
return lhs.label == rhs.label
32+
}

Breadth-First Search/Queue.swift

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
public struct Queue<T> {
2+
private var array: [T]
3+
4+
public init() {
5+
array = []
6+
}
7+
8+
public var isEmpty: Bool {
9+
return array.isEmpty
10+
}
11+
12+
public var count: Int {
13+
return array.count
14+
}
15+
16+
public mutating func enqueue(element: T) {
17+
array.append(element)
18+
}
19+
20+
public mutating func dequeue() -> T? {
21+
if isEmpty {
22+
return nil
23+
} else {
24+
return array.removeFirst()
25+
}
26+
}
27+
28+
public func peek() -> T? {
29+
return array.first
30+
}
31+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import Foundation
2+
import XCTest
3+
4+
class QueueTest: XCTestCase {
5+
func testFail() {
6+
XCTAssertFalse(true)
7+
}
8+
}

Breadth-First Search/Tests/Info.plist

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>CFBundleDevelopmentRegion</key>
6+
<string>en</string>
7+
<key>CFBundleExecutable</key>
8+
<string>$(EXECUTABLE_NAME)</string>
9+
<key>CFBundleIdentifier</key>
10+
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
11+
<key>CFBundleInfoDictionaryVersion</key>
12+
<string>6.0</string>
13+
<key>CFBundleName</key>
14+
<string>$(PRODUCT_NAME)</string>
15+
<key>CFBundlePackageType</key>
16+
<string>BNDL</string>
17+
<key>CFBundleShortVersionString</key>
18+
<string>1.0</string>
19+
<key>CFBundleSignature</key>
20+
<string>????</string>
21+
<key>CFBundleVersion</key>
22+
<string>1</string>
23+
</dict>
24+
</plist>

0 commit comments

Comments
 (0)