For working professionals
For fresh graduates
More
2. Goals of AI
6. AI Websites
12. Spark AR Studio
16. Narrow AI
17. VR Games
18. Explainable AI
19. AI Companies
20. AI in Business
The A* Algorithm is a efficient and optimal pathfinding technique that finds the shortest route from start to goal by balancing path cost and estimated distance. The challenge lies in efficiently navigating complex environments where multiple paths exist. By exploring an A* algorithm example, you'll see how it simplifies search problems precisely.
This article offers a clear breakdown of A* Algorithm concepts, step-by-step implementation guidance, and real-world applications, emphasizing practical tips to enhance your understanding and improve problem-solving skills.
To master the A* algorithm, understanding two core ideas is essential: node list management and heuristic selection. Think of node lists as your algorithm’s memory — tracking which paths to explore and which to ignore. Meanwhile, the heuristic acts as its intuition, efficiently guiding the algorithm toward the goal.
Managing these elements well prevents inefficiencies in pathfinding applications, such as maze navigation, mapping, and even Al-based game character movements.
To make the most of node lists and heuristics, you need to understand how the A* algorithm evaluates each path — and that's where cost functions come in.
f(n) = g(n) + h(n)
This balance helps the algorithm pick smarter routes, avoiding detours and dead ends.
To ensure the A* algorithm explores paths efficiently, it relies on two essential lists — the Open List and the Closed List. Managing these lists properly can significantly improve the algorithm’s performance.
Open List: Tracking Unexplored Paths
The Open List holds nodes that are yet to be explored. Think of it as a queue of potential routes waiting to be evaluated. Each time the algorithm selects the most promising node — the one with the lowest f(n) value — that node is removed from the Open List.
Example: Imagine you're navigating a city map. The Open List would be like marking potential streets on your map — evaluating each based on distance and estimated travel time.
Closed List: Avoiding Unnecessary Backtracking
The Closed List keeps track of nodes that have already been explored. Once a node is processed, it's moved from the Open List to the Closed List, ensuring the algorithm doesn’t revisit the same path.
Example: Continuing the city map analogy, marking streets you've already walked down helps you avoid retracing your steps unnecessarily.
Why Node List Management Matters
Efficiently managing these lists ensures your A* algorithm doesn’t waste time exploring inefficient paths. Without proper list management, you risk endless loops or missed optimal routes.
If you’re looking to move beyond theory and apply Graph Algorithms to real life problems, check out upGrad’s computer science courses. Learn to implement algorithms efficiently, optimize large-scale solutions, and work on industry-impacting projects.
A heuristic is a guiding function that helps the A* algorithm estimate the remaining distance to the goal, improving path selection. While it aids in predicting the best path, it's not always perfectly accurate.
Choosing the right heuristic is crucial for efficiency and accuracy. Here are three common techniques:
Manhattan Distance
The Manhattan Distance is ideal for grid-based paths where movement is restricted to horizontal and vertical directions. It calculates the total number of steps needed to move between two points without diagonal movement.
Diagonal Distance
The Diagonal Distance is useful in environments that allow diagonal movement. It combines straight and diagonal steps to estimate the shortest path.
Euclidean Distance
The Euclidean Distance calculates the direct (straight-line) distance between two points. It’s ideal for open environments with no strict movement constraints.
Choosing the Right Heuristic
Selecting the right heuristic depends on your environment: ✅ For structured grids: Manhattan Distance ✅ For diagonal movement: Diagonal Distance ✅ For open spaces: Euclidean Distance
By understanding these techniques, you can apply the A* algorithm effectively, ensuring faster, more accurate pathfinding for your projects.
Also Read: All about Informed Search in Artificial Intelligence
Now that you've got the theory down, let's see the A* algorithm in action with a practical example that ties it all together.
The A* Algorithm is a popular pathfinding method used to find the shortest route between two points. It’s widely used in navigation systems, video games, and AI applications because it efficiently balances speed and accuracy.
By combining the path cost and heuristic values, A* calculates the Total Cost (f(n)):
f(n) = g(n) + h(n)
This dual evaluation allows A* to prioritize paths with the lowest total cost, calculated by combining the actual distance traveled and the estimated remaining distance to the goal. This ensures the algorithm efficiently selects the most promising routes.
A* algorithm Example: Finding the Shortest Route in a City
Imagine you’re driving from Point A (home) to Point B (office) in a busy city. Roads have different travel times, some faster but longer, others slower but shorter.
How A* Helps:
Step-by-Step Workflow
Pseudocode for A* Algorithm
function A_Star(start, goal)
open_list = {start}
closed_list = {}
g_score[start] = 0
f_score[start] = g_score[start] + heuristic(start, goal)
while open_list is not empty:
current = node with lowest f_score in open_list
if current == goal:
return reconstruct_path(current)
remove current from open_list
add current to closed_list
for each neighbor in current's neighbors:
if neighbor in closed_list:
continue
tentative_g = g_score[current] + distance(current, neighbor)
if neighbor not in open_list or tentative_g < g_score[neighbor]:
g_score[neighbor] = tentative_g
f_score[neighbor] = g_score[neighbor] + heuristic(neighbor, goal)
if neighbor not in open_list:
add neighbor to open_list
The A* Algorithm efficiently finds the shortest route—even in complex scenarios by combining real-time path costs with smart estimations. Its ability to adapt to dynamic conditions makes it a powerful tool for both AI systems and real-world navigation.
But how does A* hold up when compared to other popular search algorithms? Let's break it down.
Each algorithm has its strengths and weaknesses, and understanding these can help you choose the right one for your pathfinding needs.
Both A* and Dijkstra’s algorithms are known for finding the shortest path. However, A* adds a crucial layer of intelligence — the heuristic function — which makes it faster and more efficient in many cases.
Feature | A* Algorithm | Dijkstra's Algorithm |
Search Strategy | Uses both path cost (g(n)) and estimated distance (h(n)) for faster results | Relies solely on path cost (g(n)) |
Speed | Faster in large maps due to heuristic guidance | Slower as it explores all possible nodes |
Optimality | A* guarantees the shortest path if the heuristic is both admissible (never overestimates) and consistent (maintains cost order). | Guarantees the shortest path |
Best Use Case | Ideal for dynamic maps, gaming paths, and traffic navigation | Best for static graphs where all nodes must be explored |
Key Takeaway: While Dijkstra’s is thorough, A* strikes a better balance between speed and accuracy by focusing only on the most promising paths.
A* vs BFS, DFS, and Greedy Best-First Search
Compared to BFS, DFS, and Greedy Best-First Search algorithms, A* stands out for its balance of precision and performance. Here's how:
Algorithm | Search Focus | Efficiency | Optimal Path Guarantee |
A* | Combines path cost and heuristic | Highly efficient in complex environments | Yes (with admissible heuristic) |
BFS | Explores all nodes layer by layer | Slower in large maps | Yes (if no weighted nodes) |
DFS | Explores paths deeply before backtracking | Prone to getting stuck in deep paths | No |
Greedy Best-First Search | Focuses only on the heuristic (h(n)) | Fast but may miss optimal paths | No |
Key Takeaway: A* outshines BFS, DFS, and Greedy Best-First Search by combining the best elements of each — precision, speed, and optimality — making it ideal for dynamic pathfinding problems.
Also Read: Searching in Data Structure: Different Search Algorithms and Their Applications
Now that we’ve compared A* with other search strategies let's break down the A* algorithm step by step and see how it all comes together in practice.
The A* algorithm shines in scenarios where efficient pathfinding is crucial. Understanding three core elements — heuristic functions, graph, and node expansion strategies — is key to mastering A*.
The right combination of these factors allows A* to find the optimal path efficiently, even in complex and changing environments.
Let's break it down step by step.
In this phase, the groundwork for the entire A* algorithm is set up. Proper initialization ensures that the algorithm can efficiently search for the optimal path.
1. Set up the grid/graph structure:
2. Assign start and goal nodes:
3. Prepare the Open and Closed Lists:
4. Initialize Cost Variables:
Note: The goal of this phase is to set up the environment and make sure the initial conditions are correct before entering the main search loop.
This is the heart of the A* algorithm. In this phase, we repeatedly expand nodes, evaluate neighboring nodes, and calculate the optimal path towards the goal.
Note: This loop iterates over all the possible paths and consistently chooses the path that appears to be most promising based on the f(n) value. Efficiency in node expansion is key to A*’s success in pathfinding.
Once the goal node is reached, we need to reconstruct the optimal path by tracing back from the goal node to the start node. This is done by following the parent pointers of each node.
Note: Path reconstruction ensures that A* not only finds the goal node but also provides the optimal path to get there. The parent pointers maintain the relationship between the nodes, allowing us to trace the most efficient route.
Also Read: 10 Best Data Structures for Machine Learning Model Optimization in 2025
Implementing the A* algorithm in Python involves setting up the grid, evaluating nodes, managing priority queues, and visualizing the search process. This allows us to see how the algorithm efficiently finds the optimal path in a given environment.
This practical example will help you understand how each component of A* works to find the optimal path.
To begin, you'll need some Python libraries to help with our A* implementation. For this example, we'll use heapq for managing the priority queue, matplotlib for visualizing the search process, and numpy for handling grid creation.
Here's what you’ll do:
import heapq # Import heapq for managing the priority queue
import numpy as np # For creating grids and handling data structures
import matplotlib.pyplot as plt # For visualizing the search and pathfinding process
# Define a simple grid for the search space (0 is open, 1 is blocked)
grid = np.array([ [0, 0, 0, 1, 0],
[0, 1, 0, 1, 0],
[0, 1, 0, 0, 0],
[0, 0, 0, 1, 0],
[0, 0, 0, 0, 0]
])
# Coordinates for start and goal
start = (0, 0) # Start position
goal = (4, 4) # Goal position
Now, let’s define some helper functions for our grid and heuristics. We'll need:
1. Heuristic Function:
We’ll use Manhattan distance as the heuristic for this example. This is useful in grid-based pathfinding when diagonal movement is not allowed.
def heuristic(a, b):
"""Calculate Manhattan distance between points a and b."""
return abs(a[0] - b[0]) + abs(a[1] - b[1])
2. Valid Movement Check:
This function ensures that the node is within the bounds of the grid and not blocked.
def valid_move(node, grid):
"""Check if the node is within bounds and not blocked."""
x, y = node
if 0 <= x < grid.shape[0] and 0 <= y < grid.shape[1]:
return grid[x, y] == 0 # True if not blocked
return False
This is where we implement the core of the A* algorithm. We’ll:
Here’s the step-by-step implementation:
def a_star(start, goal, grid):
# Initialize the open list (priority queue) and closed list (set)
open_list = []
heapq.heappush(open_list, (0, start)) # (f(n), node)
came_from = {} # To store the optimal path
g_score = {start: 0} # Path cost to reach each node
f_score = {start: heuristic(start, goal)} # Estimated cost to goal from start
while open_list:
# Get the node with the lowest f_score
_, current = heapq.heappop(open_list)
# If we reach the goal, reconstruct the path
if current == goal:
path = []
while current in came_from:
path.append(current)
current = came_from[current]
path.append(start)
path.reverse() # Reverse to get path from start to goal
return path
# Explore neighbors
x, y = current
neighbors = [(x+1, y), (x-1, y), (x, y+1), (x, y-1)] # 4-connected grid movement
for neighbor in neighbors:
if valid_move(neighbor, grid):
tentative_g_score = g_score[current] + 1 # Cost from current to neighbor (1 step)
# If this path is better, record it
if neighbor not in g_score or tentative_g_score < g_score[neighbor]:
came_from[neighbor] = current
g_score[neighbor] = tentative_g_score
f_score[neighbor] = tentative_g_score + heuristic(neighbor, goal) #Updates the f-score by combining the g-score (cost so far) and the heuristic (estimated cost to goal)
heapq.heappush(open_list, (f_score[neighbor], neighbor))
return None # Return None if no path is found
Once we’ve implemented the algorithm, it’s time to visualize the search process. This will help us understand how A* explores the grid and how it finds the optimal path.
Let’s use matplotlib to display the grid, the path, and the nodes explored.
def plot_grid(grid, path=None):
"""Visualize the grid, path, and obstacles."""
plt.imshow(grid, cmap="Blues", origin="upper") # Display the grid with a color map
plt.imshow(grid == 1, cmap="Greys", origin="upper", alpha=0.6) # Overlay obstacles (value 1) in grey
if path:
path = np.array(path)
plt.plot(path[:, 1], path[:, 0], color="red", linewidth=3) # Path in red
plt.scatter(start[1], start[0], color="green", marker="o", s=100) # Start point
plt.scatter(goal[1], goal[0], color="yellow", marker="o", s=100) # Goal point
plt.show()
# Run the A* algorithm and visualize
path = a_star(start, goal, grid)
if path:
print("Path found:", path)
plot_grid(grid, path)
else:
print("No path found.")
Expected Output:
When you run the code above, you should see a grid with:
The output will also print the path as a list of coordinates.
For example, the output might look like this:
Path found: [(0, 0), (1, 0), (2, 0), (3, 0), (4, 0), (4, 1), (4, 2), (4, 3), (4, 4)]
Explanation:
With the A* algorithm now implemented and visualized, you can see how it effectively navigates through a grid, finding the optimal path even in the presence of obstacles.
Trouble grasping Python basics or unsure where to start? upGrad's free Basic Python Programming course offers clear explanations, hands-on practice, and practical examples to simplify learning. Get started today!
Grids are just the beginning. Now, let’s explore how A* can be adapted for non-grid environments, where paths are more dynamic and connections aren't as clearly defined.
Unlike a grid, where paths are defined by clear horizontal and vertical moves between cells, non-grid environments are often more complex, with paths determined by nodes and edges that can vary in connectivity and weight.
A few key differences include:
Now that we understand how non-grid environments differ, let’s look at how A* can be modified for graph-based systems.
When working with non-grid environments, here are some key factors to keep in mind for efficient and accurate A* implementation:
Adapting the A* algorithm to non-grid environments opens up a world of possibilities, from real-time traffic navigation to pathfinding in complex game terrains.
Also Read: What is Kruskal’s Algorithm? Steps, Examples, Overview
Now that we’ve explored the versatility of A* in dynamic environments, let’s see how it’s used in practice with real-world applications that demonstrate its power across industries.
A* has proven to be a powerful and efficient algorithm for finding optimal paths in complex, real-time environments. Whether in static or dynamic systems requiring real-time adjustments, A* offers versatility in solving pathfinding and search problems.
A* is used across various industries due to its flexibility and efficiency. Here's a look at some practical examples:
Industry | Application |
Robotics Path Planning | Boston Dynamics, Rethink Robotics: These companies use A* for autonomous robots to navigate dynamic environments, ensuring efficient pathfinding in real-time. |
Game Development | Valve (Half-Life 2), Blizzard (Starcraft 2): A* is applied in game development for AI characters to efficiently navigate complex game maps, ensuring smooth gameplay. |
Mapping Services | Google Maps, Waze, TomTom: A* helps in real-time navigation and dynamic route adjustments, optimizing travel time by analyzing traffic data and road conditions. |
Autonomous Vehicles | Waymo, Tesla: A* is used in autonomous vehicles to navigate roads, handle traffic, and adjust to road conditions dynamically, ensuring safe and efficient driving. |
Drones | DJI, Amazon (Prime Air): A* helps drones in pathfinding, avoiding obstacles, and optimizing flight routes for deliveries and other services. |
Logistics & Supply Chain | FedEx, UPS: A* optimizes delivery routes, enabling efficient fleet management and reducing delivery times. |
Geographic Information Systems (GIS) | ESRI: A* is used for mapping applications and spatial analysis, optimizing routes and providing detailed geographical insights. |
Healthcare | Surgical Robots: In robot-assisted surgeries, A* is used for pathfinding to navigate the operating field and perform precise, safe operations. |
These industries rely on A* for tasks that require finding optimal paths through complex, unpredictable, and sometimes dynamic environments. The algorithm’s efficiency in both static and dynamic systems is a key factor in its widespread adoption.
Problem: In cities with high traffic congestion, Google Maps faces the challenge of finding the optimal route in real-time. The difficulty lies in adjusting routes dynamically based on changing conditions, such as road closures or traffic accidents.
Solution: Google Maps integrated A* to help prioritize path cost and distance using real-time traffic data. This allows it to make accurate, dynamic adjustments to routes, improving overall navigation efficiency.
Implementation:
Results:
The real-world applications of A* demonstrate its remarkable versatility, from guiding autonomous vehicles through traffic to optimizing game AI.
Also Read: 12 Data Science Case Studies Across Industries
While A* excels in many areas, it's not without its challenges. Let’s dive into the advantages and limitations of A*, and discuss how to address them for optimal performance.
A* is widely used in pathfinding and search problems because it combines efficiency and optimality. Below is a list of the main advantages, challenges, and corresponding workarounds.
Advantages | Challenges | Workaround |
Optimality: Guarantees the shortest path with an admissible heuristic. | High Memory Usage: Storing nodes in the open and closed lists can be memory-intensive. | Use priority queues, hash maps, or A with limited memory*. |
Efficiency: Balances g(n) and h(n) to prioritize the best paths. | Performance with Poor Heuristics: A bad heuristic can make A* inefficient. | Refine the heuristic based on the problem (e.g., Euclidean or Manhattan). |
Versatility: Works in both static and dynamic environments. | Computational Complexity: A* can be slow with large, dense search spaces. | Use bi-directional search, pruning, or A variants* like D Lite*. |
Flexibility: Easily adapts to grid-based, graph-based, or non-grid search problems. | Handling Dynamic Changes: Frequent updates in dynamic environments can lead to inefficiency. | Use D Lite* or Theta* for dynamic path adjustments. |
Proven Efficiency: A* often outperforms other algorithms (like Dijkstra) by focusing on promising paths first. | Scalability Issues: A* struggles with very large or highly dynamic spaces. | Implement iterative deepening A* or hierarchical search to reduce space. |
A* is a robust and versatile algorithm, ideal for many pathfinding and search problems. However, optimizing its performance requires understanding its advantages and addressing the challenges through smart heuristics, memory management, and algorithmic enhancements.
Also Read: Real-Life DevOps Applications: Key Examples
upGrad has a global network of over 10 million learners. It offers industry-focused courses that teach practical skills for algorithms. These courses blend theory with hands-on experience, helping you apply graph algorithms to real life challenges.
With expert guidance and project-based learning, you gain the confidence to tackle complex graph problems.
Here are some of the top recommended courses:
Are you finding it difficult to decide which program suits your career goals? Consult upGrad’s expert counselors or visit an offline center to find a course that aligns with your goals!
Q. How does A* handle multiple potential paths in dynamic environments?
A. A* adapts by recalculating the optimal path when significant changes occur, such as road closures or accidents. It updates the heuristic and path costs only when triggered by these changes, ensuring efficient routing without constant recalculation, as seen in systems like navigation apps.
Q. What happens if the heuristic in an A* algorithm example is not admissible?
A. If the heuristic overestimates the cost, A* may still find a path, but it risks being suboptimal due to misleading path priorities. This is because the algorithm may ignore better paths due to incorrect cost estimates. Ensuring the heuristic is admissible is critical for A* to guarantee optimality.
Q. Can A* be used for pathfinding in 3D environments?
A. Yes, A* can be extended to 3D pathfinding by adjusting the grid or graph to account for three-dimensional movement. For example, in drone navigation or robotic path planning, A* calculates movement costs across a 3D grid, with additional layers for height or altitude.
Q. What are the challenges of using A* for real-time traffic navigation?
A. A* must continually update the edge weights to reflect real-time traffic data, requiring fast recalculations. Handling dynamic changes in the environment, like accidents or road closures, can cause A* to perform inefficiently unless optimized for real-time updates.
Q. How does A* deal with obstacles in dynamic environments, like moving obstacles?
A. A* can adapt to dynamic environments by recalculating paths as new obstacles appear. This requires integrating real-time data into the heuristic and constantly adjusting the search space, ensuring A* remains efficient and finds a clear path despite changes.
Q. How does A* perform in large search spaces with many obstacles?
A. In environments with numerous obstacles, A* can face performance issues due to the many nodes it needs to evaluate. Optimizing the heuristic and using advanced pruning techniques can help mitigate this by focusing on the most promising paths, reducing unnecessary exploration.
Q. How does A* differ when applied to graph-based routing compared to grid-based pathfinding?
A. In graph-based routing, A* evaluates paths between nodes connected by edges, where edge weights vary (e.g., distance or travel time). In contrast, grid-based pathfinding uses a fixed grid layout where each cell represents a node, and movement is restricted to horizontal and vertical directions. Graph-based routing allows for more flexibility in node connectivity and path weighting.
Q. What is the role of the open list and closed list in A*?
A. The open list holds nodes that are yet to be explored, prioritized by their f(n) value, while the closed list stores nodes that have already been evaluated. Proper management of these lists ensures A algorithm examples* can efficiently explore the most promising paths without retracing its steps.
Q. How does A* with limited memory work in large-scale environments?
A. In large-scale environments, A with limited memory* stores only the most relevant nodes, discarding others to manage memory usage. This can be achieved through techniques like iterative deepening A*, which limits memory use while still finding an optimal path, making it ideal for vast or complex search spaces.
Q. Can A* handle non-uniform grids, where movement cost differs between cells?
A. Yes, A* can handle non-uniform grids by adjusting the cost function (g(n)) to account for varying movement costs between cells. For example, certain cells (like forests or mountains) could have higher costs than others, and A* would incorporate this into its pathfinding process to find the optimal path through these varying costs.
Q. How does A* handle pathfinding in irregular terrains, like those encountered in gaming?
A. A* can adjust the pathfinding strategy in irregular terrains by incorporating custom heuristics and terrain difficulty factors. For instance, in gaming environments, A* might treat different types of terrain (e.g., water, mountains) as nodes with higher costs, ensuring that it navigates optimally based on the varying difficulty of traversal.
Author
Talk to our experts. We are available 7 days a week, 9 AM to 12 AM (midnight)
Indian Nationals
1800 210 2020
Foreign Nationals
+918045604032
1.The above statistics depend on various factors and individual results may vary. Past performance is no guarantee of future results.
2.The student assumes full responsibility for all expenses associated with visas, travel, & related costs. upGrad does not provide any a.