Searching Algorithms (BFS, DFS, DLS, UCS)
Searching Algorithms (BFS, DFS, DLS, UCS)
Search (BFS)
Introduction to Breadth-First Search (BFS)
Definition: Breadth-First Search (BFS) is an algorithm used to traverse or search
through graph or tree data structures.
Traversal Approach: BFS explores nodes layer by layer, starting at a root node and
visiting all of its immediate neighbors before moving deeper into the structure.
Core Mechanism: BFS uses a queue data structure to manage nodes, ensuring it
explores each level completely before moving to the next.
Typical Use: Commonly used for finding the shortest path in unweighted graphs and
performing level-order traversal in trees.
Why We Use BFS
Shortest Path:
● BFS is ideal for finding the shortest path in unweighted graphs, where each step between nodes has the same
"cost."
● Example: Finding the shortest route between cities in an unweighted road network.
Level-Order Traversal:
● BFS visits nodes level by level, making it especially useful in scenarios requiring a broad, systematic approach.
● Example: In organizational charts, where BFS can process each hierarchy level in order.
Connected Components:
● BFS can identify all nodes connected to a starting node, making it useful for finding clusters or connected
groups in undirected graphs.
● Example: Discovering all members in a social network who are directly or indirectly connected.
When to Use BFS
Closer Solutions: When the solution or target node is likely closer to the root, BFS
will typically locate it faster than Depth-First Search (DFS).
Complete Exploration: BFS visits every reachable node from the starting point,
which ensures no parts of the graph are left unexplored in connected components.
Pros and Cons of BFS
Advantages Disadvantages
Shortest Path: Finds shortest path in unweighted Memory Usage: Stores entire levels at once, which
graphs can consume more memory
Level-Order Traversal: Visits nodes layer by layer Performance: Can be slower for very deep trees or
large graphs
Good for locating nodes near the root Not Depth-Optimal: May be inefficient for deep trees
or far-off solutions
BFS Traversal Example in a Tree
Let's consider the following binary tree as an example of BFS traversal:
Steps for BFS Traversal
1. Start from the root node 1.
2. Visit 1's children: 2 and 3.
3. Move to the next level and visit the children of 2 and 3: 4, 5, and 6.
This approach continues until all levels are traversed. The queue data structure stores nodes temporarily until they
are fully explored.
BFS Pseudo-Code
Here’s an example of BFS pseudo-code, using a queue to manage the nodes.
Real-World Applications of BFS
Social Networks
GPS Navigation
AI and Games
Applications:
Traversal Approach: DFS explores nodes by diving deep into one path until it
reaches a dead-end (or the goal), then it backtracks to explore other paths.
Core Mechanism: DFS uses a stack data structure, often implemented with
recursion, to keep track of nodes. This stack-like behavior allows it to backtrack and
continue exploring unexplored paths.
Typical Use: DFS is commonly used in scenarios where we need to explore all
possible paths or detect cycles in graphs.
Why We Use DFS
Path Exploration:
● DFS is ideal for exploring all paths in a graph or tree to their depths, useful for understanding entire structures
or configurations.
● Example: Navigating through a maze, where we explore each path deeply before trying another.
Detecting Cycles:
● DFS helps in detecting cycles within graphs, which is especially useful in detecting deadlocks in computer
systems and dependencies in dependency graphs.
● Example: Checking for circular dependencies in package management.
Topological Sorting:
● In directed acyclic graphs (DAGs), DFS helps produce a topological order, which is essential in task scheduling
and resolving dependencies.
● Example: Course prerequisites where some courses must be taken before others.
When to Use DFS
● Deep Solutions: DFS is efficient when solutions or goals are expected to be far
from the starting node or root, as it explores depth-first.
● Space Efficiency: In general, DFS requires less memory than BFS, especially
when implemented recursively, as it doesn’t store entire levels.
● Complete Path Exploration: DFS ensures that each path from a starting point
is fully explored, making it useful for tasks that require complete examination.
Pros and Cons of DFS
Advantages Disadvantages
Memory Efficient: Typically requires less memory than Not Optimal for Shortest Path: DFS may not yield the
BFS due to recursive implementation shortest path in unweighted graphs
Full Path Exploration: Useful for tasks that need Risk of Infinite Loops: Can get stuck in cycles if not
every path explored handled properly in graphs
Works Well for Deep Solutions May Miss Closer Solutions: DFS could miss closer
solutions by going deep into other branches
DFS Traversal Example in a Tree
Let's consider the following binary tree as an example of DFS traversal:
Steps for DFS Traversal (Pre-order example):
Steps for DFS Traversal (Pre-order example):
This approach continues until all nodes are visited. The stack data structure, which can be a call stack in recursion, temporarily stores nodes until
they’re fully explored.
DFS Pseudo-Code
Here’s an example of DFS pseudo-code using recursion, which mimics a
stack:
Real-World Applications of DFS
Maze and Puzzle Solving
Cycle Detection
● Use: Identify cycles in graphs, which is essential in deadlock detection or finding circular dependencies.
● Example: Detecting deadlocks in an operating system.
● Benefit: Efficient in cycle detection by visiting each node only once.
Real-World Applications of DFS
Topological Sorting
Applications:
● DLS limits the depth of exploration, which is useful when we know that the solution lies within a specific depth
range.
● Example: Searching for a file within a folder structure only to a certain folder depth.
● In graphs with cycles, DLS prevents infinite loops by restricting the depth, unlike DFS, which could get trapped
in cycles.
● Example: In an AI game, limiting the search depth can prevent endlessly evaluating repeating states.
● By limiting the search depth, DLS is often more memory-efficient than DFS, which continues exploring until all
nodes are visited.
● Example: In large graphs where deep exploration is memory-intensive, limiting depth conserves resources.
When to Use DLS
Known Depth Range: When the solution is known or suspected to be within a certain
depth, DLS is efficient and avoids unnecessary exploration.
Infinite or Cyclic Graphs: In structures where cycles or repeated paths are possible,
DLS prevents infinite exploration by limiting depth.
Prevents Infinite Loops: Limits depth to avoid cycles Incomplete: Might miss solutions beyond the depth
limit
Memory Efficient: Uses less memory than DFS when Solution Depth Dependent: Requires prior knowledge
depth is constrained or estimation of depth
Control Over Exploration Depth Suboptimal for Deep Solutions: Misses solutions at
greater depths without increasing limit
DLS Traversal Example in a Tree
Consider the following binary tree and a depth limit of 2 as an example of DLS traversal:
Steps for DFS Traversal (Pre-order example):
Steps for DLS Traversal (with depth limit 2):
Since the depth limit is 2, nodes beyond this level are not explored.
4. Starting Point: Begin at the root node 1 with a depth counter set to zero.
5. Depth-Limited Exploration: Traverse each branch until the depth limit is reached, then backtrack.
6. Stop at Limit: When the depth limit is reached, stop further exploration in that branch.
This approach prevents exploring beyond a certain level, making DLS useful when we need to restrict exploration within a fixed
range.
DLS Pseudo-Code
Here’s an example of DLS pseudo-code using recursion and a depth parameter to
limit the search.
This code limits depth by checking if the current depth exceeds the specified limit
before further exploration.
Real-World Applications of DLS
Limited-Depth Search in File Systems
● Use: Explore only parts of a graph within a certain depth to avoid memory issues.
● Example: Searching web links on a site up to a certain link depth to avoid excessive data.
● Benefit: Conserves memory by focusing only on nodes within a set depth.
Summary
Definition: DLS is a depth-first search with a predefined depth limit, exploring nodes up to that limit before
backtracking.
Applications:
Traversal Approach: UCS expands nodes with the lowest cumulative path cost first.
It uses a priority queue to keep track of nodes, ordering them by their path cost.
Core Mechanism: UCS leverages a priority queue to expand the least-cost node at
each step, making it an optimal choice for finding shortest paths when weights vary.
Typical Use: UCS is widely used for optimal pathfinding in weighted graphs, such as
in routing and navigation systems.
Why We Use UCS
Optimal Path in Weighted Graphs:
● UCS is ideal for finding the minimum-cost path in graphs where edges have different weights, unlike BFS, which
assumes uniform edge costs.
● Example: Determining the cheapest route between cities with roads of varying tolls.
● UCS is guaranteed to find the optimal path in terms of cost because it always expands the lowest-cost node
first.
● Example: Finding the shortest or least expensive path in logistics and supply chain networks.
● UCS functions optimally when all weights are non-negative, ensuring that it consistently finds the minimum
path without backtracking.
● Example: In transportation networks where distances or costs cannot be negative.
When to Use UCS
Weighted Graphs with Variable Costs: UCS is particularly useful in graphs where
edge weights vary, as it ensures that the least-cost path is found.
Optimal Pathfinding Requirements: UCS is ideal when it’s crucial to find the
optimal (least-cost) solution, as in routing or logistics.
Non-Negative Weights: UCS is best suited for graphs with non-negative weights
since negative weights can lead to suboptimal paths.
Pros and Cons of UCS
Advantages Disadvantages
Optimal Path: Finds the minimum-cost path in Memory Intensive: Stores many nodes in the priority
weighted graphs queue, especially in dense graphs
Handles Variable Weights: Works well where edge Slow for Large Graphs: Performance can be slow for
weights differ large or dense graphs
No Backtracking Required: Guaranteed to find the Not Suitable for Negative Weights: Fails with
optimal path without needing to revisit nodes negative-weight edges
UCS Traversal Example in a Weighted Graph
Consider the following weighted graph as an example for UCS traversal:
Each edge in the graph has a weight, shown by the numbers on each line. We will use UCS to find the lowest-cost path from node
(0) to node (2).
Steps for UCS Traversal
The goal here is to find the minimum-cost path from node 0 to node 2.
Starting Node:
● Begin at node 0 with a path cost of 0.
● Add nodes reachable from node 0 to the priority queue based on their costs:
○ Path to node 1 with cost 3.
○ Path to node 4 with cost 8.
○ Path to node 3 with cost 7.
Expand Node with Lowest Cost:
● Expand node 1 (current cost 3), as it has the lowest cost in the queue.
● From node 1, add paths to reachable nodes:
○ Path to node 2 with cumulative cost 4 (3 + 1).
○ Path to node 3 with cumulative cost 7 (3 + 4).
Continue Expanding Lowest Cost Paths:
● Now, expand node 2 (current cost 4), as it has the lowest cumulative cost.
● Node 2 is our goal node, so we stop the search.
UCS Traversal Result: The minimum-cost path from node 0 to node 2 is 0 -> 1 -> 2 with a cost of 4.
UCS Traversal Explained
Starting Point: Begin at node 0, adding paths from node 0 to all directly connected
nodes in a priority queue ordered by cumulative path cost.
Expand Nodes by Lowest Cost: At each step, expand the node with the lowest
cumulative path cost in the queue. This ensures that the UCS algorithm always
explores the least expensive path available.
Goal Node Check: When node 2 (the goal) is reached, the path and cost are
returned as it is guaranteed to be the least-cost path due to UCS's priority on
minimum cumulative cost.
This approach ensures that UCS finds the minimum-cost path in a weighted graph by
prioritizing nodes with the least cumulative path cost at each step.
UCS Pseudo-Code
Here’s an example of UCS pseudo-code using a priority queue to manage nodes, ensuring it expands the node with the
lowest path cost at each step.
This code finds the minimum-cost path in a weighted graph by ensuring that only the least-cost paths are explored.
Real-World Applications of UCS
Road Network Routing
● Use: Route packets through the internet with the lowest latency or cost.
● Example: Internet routing protocols can leverage UCS to find the most efficient paths.
● Benefit: Optimizes network speed by directing packets along the least-latency routes.
Resource Allocation in AI
● Weighted Pathfinding: Finds optimal paths in graphs with varying edge weights.
● Optimal Solution Requirements: Suitable for scenarios where the optimal (least-cost) solution is critical.
● Non-Negative Weights: Works best with non-negative weights, as it assumes positive cumulative path costs.
Applications: