A(A-star)搜索是一种启发式搜索算法,通常用于路径查找和图搜索问题。它结合了Dijkstra算法的优点和最佳优先搜索的优点,通过使用启发式函数来引导搜索过程,使其能够更快地找到最短路径。以下是一个Java实现的A搜索算法的示例。
在这个示例中,我们将使用一个二维网格来表示搜索空间,每个网格单元可以是一个可通过的节点或障碍物。启发式函数将使用曼哈顿距离(在二维网格中,两个节点之间的水平和垂直距离之和)。
import java.util.*;
class Node implements Comparable<Node> {
int x, y, gCost, hCost, fCost;
Node parent;
public Node(int x, int y) {
this.x = x;
this.y = y;
this.gCost = 0;
this.hCost = 0;
this.fCost = 0;
this.parent = null;
}
@Override
public int compareTo(Node other) {
return Integer.compare(this.fCost, other.fCost);
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
Node node = (Node) obj;
return x == node.x && y == node.y;
}
@Override
public int hashCode() {
return Objects.hash(x, y);
}
}
public class AStarSearch {
private static final int[][] DIRECTIONS = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
private static final int OBSTACLE = 1;
private static final int EMPTY = 0;
public static List<Node> aStarSearch(int[][] grid, Node start, Node goal) {
PriorityQueue<Node> openSet = new PriorityQueue<>();
Set<Node> closedSet = new HashSet<>();
Map<Node, Node> cameFrom = new HashMap<>();
Map<Node, Integer> gScore = new HashMap<>();
start.gCost = 0;
start.hCost = heuristic(start, goal);
start.fCost = start.gCost + start.hCost;
openSet.add(start);
while (!openSet.isEmpty()) {
Node current = openSet.poll();
if (current.equals(goal)) {
return reconstructPath(cameFrom, current);
}
closedSet.add(current);
for (int[] direction : DIRECTIONS) {
int neighborX = current.x + direction[0];
int neighborY = current.y + direction[1];
if (neighborX < 0 || neighborX >= grid.length || neighborY < 0 || neighborY >= grid[0].length || grid[neighborX][neighborY] == OBSTACLE) {
continue;
}
Node neighbor = new Node(neighborX, neighborY);
if (closedSet.contains(neighbor)) {
continue;
}
int tentativeGCost = gScore.get(current) + 1;
if (!openSet.contains(neighbor) || tentativeGCost < gScore.getOrDefault(neighbor, Integer.MAX_VALUE)) {
cameFrom.put(neighbor, current);
gScore.put(neighbor, tentativeGCost);
neighbor.gCost = tentativeGCost;
neighbor.hCost = heuristic(neighbor, goal);
neighbor.fCost = neighbor.gCost + neighbor.hCost;
if (!openSet.contains(neighbor)) {
openSet.add(neighbor);
}
}
}
}
return Collections.emptyList(); // No path found
}
private static int heuristic(Node a, Node b) {
return Math.abs(a.x - b.x) + Math.abs(a.y - b.y); // Manhattan distance
}
private static List<Node> reconstructPath(Map<Node, Node> cameFrom, Node current) {
List<Node> path = new ArrayList<>();
while (current != null) {
path.add(current);
current = cameFrom.get(current);
}
Collections.reverse(path);
return path;
}
public static void main(String[] args) {
int[][] grid = {
{EMPTY, EMPTY, EMPTY, EMPTY, EMPTY},
{EMPTY, OBSTACLE, EMPTY, OBSTACLE, EMPTY},
{EMPTY, EMPTY, EMPTY, EMPTY, EMPTY},
{EMPTY, OBSTACLE, EMPTY, OBSTACLE, EMPTY},
{EMPTY, EMPTY, EMPTY, EMPTY, EMPTY}
};
Node start = new Node(0, 0);
Node goal = new Node(4, 4);
List<Node> path = aStarSearch(grid, start, goal);
if (!path.isEmpty()) {
System.out.println("Path found:");
for (Node node : path) {
System.out.println("(" + node.x + ", " + node.y + ")");
}
} else {
System.out.println("No path found.");
}
}
}
代码解释
-
Node 类:表示网格中的一个节点,包含坐标
(x, y)
,gCost
(从起点到当前节点的实际代价),hCost
(启发式代价),fCost
(总代价,gCost + hCost
),以及父节点parent
。 -
AStarSearch 类:包含A*搜索算法的实现。
-
aStarSearch 方法:这是A*搜索算法的核心。它使用优先队列
openSet
来存储待处理的节点,并根据节点的fCost
进行排序。closedSet
存储已经处理过的节点,cameFrom
用于路径重构,gScore
存储每个节点的gCost
。 -
heuristic 方法:计算启发式代价,这里使用曼哈顿距离。
-
reconstructPath 方法:根据
cameFrom
映射重构路径。 -
main 方法:定义了一个简单的网格,并调用
aStarSearch
方法查找从起点到终点的路径。
这个示例是一个基本的A*搜索算法实现,可以根据具体需求进行扩展和优化。