Breadth-First Search, known as BFS, is one of the most important algorithms for exploring graphs and trees. While DFS goes deep into one branch before returning, BFS takes a much wider and more organized approach. It explores nodes level by level, almost like waves spreading out from a starting point. Because of this behaviour, BFS is often used when we want the shortest path or when we need to visit all nodes in increasing order of distance.
with hands-on learning.
get the skills and confidence to land your next move.
BFS appears in many real situations. For example, social networks use BFS to measure how close one person is to another. Navigation apps use it to find short routes, and computer games use it to explore maps in a clear and predictable pattern. Learning BFS helps beginners understand queues, graph traversal, and systematic searching. It also gives Swift learners confidence when handling more complex structures later on.
Program 1: Basic BFS Using a Queue
This first program introduces BFS with a simple queue and an adjacency-list graph. It focuses on showing the main idea clearly so beginners can follow how nodes are visited level by level.
import Foundation
func bfs(_ graph: [Int: [Int]], start: Int) {
var queue: [Int] = [start]
var visited = Set<Int>()
visited.insert(start)
while !queue.isEmpty {
let node = queue.removeFirst()
print(node)
if let neighbors = graph[node] {
for n in neighbors {
if !visited.contains(n) {
visited.insert(n)
queue.append(n)
}
}
}
}
}
let graph1: [Int: [Int]] = [
1: [2, 3],
2: [4, 5],
3: [6],
4: [],
5: [],
6: []
]
bfs(graph1, start: 1)This code uses a standard queue structure. The first node added becomes the first processed, then its neighbors are added to the end of the queue. This creates the “level order” effect, which makes BFS reliable for shortest-path situations. Beginners often appreciate this program because the flow is easy to see and the output matches the natural expansion of a graph.
Program 2: BFS on a Tree
This version applies BFS to a simple tree structure. Many Swift developers use trees in apps, such as menu systems or hierarchical data, so this makes the example more practical.
import Foundation
class TreeNode {
var value: Int
var children: [TreeNode]
init(_ value: Int, _ children: [TreeNode] = []) {
self.value = value
self.children = children
}
}
func bfsTree(_ root: TreeNode) {
var queue: [TreeNode] = [root]
while !queue.isEmpty {
let node = queue.removeFirst()
print(node.value)
for child in node.children {
queue.append(child)
}
}
}
let root = TreeNode(1, [
TreeNode(2, [
TreeNode(4),
TreeNode(5)
]),
TreeNode(3, [
TreeNode(6)
])
])
bfsTree(root)Tree-based BFS is simple because each node naturally has children that you place in the queue. This offers a very intuitive level-order traversal, which is useful for tasks like printing nodes in a neat sequence or performing checks on each layer of a tree.
Program 3: BFS With Distance Tracking
This version keeps track of the distance from the start node to each visited node. It is useful for shortest-path problems when every edge has the same weight.
import Foundation
func bfsDistance(_ graph: [Int: [Int]], start: Int) {
var queue: [Int] = [start]
var distance: [Int: Int] = [start: 0]
while !queue.isEmpty {
let node = queue.removeFirst()
let currentDistance = distance[node] ?? 0
print("Node \(node) at distance \(currentDistance)")
if let neighbors = graph[node] {
for n in neighbors {
if distance[n] == nil {
distance[n] = currentDistance + 1
queue.append(n)
}
}
}
}
}
let graph2: [Int: [Int]] = [
1: [2, 3],
2: [4],
3: [5, 6],
4: [],
5: [],
6: []
]
bfsDistance(graph2, start: 1)By storing distances, this program shows how BFS naturally produces the shortest path in an unweighted graph. Beginners find this version very helpful because it connects theory with real-world uses such as routing, game maps, and network analysis.
Program 4: BFS With Path Reconstruction
This program not only explores the graph but also rebuilds the shortest path from the start node to a target node. This mirrors how navigation systems work behind the scenes.
import Foundation
func bfsPath(_ graph: [Int: [Int]], start: Int, target: Int) {
var queue: [Int] = [start]
var parent: [Int: Int] = [:]
parent[start] = -1
while !queue.isEmpty {
let node = queue.removeFirst()
if node == target {
var path: [Int] = []
var current: Int? = target
while current != -1 {
if let c = current {
path.append(c)
current = parent[c]
}
}
print("Shortest path:", path.reversed())
return
}
if let neighbors = graph[node] {
for n in neighbors {
if parent[n] == nil {
parent[n] = node
queue.append(n)
}
}
}
}
print("No path found.")
}
let graph3: [Int: [Int]] = [
1: [2, 3],
2: [4, 5],
3: [6],
4: [],
5: [],
6: []
]
bfsPath(graph3, start: 1, target: 5)Path reconstruction is a powerful technique because it turns the BFS exploration into a real solution. Beginners enjoy this example because it shows how to produce something meaningful, such as a route from point A to point B.
Program 5: BFS as a Swift Extension
This final program packages BFS into a convenient Swift extension. It allows any integer-keyed graph dictionary to call BFS directly, making the code feel clean and modern.
import Foundation
extension Dictionary where Key == Int, Value == [Int] {
func bfs(start: Int) {
var visited = Set<Int>()
var queue: [Int] = [start]
visited.insert(start)
while !queue.isEmpty {
let node = queue.removeFirst()
print(node)
if let neighbors = self[node] {
for n in neighbors {
if !visited.contains(n) {
visited.insert(n)
queue.append(n)
}
}
}
}
}
}
let graph4: [Int: [Int]] = [
1: [2, 3],
2: [4, 5],
3: [6],
4: [],
5: [],
6: []
]
graph4.bfs(start: 1)This extension-based approach is great for real projects because it keeps your code neat and reusable. It also helps beginners see how algorithms can be wrapped in Swift extensions to make them feel like natural features of the language.
Frequently Asked Questions (FAQ)
This section answers some common questions that new Swift learners often ask when starting with BFS.
Q1. Why does BFS use a queue?
Because a queue processes elements in the order they were added, which helps BFS visit nodes level by level.
Q2. Is BFS used for shortest paths?
Yes, BFS finds the shortest path in graphs where all edges have the same weight.
Q3. Can BFS handle cycles?
It can, as long as you use a visited set to prevent loops.
Q4. Does BFS work on trees and graphs?
Absolutely. Trees are a special kind of graph, so BFS works perfectly on both.
Q5. Is BFS faster than DFS?
In general, both have similar time complexity, but BFS handles shortest paths better, while DFS is stronger for deep exploration.
Conclusion
Breadth-First Search is one of the most friendly and useful algorithms for beginners learning Swift. By exploring nodes in clear layers, it becomes a natural tool for shortest-path problems, level-order traversal, and many everyday tasks in computing. Through the different programs you explored here—basic queue BFS, tree BFS, distance tracking, path reconstruction, and Swift extensions—you now have a full picture of how flexible and powerful this algorithm can be. The best way to grow comfortable with BFS is to try it on your own graphs and experiment with different structures. With practice, BFS will soon feel like an old friend in your Swift programming journey.




