Skip to content

Commit fa073ec

Browse files
committed
Small tweaks to text
1 parent e9c1860 commit fa073ec

File tree

3 files changed

+99
-48
lines changed

3 files changed

+99
-48
lines changed

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ func breadthFirstSearch(graph: Graph, source: Node) -> [String] {
1212
if !neighborNode.visited {
1313
queue.enqueue(neighborNode)
1414
neighborNode.visited = true
15-
1615
nodesExplored.append(neighborNode.label)
1716
}
1817
}

Breadth-First Search/BreadthFirstSearch.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ func breadthFirstSearch(graph: Graph, source: Node) -> [String] {
1212
if !neighborNode.visited {
1313
queue.enqueue(neighborNode)
1414
neighborNode.visited = true
15-
1615
nodesExplored.append(neighborNode.label)
1716
}
1817
}

Breadth-First Search/README.markdown

Lines changed: 99 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Breadth-First Search
22

3-
Breadth-first search (BFS) is an algorithm for traversing or searching [tree](../Tree/) or [graph](../Graph/) data structures. It starts at the tree source and explores the neighbor nodes first, before moving to the next level neighbors.
3+
Breadth-first search (BFS) is an algorithm for traversing or searching [tree](../Tree/) or [graph](../Graph/) data structures. It starts at the tree source and explores the immediate neighbor nodes first, before moving to the next level neighbors.
44

55
## Animated example
66

@@ -9,49 +9,67 @@ Breadth-first search (BFS) is an algorithm for traversing or searching [tree](..
99
Let's follow the animated example by using a [queue](../Queue/).
1010

1111
Start with the source node ``a`` and add it to a queue.
12+
1213
```swift
1314
queue.enqueue(a)
1415
```
15-
The queue is now ``[ a ]``. Dequeue ``a`` and enqueue the neighbor nodes ``b`` and ``c``.
16+
17+
The queue is now ``[ a ]``. Dequeue ``a`` and enqueue its two neighbor nodes ``b`` and ``c``.
18+
1619
```swift
17-
queue.dequeue(a)
20+
queue.dequeue() // a
1821
queue.enqueue(b)
1922
queue.enqueue(c)
2023
```
21-
The queue is now ``[ b, c ]``. Dequeue ``b`` and enqueue the neighbor nodes ``d`` and ``e``.
24+
25+
The queue is now ``[ b, c ]``. Dequeue ``b`` and enqueue `b`'s neighbor nodes ``d`` and ``e``.
26+
2227
```swift
23-
queue.dequeue(b)
28+
queue.dequeue() // b
2429
queue.enqueue(d)
2530
queue.enqueue(e)
2631
```
27-
The queue is now ``[ c, d, e ]``. Dequeue ``c`` and enqueue the neighbor nodes ``f`` and ``g``.
32+
33+
The queue is now ``[ c, d, e ]``. Dequeue ``c`` and enqueue `c`'s neighbor nodes ``f`` and ``g``.
34+
2835
```swift
29-
queue.dequeue(c)
36+
queue.dequeue() // c
3037
queue.enqueue(f)
3138
queue.enqueue(g)
3239
```
40+
3341
The queue is now ``[ d, e, f, g ]``. Dequeue ``d`` which has no neighbor nodes.
42+
3443
```swift
35-
queue.dequeue(d)
44+
queue.dequeue() // d
3645
```
37-
The queue is now ``[ e, f, g ]``. Dequeue ``e`` and enqueue the single neighbor node ``h``.
46+
47+
The queue is now ``[ e, f, g ]``. Dequeue ``e`` and enqueue its single neighbor node ``h``.
48+
3849
```swift
39-
queue.dequeue(e)
50+
queue.dequeue() // e
4051
queue.enqueue(h)
4152
```
53+
4254
The queue is now ``[ f, g, h ]``. Dequeue ``f`` which has no neighbor nodes.
55+
4356
```swift
44-
queue.dequeue(f)
57+
queue.dequeue() // f
4558
```
59+
4660
The queue is now ``[ g, h ]``. Dequeue ``g`` which has no neighbor nodes.
61+
4762
```swift
48-
queue.dequeue(g)
63+
queue.dequeue() // g
4964
```
65+
5066
The queue is now ``[ h ]``. Dequeue ``h`` which has no neighbor nodes.
67+
5168
```swift
52-
queue.dequeue(h)
69+
queue.dequeue() // h
5370
```
54-
The queue is now empty which means all nodes have been explored.
71+
72+
The queue is now empty, meaning that all nodes have been explored. The order in which the nodes were explored is `a`, `b`, `c`, `d`, `e`, `f`, `g`, `h`.
5573

5674
## The code
5775

@@ -72,7 +90,6 @@ func breadthFirstSearch(graph: Graph, source: Node) -> [String] {
7290
if !neighborNode.visited {
7391
queue.enqueue(neighborNode)
7492
neighborNode.visited = true
75-
7693
nodesExplored.append(neighborNode.label)
7794
}
7895
}
@@ -83,8 +100,9 @@ func breadthFirstSearch(graph: Graph, source: Node) -> [String] {
83100
```
84101

85102
Put this code in a playground and test it like so:
103+
86104
```swift
87-
let graph = Graph() // Representing the graph from the animated example
105+
let graph = Graph() // Representing the graph from the animated example
88106

89107
let nodeA = graph.addNode("a")
90108
let nodeB = graph.addNode("b")
@@ -104,46 +122,53 @@ graph.addEdge(nodeC, neighbor: nodeG)
104122
graph.addEdge(nodeE, neighbor: nodeH)
105123

106124
let nodesExplored = breadthFirstSearch(graph, source: nodeA)
107-
print(nodesExplored) // This will output: ["a", "b", "c", "d", "e", "f", "g", "h"]
125+
print(nodesExplored)
108126
```
109127

128+
This will output: `["a", "b", "c", "d", "e", "f", "g", "h"]`
129+
110130
## Applications
111131

112132
Breadth-first search can be used to solve many problems, for example:
113133

114-
* Computing the shortest path between a source node and each of the other nodes
115-
* Only for unweighted graphs
134+
* Computing the shortest path between a source node and each of the other nodes (only for unweighted graphs)
116135
* Calculating the minimum spanning tree on an unweighted graph
117136

118137
## Shortest path example
119138

120-
Breadth-first search can be used to compute the [shortest path](../Shortest Path/) between a source node and each of the other nodes because it explores all of the neighbor nodes before moving to the next level neighbors. Let's follow the animated example and calculate the shortest path to all the other nodes:
139+
Breadth-first search can be used to compute the [shortest path](../Shortest Path/) between a source node and each of the other nodes in the tree or graph, because it explores all of the immediate neighbor nodes first before moving to the next level neighbors.
140+
141+
Let's follow the animated example and calculate the shortest path to all the other nodes. Start with the source node ``a`` and add it to a queue with a distance of ``0``.
121142

122-
Start with the source node ``a`` and add it to a queue with a distance of ``0``.
123143
```swift
124144
queue.enqueue(a)
125145
a.distance = 0
126146
```
127-
The queue is now ``[ a ]``. Dequeue ``a`` and enqueue the neighbor nodes ``b`` and ``c`` with a distance of ``1``.
147+
148+
The queue is now ``[ a ]``. Dequeue ``a`` and enqueue its two neighbor nodes ``b`` and ``c`` with a distance of ``1``.
149+
128150
```swift
129-
queue.dequeue(a)
151+
queue.dequeue() // a
130152
queue.enqueue(b)
131-
b.distance = a.distance + 1 // result: 1
153+
b.distance = a.distance + 1 // result: 1
132154
queue.enqueue(c)
133-
c.distance = a.distance + 1 // result: 1
155+
c.distance = a.distance + 1 // result: 1
134156
```
135-
The queue is now ``[ b, c ]``. Dequeue ``b`` and enqueue the neighbor nodes ``d`` and ``e`` with a distance of ``2``.
157+
158+
The queue is now ``[ b, c ]``. Dequeue ``b`` and enqueue `b`'s neighbor nodes ``d`` and ``e`` with a distance of ``2``.
159+
136160
```swift
137-
queue.dequeue(b)
161+
queue.dequeue() // b
138162
queue.enqueue(d)
139-
d.distance = b.distance + 1 // result: 2
163+
d.distance = b.distance + 1 // result: 2
140164
queue.enqueue(e)
141-
e.distance = b.distance + 1 // result: 2
165+
e.distance = b.distance + 1 // result: 2
142166
```
143167

144168
Continue until the queue is empty to calculate the shortest path to all other nodes.
145169

146170
Here's the code:
171+
147172
```swift
148173
func breadthFirstSearchShortestPath(graph: Graph, source: Node) -> Graph {
149174
let shortestPathGraph = graph.duplicate()
@@ -169,19 +194,21 @@ func breadthFirstSearchShortestPath(graph: Graph, source: Node) -> Graph {
169194
```
170195

171196
Put this code in a playground and test it like so:
197+
172198
```swift
173199
let shortestPathGraph = breadthFirstSearchShortestPath(graph, source: nodeA)
174200
print(shortestPathGraph.nodes)
175-
176-
// This will output:
177-
// Node(label: a, distance: 0), Node(label: b, distance: 1), Node(label: c, distance: 1),
178-
// Node(label: d, distance: 2), Node(label: e, distance: 2), Node(label: f, distance: 2),
179-
// Node(label: g, distance: 2), Node(label: h, distance: 3)
180201
```
181202

203+
This will output:
204+
205+
Node(label: a, distance: 0), Node(label: b, distance: 1), Node(label: c, distance: 1),
206+
Node(label: d, distance: 2), Node(label: e, distance: 2), Node(label: f, distance: 2),
207+
Node(label: g, distance: 2), Node(label: h, distance: 3)
208+
182209
## Minimum spanning tree example
183210

184-
Breadth-first search can be used to calculate the [minimum spanning tree](../Minimum Spanning Tree/) on an unweighted graph.
211+
Breadth-first search can be used to calculate the [minimum spanning tree](../Minimum Spanning Tree/) on an unweighted graph. A minimum spanning tree describes a path that contains the smallest number of edges that are needed to visit every node in the graph.
185212

186213
Let's calculate the minimum spanning tree for the following graph:
187214

@@ -190,71 +217,92 @@ Let's calculate the minimum spanning tree for the following graph:
190217
*Note: the minimum spanning tree is represented by the bold edges.*
191218

192219
Start with the source node ``a`` and add it to a queue and mark it as visited.
220+
193221
```swift
194222
queue.enqueue(a)
195223
a.visited = true
196224
```
197-
The queue is now ``[ a ]``. Dequeue ``a`` and enqueue the neighbor nodes ``b`` and ``h`` and mark them as visited.
225+
226+
The queue is now ``[ a ]``. Dequeue ``a`` and enqueue its immediate neighbor nodes ``b`` and ``h`` and mark them as visited.
227+
198228
```swift
199-
queue.dequeue(a)
229+
queue.dequeue() // a
200230
queue.enqueue(b)
201231
b.visited = true
202232
queue.enqueue(h)
203233
h.visited = true
204234
```
235+
205236
The queue is now ``[ b, h ]``. Dequeue ``b`` and enqueue the neighbor node ``c`` mark it as visited. Remove the edge between ``b`` to ``h`` because ``h`` has already been visited.
237+
206238
```swift
207-
queue.dequeue(b)
239+
queue.dequeue() // b
208240
queue.enqueue(c)
209241
c.visited = true
210242
b.removeEdgeTo(h)
211243
```
244+
212245
The queue is now ``[ h, c ]``. Dequeue ``h`` and enqueue the neighbor nodes ``g`` and ``i`` and mark them as visited.
246+
213247
```swift
214-
queue.dequeue(h)
248+
queue.dequeue() // h
215249
queue.enqueue(g)
216250
g.visited = true
217251
queue.enqueue(i)
218252
i.visited = true
219253
```
254+
220255
The queue is now ``[ c, g, i ]``. Dequeue ``c`` and enqueue the neighbor nodes ``d`` and ``f`` and mark them as visited. Remove the edge between ``c`` to ``i`` because ``i`` has already been visited.
256+
221257
```swift
222-
queue.dequeue(c)
258+
queue.dequeue() // c
223259
queue.enqueue(d)
224260
d.visited = true
225261
queue.enqueue(f)
226262
f.visited = true
227263
c.removeEdgeTo(i)
228264
```
265+
229266
The queue is now ``[ g, i, d, f ]``. Dequeue ``g`` and remove the edges between ``g`` to ``f`` and ``g`` to ``i`` because ``f`` and ``i`` have already been visited.
267+
230268
```swift
231-
queue.dequeue(g)
269+
queue.dequeue() // g
232270
g.removeEdgeTo(f)
233271
g.removeEdgeTo(i)
234272
```
273+
235274
The queue is now ``[ i, d, f ]``. Dequeue ``i``.
275+
236276
```swift
237-
queue.dequeue(i)
277+
queue.dequeue() // i
238278
```
279+
239280
The queue is now ``[ d, f ]``. Dequeue ``d`` and enqueue the neighbor node ``e`` mark it as visited. Remove the edge between ``d`` to ``f`` because ``f`` has already been visited.
281+
240282
```swift
241-
queue.dequeue(d)
283+
queue.dequeue() // d
242284
queue.enqueue(e)
243285
e.visited = true
244286
d.removeEdgeTo(f)
245287
```
288+
246289
The queue is now ``[ f, e ]``. Dequeue ``f``. Remove the edge between ``f`` to ``e`` because ``e`` has already been visited.
290+
247291
```swift
248-
queue.dequeue(f)
292+
queue.dequeue() // f
249293
f.removeEdgeTo(e)
250294
```
295+
251296
The queue is now ``[ e ]``. Dequeue ``e``.
297+
252298
```swift
253-
queue.dequeue(e)
299+
queue.dequeue() // e
254300
```
255-
The queue is now empty which means the minimum spanning tree has been computed.
301+
302+
The queue is now empty, which means the minimum spanning tree has been computed.
256303

257304
Here's the code:
305+
258306
```swift
259307
func breadthFirstSearchMinimumSpanningTree(graph: Graph, source: Node) -> Graph {
260308
let minimumSpanningTree = graph.duplicate()
@@ -280,7 +328,11 @@ func breadthFirstSearchMinimumSpanningTree(graph: Graph, source: Node) -> Graph
280328
return minimumSpanningTree
281329
}
282330
```
331+
332+
This function returns a new `Graph` object that describes just the minimum spanning tree. In the figure, that would be the graph containing just the bold edges.
333+
283334
Put this code in a playground and test it like so:
335+
284336
```swift
285337
let graph = Graph()
286338

@@ -331,6 +383,7 @@ print(minimumSpanningTree) // [node: a edges: ["b", "h"]]
331383
// [node: d edges: ["e"]]
332384
// [node: h edges: ["g", "i"]]
333385
```
386+
334387
## See also
335388

336389
[Graph](../Graph/), [Tree](../Tree/), [Queues](../Queue/), [Shortest Path](../Shortest Path/), [Minimum Spanning Tree](../Minimum Spanning Tree/).

0 commit comments

Comments
 (0)