EG/plugins/user/pathfinding_algorithms/algorithms/dijkstra.py
2025-12-12 16:16:15 +08:00

148 lines
5.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
Dijkstra算法实现
Dijkstra算法是一种用于计算单源最短路径的经典算法
"""
import heapq
from typing import List, Tuple, Optional, Dict, Set
class Dijkstra:
"""
Dijkstra算法实现
Dijkstra算法是一种用于计算单源最短路径的经典算法
"""
def __init__(self):
"""初始化Dijkstra算法"""
self.stats = {
'nodes_visited': 0,
'max_queue_size': 0
}
def find_path(self, grid: List[List[int]], start: Tuple[int, int], goal: Tuple[int, int]) -> Optional[List[Tuple[int, int]]]:
"""
使用Dijkstra算法查找路径
Args:
grid: 网格地图0表示可通行1表示障碍物
start: 起点坐标 (row, col)
goal: 终点坐标 (row, col)
Returns:
路径坐标列表如果找不到路径则返回None
"""
# 重置统计信息
self.stats = {
'nodes_visited': 0,
'max_queue_size': 0
}
# 获取网格尺寸
rows = len(grid)
cols = len(grid[0]) if rows > 0 else 0
# 检查起点和终点是否有效
if not (0 <= start[0] < rows and 0 <= start[1] < cols):
return None
if not (0 <= goal[0] < rows and 0 <= goal[1] < cols):
return None
if grid[start[0]][start[1]] == 1 or grid[goal[0]][goal[1]] == 1:
return None
# 初始化优先队列
priority_queue = []
heapq.heappush(priority_queue, (0, start))
# 初始化距离和父节点字典
distances: Dict[Tuple[int, int], float] = {start: 0}
parent: Dict[Tuple[int, int], Tuple[int, int]] = {}
visited: Set[Tuple[int, int]] = set()
# 8方向移动包括对角线
directions = [
(-1, 0), (1, 0), (0, -1), (0, 1), # 上下左右
(-1, -1), (-1, 1), (1, -1), (1, 1) # 对角线
]
while priority_queue:
# 更新统计信息
self.stats['nodes_visited'] += 1
self.stats['max_queue_size'] = max(self.stats['max_queue_size'], len(priority_queue))
# 取出距离最小的节点
current_distance, current = heapq.heappop(priority_queue)
# 如果已经访问过,跳过
if current in visited:
continue
# 标记为已访问
visited.add(current)
# 如果到达目标节点
if current == goal:
# 重构路径
path = self._reconstruct_path(parent, current)
return path
# 检查所有邻居节点
for dr, dc in directions:
neighbor = (current[0] + dr, current[1] + dc)
# 检查邻居节点是否在网格范围内
if not (0 <= neighbor[0] < rows and 0 <= neighbor[1] < cols):
continue
# 检查邻居节点是否为障碍物
if grid[neighbor[0]][neighbor[1]] == 1:
continue
# 检查邻居节点是否已访问
if neighbor in visited:
continue
# 计算移动代价
if abs(dr) + abs(dc) == 2: # 对角线移动
move_cost = 1.414 # √2
else: # 直线移动
move_cost = 1.0
# 计算到邻居节点的距离
distance = current_distance + move_cost
# 如果找到更短路径
if neighbor not in distances or distance < distances[neighbor]:
# 更新距离和父节点
distances[neighbor] = distance
parent[neighbor] = current
heapq.heappush(priority_queue, (distance, neighbor))
# 未找到路径
return None
def _reconstruct_path(self, parent: Dict[Tuple[int, int], Tuple[int, int]], current: Tuple[int, int]) -> List[Tuple[int, int]]:
"""
重构路径
Args:
parent: 父节点字典
current: 当前节点
Returns:
路径坐标列表
"""
path = [current]
while current in parent:
current = parent[current]
path.append(current)
path.reverse()
return path
def get_stats(self) -> Dict[str, int]:
"""
获取算法统计信息
Returns:
统计信息字典
"""
return self.stats.copy()