You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

110 lines
3.3 KiB
C#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using WpfNodeTest.Models;
namespace WpfNodeTest.Services;
/// <summary>
/// 路径规划服务使用Dijkstra算法
/// </summary>
public class PathPlanningService
{
/// <summary>
/// 规划从起点到终点的路径
/// </summary>
/// <param name="graphData">节点图数据</param>
/// <param name="startNodeId">起点节点ID</param>
/// <param name="endNodeId">终点节点ID</param>
/// <returns>路径节点ID列表</returns>
public List<string> PlanPath(NodeGraphData graphData, string startNodeId, string endNodeId)
{
// 构建邻接表(双向图)
var adjacency = BuildAdjacency(graphData);
// Dijkstra算法
var distances = new Dictionary<string, double>();
var previous = new Dictionary<string, string>();
var unvisited = new HashSet<string>();
foreach (var node in graphData.Nodes)
{
distances[node.Id] = double.MaxValue;
unvisited.Add(node.Id);
}
distances[startNodeId] = 0;
while (unvisited.Count > 0)
{
var current = unvisited.OrderBy(n => distances[n]).First();
unvisited.Remove(current);
if (current == endNodeId) break;
if (adjacency.TryGetValue(current, out var neighbors))
{
foreach (var (neighbor, weight) in neighbors)
{
if (!unvisited.Contains(neighbor)) continue;
var alt = distances[current] + weight;
if (alt < distances[neighbor])
{
distances[neighbor] = alt;
previous[neighbor] = current;
}
}
}
}
// 回溯路径
var path = new List<string>();
var step = endNodeId;
while (previous.ContainsKey(step))
{
path.Add(step);
step = previous[step];
}
path.Add(startNodeId);
path.Reverse();
return path;
}
/// <summary>
/// 构建邻接表(双向图)
/// </summary>
private Dictionary<string, List<(string nodeId, double weight)>> BuildAdjacency(NodeGraphData graphData)
{
var adjacency = new Dictionary<string, List<(string, double)>>();
foreach (var node in graphData.Nodes)
{
adjacency[node.Id] = new List<(string, double)>();
}
foreach (var conn in graphData.Connections)
{
// 双向连接
adjacency[conn.SourceNodeId].Add((conn.TargetNodeId, conn.Weight));
adjacency[conn.TargetNodeId].Add((conn.SourceNodeId, conn.Weight));
}
return adjacency;
}
/// <summary>
/// 将路径拆分为子任务
/// </summary>
/// <param name="path">路径节点ID列表</param>
/// <param name="graphData">节点图数据</param>
/// <returns>子任务列表(起点->终点)</returns>
public List<(string from, string to)> SplitToSubTasks(List<string> path, NodeGraphData graphData)
{
var subTasks = new List<(string, string)>();
for (int i = 0; i < path.Count - 1; i++)
{
subTasks.Add((path[i], path[i + 1]));
}
return subTasks;
}
}