Understanding Queue Operations & Implementation
From Riyadh to Makkah: Programming Breadth-First Searchdeque([start]) - Initialize queuequeue.popleft() - Dequeue (FIFO)queue.append() - Enqueue (add to back)len(queue) - Check if emptydeque - Efficient double-ended queueset - Fast lookup for visited citiesdict - Parent mapping for path reconstructionfrom collections import deque
def bfs_shortest_path(graph, start, goal):
"""
Find shortest path using BFS (Breadth-First Search)
Args:
graph: dict of city connections {city: [neighbors]}
start: starting city name (string)
goal: destination city name (string)
Returns:
list: path from start to goal (shortest in terms of hops)
None: if no path exists
Time Complexity: O(V + E) where V=vertices, E=edges
Space Complexity: O(V) for queue and visited set
"""
# Step 1: Initialize data structures
queue = deque([start]) # FIFO queue for BFS
visited = set([start]) # Track visited cities
parent = {start: None} # Track parent for path reconstruction
print(f"π Starting BFS from {start} to {goal}")
print(f"π Initial queue: {list(queue)}")
# Step 2: BFS main loop
while queue:
# Dequeue: Remove first city from queue (FIFO)
current = queue.popleft()
print(f"\nπ Processing: {current}")
print(f"π Queue after dequeue: {list(queue)}")
# Step 3: Check if goal reached
if current == goal:
print(f"π― Goal {goal} found!")
# Reconstruct path by following parent pointers
path = []
temp = current
while temp is not None:
path.append(temp)
temp = parent[temp]
return path[::-1] # Reverse to get startβgoal order
# Step 4: Explore all neighbors of current city
neighbors = graph.get(current, [])
print(f"π Exploring neighbors of {current}: {neighbors}")
for neighbor in neighbors:
if neighbor not in visited:
# Mark as visited to avoid cycles
visited.add(neighbor)
# Set parent for path reconstruction
parent[neighbor] = current
# Enqueue: Add to back of queue
queue.append(neighbor)
print(f" β Added {neighbor} to queue (via {current})")
print(f"π Queue after exploring {current}: {list(queue)}")
print(f"β
Visited cities: {visited}")
print(f"β No path found from {start} to {goal}")
return None # No path exists
def print_bfs_analysis(graph, start, goal):
"""Run BFS with detailed analysis"""
print("="*60)
print("π§ BFS ALGORITHM ANALYSIS")
print("="*60)
path = bfs_shortest_path(graph, start, goal)
if path:
print(f"\nπ SUCCESS! Path found: {' β '.join(path)}")
print(f"π Path length: {len(path) - 1} hops")
print(f"ποΈ Cities in path: {len(path)}")
else:
print(f"\nπ No path exists from {start} to {goal}")
# Our Saudi cities network (same as visual demo)
cities_graph = {
'Riyadh': ['Qassim', 'Jeddah'], # Capital city: 2 connections
'Qassim': ['Riyadh', 'Medina'], # Central region: 2 connections
'Medina': ['Qassim', 'Jeddah'], # Holy city: 2 connections
'Jeddah': ['Riyadh', 'Medina', 'Makkah'], # Port city: 3 connections
'Makkah': ['Jeddah'] # Holy city: 1 connection
}
# Example usage
if __name__ == "__main__":
print_bfs_analysis(cities_graph, 'Riyadh', 'Makkah')
# Try different start/goal combinations
print("\n" + "="*40)
print("π TESTING OTHER ROUTES")
print("="*40)
test_cases = [
('Riyadh', 'Medina'),
('Qassim', 'Makkah'),
('Medina', 'Riyadh')
]
for start, goal in test_cases:
path = bfs_shortest_path(cities_graph, start, goal)
result = f"{' β '.join(path)}" if path else "No path"
print(f"π {start} to {goal}: {result}")
This shows exactly what you'll see when running the Python code:
$ python bfs_search.py
============================================================
π§ BFS ALGORITHM ANALYSIS
============================================================
π Starting BFS from Riyadh to Makkah
π Initial queue: ['Riyadh']
π Processing: Riyadh
π Queue after dequeue: []
π Exploring neighbors of Riyadh: ['Qassim', 'Jeddah']
β Added Qassim to queue (via Riyadh)
β Added Jeddah to queue (via Riyadh)
π Queue after exploring Riyadh: ['Qassim', 'Jeddah']
β
Visited cities: {'Riyadh', 'Qassim', 'Jeddah'}
π Processing: Qassim
π Queue after dequeue: ['Jeddah']
π Exploring neighbors of Qassim: ['Riyadh', 'Medina']
β Added Medina to queue (via Qassim)
π Queue after exploring Qassim: ['Jeddah', 'Medina']
β
Visited cities: {'Riyadh', 'Qassim', 'Jeddah', 'Medina'}
π Processing: Jeddah
π Queue after dequeue: ['Medina']
π Exploring neighbors of Jeddah: ['Riyadh', 'Medina', 'Makkah']
β Added Makkah to queue (via Jeddah)
π Queue after exploring Jeddah: ['Medina', 'Makkah']
β
Visited cities: {'Riyadh', 'Qassim', 'Jeddah', 'Medina', 'Makkah'}
π Processing: Medina
π Queue after dequeue: ['Makkah']
π Exploring neighbors of Medina: ['Qassim', 'Jeddah']
π Queue after exploring Medina: ['Makkah']
β
Visited cities: {'Riyadh', 'Qassim', 'Jeddah', 'Medina', 'Makkah'}
π Processing: Makkah
π Queue after dequeue: []
π― Goal Makkah found!
π SUCCESS! Path found: Riyadh β Jeddah β Makkah
π Path length: 2 hops
ποΈ Cities in path: 3
========================================
π TESTING OTHER ROUTES
========================================
π Riyadh to Medina: Riyadh β Qassim β Medina
π Qassim to Makkah: Qassim β Riyadh β Jeddah β Makkah
π Medina to Riyadh: Medina β Qassim β Riyadh
Try these modifications to deepen your understanding: