You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardexpand all lines: Breadth-First Search/README.markdown
+3-255
Original file line number
Diff line number
Diff line change
@@ -144,263 +144,11 @@ print(nodesExplored)
144
144
145
145
This will output: `["a", "b", "c", "d", "e", "f", "g", "h"]`
146
146
147
-
## Applications
147
+
## What is BFS good for?
148
148
149
149
Breadth-first search can be used to solve many problems. A small selection:
150
150
151
-
* Computing the shortest path between a source node and each of the other nodes (only for unweighted graphs).
152
-
* Calculating the minimum spanning tree on an unweighted graph.
153
-
154
-
## Shortest path example
155
-
156
-
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.
157
-
158
-
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``.
159
-
160
-
```swift
161
-
queue.enqueue(a)
162
-
a.distance=0
163
-
```
164
-
165
-
The queue is now ``[ a ]``. Dequeue ``a`` and enqueue its two neighbor nodes ``b`` and ``c`` with a distance of ``1``.
166
-
167
-
```swift
168
-
queue.dequeue() // a
169
-
queue.enqueue(b)
170
-
b.distance= a.distance+1// result: 1
171
-
queue.enqueue(c)
172
-
c.distance= a.distance+1// result: 1
173
-
```
174
-
175
-
The queue is now ``[ b, c ]``. Dequeue ``b`` and enqueue `b`'s neighbor nodes ``d`` and ``e`` with a distance of ``2``.
176
-
177
-
```swift
178
-
queue.dequeue() // b
179
-
queue.enqueue(d)
180
-
d.distance= b.distance+1// result: 2
181
-
queue.enqueue(e)
182
-
e.distance= b.distance+1// result: 2
183
-
```
184
-
185
-
Continue until the queue is empty to calculate the shortest path to all other nodes.
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.
228
-
229
-
Let's calculate the minimum spanning tree for the following graph:
*Note: the minimum spanning tree is represented by the bold edges.*
234
-
235
-
Start with the source node ``a`` and add it to a queue and mark it as visited.
236
-
237
-
```swift
238
-
queue.enqueue(a)
239
-
a.visited=true
240
-
```
241
-
242
-
The queue is now ``[ a ]``. Dequeue ``a`` and enqueue its immediate neighbor nodes ``b`` and ``h`` and mark them as visited.
243
-
244
-
```swift
245
-
queue.dequeue() // a
246
-
queue.enqueue(b)
247
-
b.visited=true
248
-
queue.enqueue(h)
249
-
h.visited=true
250
-
```
251
-
252
-
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.
253
-
254
-
```swift
255
-
queue.dequeue() // b
256
-
queue.enqueue(c)
257
-
c.visited=true
258
-
b.removeEdgeTo(h)
259
-
```
260
-
261
-
The queue is now ``[ h, c ]``. Dequeue ``h`` and enqueue the neighbor nodes ``g`` and ``i`` and mark them as visited.
262
-
263
-
```swift
264
-
queue.dequeue() // h
265
-
queue.enqueue(g)
266
-
g.visited=true
267
-
queue.enqueue(i)
268
-
i.visited=true
269
-
```
270
-
271
-
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.
272
-
273
-
```swift
274
-
queue.dequeue() // c
275
-
queue.enqueue(d)
276
-
d.visited=true
277
-
queue.enqueue(f)
278
-
f.visited=true
279
-
c.removeEdgeTo(i)
280
-
```
281
-
282
-
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.
283
-
284
-
```swift
285
-
queue.dequeue() // g
286
-
g.removeEdgeTo(f)
287
-
g.removeEdgeTo(i)
288
-
```
289
-
290
-
The queue is now ``[ i, d, f ]``. Dequeue ``i``.
291
-
292
-
```swift
293
-
queue.dequeue() // i
294
-
```
295
-
296
-
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.
297
-
298
-
```swift
299
-
queue.dequeue() // d
300
-
queue.enqueue(e)
301
-
e.visited=true
302
-
d.removeEdgeTo(f)
303
-
```
304
-
305
-
The queue is now ``[ f, e ]``. Dequeue ``f``. Remove the edge between ``f`` to ``e`` because ``e`` has already been visited.
306
-
307
-
```swift
308
-
queue.dequeue() // f
309
-
f.removeEdgeTo(e)
310
-
```
311
-
312
-
The queue is now ``[ e ]``. Dequeue ``e``.
313
-
314
-
```swift
315
-
queue.dequeue() // e
316
-
```
317
-
318
-
The queue is now empty, which means the minimum spanning tree has been computed.
let sourceInMinimumSpanningTree = minimumSpanningTree.findNodeWithLabel(source.label)
328
-
queue.enqueue(sourceInMinimumSpanningTree)
329
-
sourceInMinimumSpanningTree.visited=true
330
-
331
-
whilelet current = queue.dequeue() {
332
-
for edge in current.neighbors {
333
-
let neighborNode = edge.neighbor
334
-
if!neighborNode.visited {
335
-
neighborNode.visited=true
336
-
queue.enqueue(neighborNode)
337
-
} else {
338
-
current.remove(edge)
339
-
}
340
-
}
341
-
}
342
-
343
-
return minimumSpanningTree
344
-
}
345
-
```
346
-
347
-
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.
348
-
349
-
Put this code in a playground and test it like so:
350
-
351
-
```swift
352
-
let graph =Graph()
353
-
354
-
let nodeA = graph.addNode("a")
355
-
let nodeB = graph.addNode("b")
356
-
let nodeC = graph.addNode("c")
357
-
let nodeD = graph.addNode("d")
358
-
let nodeE = graph.addNode("e")
359
-
let nodeF = graph.addNode("f")
360
-
let nodeG = graph.addNode("g")
361
-
let nodeH = graph.addNode("h")
362
-
let nodeI = graph.addNode("i")
363
-
364
-
graph.addEdge(nodeA, neighbor: nodeB)
365
-
graph.addEdge(nodeA, neighbor: nodeH)
366
-
graph.addEdge(nodeB, neighbor: nodeA)
367
-
graph.addEdge(nodeB, neighbor: nodeC)
368
-
graph.addEdge(nodeB, neighbor: nodeH)
369
-
graph.addEdge(nodeC, neighbor: nodeB)
370
-
graph.addEdge(nodeC, neighbor: nodeD)
371
-
graph.addEdge(nodeC, neighbor: nodeF)
372
-
graph.addEdge(nodeC, neighbor: nodeI)
373
-
graph.addEdge(nodeD, neighbor: nodeC)
374
-
graph.addEdge(nodeD, neighbor: nodeE)
375
-
graph.addEdge(nodeD, neighbor: nodeF)
376
-
graph.addEdge(nodeE, neighbor: nodeD)
377
-
graph.addEdge(nodeE, neighbor: nodeF)
378
-
graph.addEdge(nodeF, neighbor: nodeC)
379
-
graph.addEdge(nodeF, neighbor: nodeD)
380
-
graph.addEdge(nodeF, neighbor: nodeE)
381
-
graph.addEdge(nodeF, neighbor: nodeG)
382
-
graph.addEdge(nodeG, neighbor: nodeF)
383
-
graph.addEdge(nodeG, neighbor: nodeH)
384
-
graph.addEdge(nodeG, neighbor: nodeI)
385
-
graph.addEdge(nodeH, neighbor: nodeA)
386
-
graph.addEdge(nodeH, neighbor: nodeB)
387
-
graph.addEdge(nodeH, neighbor: nodeG)
388
-
graph.addEdge(nodeH, neighbor: nodeI)
389
-
graph.addEdge(nodeI, neighbor: nodeC)
390
-
graph.addEdge(nodeI, neighbor: nodeG)
391
-
graph.addEdge(nodeI, neighbor: nodeH)
392
-
393
-
let minimumSpanningTree =breadthFirstSearchMinimumSpanningTree(graph, source: nodeA)
394
-
395
-
print(minimumSpanningTree) // [node: a edges: ["b", "h"]]
Copy file name to clipboardexpand all lines: Minimum Spanning Tree/MinimumSpanningTree.playground/Pages/Minimum spanning tree example.xcplaygroundpage/Contents.swift
0 commit comments