C# 路径搜索算法 A* 算法 和 Dijkstra 算法

 A*算法和Dijkstra算法是两种常用的路径搜索算法,用于在图形结构中寻找最短路径。它们都属于单源最短路径算法,可以用于解决各种寻路问题。

        A算法是一种启发式搜索算法,同时考虑了实际移动代价和估计距离代价,通过估计代价来指导搜索方向,并选择最优的路径。A算法通过估价函数值 f(n) = g(n) + h(n) 来评估节点的优先级,其中 g(n) 是实际移动代价,h(n) 是从当前节点到目标节点的估计代价。A算法使用优先队列(通常是最小堆)来管理待处理的节点,每次选择具有最小 f(n) 值的节点进行扩展。A算法在最优条件下(即 h(n) 函数是准确的)保证能够找到最短路径。

        Dijkstra算法是一种经典的图搜索算法,通过不断选择最短路径的节点进行扩展,逐步确定从起点到达其他节点的最短路径。Dijkstra算法使用一个距离数组来记录起始节点到每个节点的最短距离,通过选择当前距离最小的节点进行扩展,更新与该节点相邻节点的距离值。Dijkstra算法在没有负权边的情况下保证能够找到最短路径。

        总结:A*算法通过使用估计函数来指导搜索方向,具有较高的效率和准确性,特别适用于路径搜索问题。Dijkstra算法是一种经典的最短路径算法,适用于图中存在负权边(但不能有负权环)的场景。根据实际情况选择合适的算法,可以高效地寻找最短路径。

A*路径搜索算法的完整代码:

using System;
using System.Collections.Generic;

public class AStarPathfinding
{
    // 定义节点类
    public class Node
    {
        public int x;
        public int y;
        public bool isWalkable;
        public List<Node> neighbors;
        public Node parent;
        public int gCost;
        public int hCost;

        public Node(int x, int y, bool isWalkable)
        {
            this.x = x;
            this.y = y;
            this.isWalkable = isWalkable;
            neighbors = new List<Node>();
        }

        public int fCost { get { return gCost + hCost; } }
    }

    // 寻找路径
    public static List<Node> FindPath(Node startNode, Node endNode)
    {
        List<Node> openSet = new List<Node>();
        HashSet<Node> closedSet = new HashSet<Node>();
        openSet.Add(startNode);

        while (openSet.Count > 0)
        {
            Node currentNode = openSet[0];
            for (int i = 1; i < openSet.Count; i++)
            {
                if (openSet[i].fCost < currentNode.fCost || openSet[i].fCost == currentNode.fCost && openSet[i].hCost < currentNode.hCost)
                {
                    currentNode = openSet[i];
                }
            }

            openSet.Remove(currentNode);
            closedSet.Add(currentNode);

            if (currentNode == endNode)
            {
                return GeneratePath(startNode, endNode);
            }

            foreach (Node neighbor in currentNode.neighbors)
            {
                if (!neighbor.isWalkable || closedSet.Contains(neighbor))
                {
                    continue;
                }

                int newCostToNeighbor = currentNode.gCost + GetDistance(currentNode, neighbor);
                if (newCostToNeighbor < neighbor.gCost || !openSet.Contains(neighbor))
                {
                    neighbor.gCost = newCostToNeighbor;
                    neighbor.hCost = GetDistance(neighbor, endNode);
                    neighbor.parent = currentNode;

                    if (!openSet.Contains(neighbor))
                    {
                        openSet.Add(neighbor);
                    }
                }
            }
        }

        return null;
    }

    // 计算两个节点之间的距离
    public static int GetDistance(Node nodeA, Node nodeB)
    {
        int distanceX = Math.Abs(nodeA.x - nodeB.x);
        int distanceY = Math.Abs(nodeA.y - nodeB.y);

        return distanceX + distanceY;
    }

    // 生成路径
    public static List<Node> GeneratePath(Node startNode, Node endNode)
    {
        List<Node> path = new List<Node>();
        Node currentNode = endNode;

        while (currentNode != startNode)
        {
            path.Add(currentNode);
            currentNode = currentNode.parent;
        }

        path.Reverse();
        return path;
    }

    // 使用示例
    static void Main(string[] args)
    {
        // 创建地图
        Node[,] map = new Node[10, 10];
        for (int i = 0; i < 10; i++)
        {
            for (int j = 0; j < 10; j++)
            {
                bool isWalkable = true;  // 是否可以行走,根据实际情况设置
                map[i, j] = new Node(i, j, isWalkable);
            }
        }

        // 设置邻居节点
        for (int i = 0; i < 10; i++)
        {
            for (int j = 0; j < 10; j++)
            {
                Node node = map[i, j];
                if (i > 0)
                {
                    node.neighbors.Add(map[i - 1, j]);
                }
                if (i < 9)
                {
                    node.neighbors.Add(map[i + 1, j]);
                }
                if (j > 0)
                {
                    node.neighbors.Add(map[i, j - 1]);
                }
                if (j < 9)
                {
                    node.neighbors.Add(map[i, j + 1]);
                }
            }
        }

        // 测试寻路
        Node startNode = map[0, 0];
        Node endNode = map[9, 9];
        List<Node> path = FindPath(startNode, endNode);

        if (path != null)
        {
            Console.WriteLine("Path Found:");
            foreach (Node node in path)
            {
                Console.WriteLine("(" + node.x + ", " + node.y + ")");
            }
        }
        else
        {
            Console.WriteLine("No Path Found.");
        }
    }
}

using System;
using System.Collections.Generic;

public class AStarPathfinding
{
    // 定义节点类
    public class Node
    {
        public int x;
        public int y;
        public bool isWalkable;
        public List<Node> neighbors;
        public Node parent;
        public int gCost;
        public int hCost;

        public Node(int x, int y, bool isWalkable)
        {
            this.x = x;
            this.y = y;
            this.isWalkable = isWalkable;
            neighbors = new List<Node>();
        }

        public int fCost { get { return gCost + hCost; } }
    }

    // 寻找路径
    public static List<Node> FindPath(Node startNode, Node endNode)
    {
        List<Node> openSet = new List<Node>();
        HashSet<Node> closedSet = new HashSet<Node>();
        openSet.Add(startNode);

        while (openSet.Count > 0)
        {
            Node currentNode = openSet[0];
            for (int i = 1; i < openSet.Count; i++)
            {
                if (openSet[i].fCost < currentNode.fCost || openSet[i].fCost == currentNode.fCost && openSet[i].hCost < currentNode.hCost)
                {
                    currentNode = openSet[i];
                }
            }

            openSet.Remove(currentNode);
            closedSet.Add(currentNode);

            if (currentNode == endNode)
            {
                return GeneratePath(startNode, endNode);
            }

            foreach (Node neighbor in currentNode.neighbors)
            {
                if (!neighbor.isWalkable || closedSet.Contains(neighbor))
                {
                    continue;
                }

                int newCostToNeighbor = currentNode.gCost + GetDistance(currentNode, neighbor);
                if (newCostToNeighbor < neighbor.gCost || !openSet.Contains(neighbor))
                {
                    neighbor.gCost = newCostToNeighbor;
                    neighbor.hCost = GetDistance(neighbor, endNode);
                    neighbor.parent = currentNode;

                    if (!openSet.Contains(neighbor))
                    {
                        openSet.Add(neighbor);
                    }
                }
            }
        }

        return null;
    }

    // 计算两个节点之间的距离
    public static int GetDistance(Node nodeA, Node nodeB)
    {
        int distanceX = Math.Abs(nodeA.x - nodeB.x);
        int distanceY = Math.Abs(nodeA.y - nodeB.y);

        return distanceX + distanceY;
    }

    // 生成路径
    public static List<Node> GeneratePath(Node startNode, Node endNode)
    {
        List<Node> path = new List<Node>();
        Node currentNode = endNode;

        while (currentNode != startNode)
        {
            path.Add(currentNode);
            currentNode = currentNode.parent;
        }

        path.Reverse();
        return path;
    }

    // 使用示例
    static void Main(string[] args)
    {
        // 创建地图
        Node[,] map = new Node[10, 10];
        for (int i = 0; i < 10; i++)
        {
            for (int j = 0; j < 10; j++)
            {
                bool isWalkable = true;  // 是否可以行走,根据实际情况设置
                map[i, j] = new Node(i, j, isWalkable);
            }
        }

        // 设置邻居节点
        for (int i = 0; i < 10; i++)
        {
            for (int j = 0; j < 10; j++)
            {
                Node node = map[i, j];
                if (i > 0)
                {
                    node.neighbors.Add(map[i - 1, j]);
                }
                if (i < 9)
                {
                    node.neighbors.Add(map[i + 1, j]);
                }
                if (j > 0)
                {
                    node.neighbors.Add(map[i, j - 1]);
                }
                if (j < 9)
                {
                    node.neighbors.Add(map[i, j + 1]);
                }
            }
        }

        // 测试寻路
        Node startNode = map[0, 0];
        Node endNode = map[9, 9];
        List<Node> path = FindPath(startNode, endNode);

        if (path != null)
        {
            Console.WriteLine("Path Found:");
            foreach (Node node in path)
            {
                Console.WriteLine("(" + node.x + ", " + node.y + ")");
            }
        }
        else
        {
            Console.WriteLine("No Path Found.");
        }
    }
}

        在示例代码中,我们定义了一个 AStarPathfinding 类实现A*路径搜索的相关逻辑。代码中包含了一个 Node 类用于表示节点对象,以及 FindPath 函数用于寻找路径,GetDistance 函数用于计算两个节点之间的距离,GeneratePath 函数用于生成路径。

        在 Main 函数中,我们首先创建了一个 10x10 的地图,设置各个节点的可行走状态,并为每个节点设置邻居节点。然后,我们以 (0, 0) 作为起始节点,(9, 9) 作为目标节点,调用 FindPath 函数寻找路径。如果找到了路径,则输出路径上的节点坐标;否则,输出 "No Path Found."。

        请注意,这只是一个简单的示例,实际的路径搜索算法根据具体的场景和需求可能需要更复杂的实现。

Dijkstra算法的完整代码:

using System;
using System.Collections.Generic;

public class DijkstraAlgorithm
{
    // 定义节点类
    public class Node
    {
        public int id;
        public int distance;
        public bool visited;
        public List<Edge> edges;

        public Node(int id)
        {
            this.id = id;
            this.distance = int.MaxValue;
            this.visited = false;
            this.edges = new List<Edge>();
        }
    }

    // 定义边类
    public class Edge
    {
        public Node source;
        public Node destination;
        public int weight;

        public Edge(Node source, Node destination, int weight)
        {
            this.source = source;
            this.destination = destination;
            this.weight = weight;
        }
    }

    // Dijkstra算法
    public static void Dijkstra(Node startNode)
    {
        startNode.distance = 0;

        PriorityQueue<Node> queue = new PriorityQueue<Node>();
        queue.Enqueue(startNode);

        while (queue.Count > 0)
        {
            Node currentNode = queue.Dequeue();
            currentNode.visited = true;

            foreach (Edge edge in currentNode.edges)
            {
                Node neighborNode = edge.destination;
                int distance = currentNode.distance + edge.weight;

                if (distance < neighborNode.distance)
                {
                    neighborNode.distance = distance;

                    if (!neighborNode.visited)
                    {
                        queue.Enqueue(neighborNode);
                    }
                }
            }
        }
    }

    // 示例用法
    public static void Main()
    {
        // 创建节点
        Node nodeA = new Node(0);
        Node nodeB = new Node(1);
        Node nodeC = new Node(2);
        Node nodeD = new Node(3);
    
        // 创建边
        Edge edgeAB = new Edge(nodeA, nodeB, 2);
        Edge edgeAC = new Edge(nodeA, nodeC, 4);
        Edge edgeBC = new Edge(nodeB, nodeC, 1);
        Edge edgeCD = new Edge(nodeC, nodeD, 3);

        // 添加边到节点的边列表
        nodeA.edges.Add(edgeAB);
        nodeA.edges.Add(edgeAC);
        nodeB.edges.Add(edgeBC);
        nodeC.edges.Add(edgeCD);

        // 运行Dijkstra算法
        Dijkstra(nodeA);

        // 输出最短距离
        Console.WriteLine("Shortest distance from nodeA to nodeD: " + nodeD.distance);
    }
}

        这个代码示例创建了一组示例节点和边,然后运行Dijkstra算法来找到从起点到终点的最短路径。在这个示例中,节点使用id来唯一标识,边包含源节点,目标节点和权重。Dijkstra算法使用优先队列来管理待处理的节点,通过不断选择最短距离的节点进行扩展,更新相邻节点的距离值。最后,输出从起点到终点的最短距离。

        请注意,这只是一个简单的示例,实际使用时可能需要根据具体情况进行修改和扩展。 

  • 13
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C# 最短路径 Dijkstra算法是一种用于寻找图中最短路径算法。它基于贪心策略,每次选择当前距离起点最近的节点,并更新与该节点相邻的节点的距离。该算法的时间复杂度为O(n^2),其中n为节点数。 具体实现时,可以使用一个数组来记录每个节点的距离和是否已经被访问过。首先将起点的距离设为0,其余节点的距离设为无穷大。然后从起点开始,每次选择距离起点最近的未访问节点,并更新与该节点相邻的节点的距离。重复该过程直到所有节点都被访问过或者无法到达终点。 以下是C#实现Dijkstra算法的示例代码: ``` using System; using System.Collections.Generic; class DijkstraAlgorithm { static void Main(string[] args) { int[,] graph = new int[,] { { 0, 4, 0, 0, 0, 0, 0, 8, 0 }, { 4, 0, 8, 0, 0, 0, 0, 11, 0 }, { 0, 8, 0, 7, 0, 4, 0, 0, 2 }, { 0, 0, 7, 0, 9, 14, 0, 0, 0 }, { 0, 0, 0, 9, 0, 10, 0, 0, 0 }, { 0, 0, 4, 14, 10, 0, 2, 0, 0 }, { 0, 0, 0, 0, 0, 2, 0, 1, 6 }, { 8, 11, 0, 0, 0, 0, 1, 0, 7 }, { 0, 0, 2, 0, 0, 0, 6, 7, 0 } }; Dijkstra(graph, 0); } static void Dijkstra(int[,] graph, int start) { int n = graph.GetLength(0); int[] dist = new int[n]; bool[] visited = new bool[n]; for (int i = 0; i < n; i++) { dist[i] = int.MaxValue; visited[i] = false; } dist[start] = 0; for (int count = 0; count < n - 1; count++) { int u = MinDistance(dist, visited); visited[u] = true; for (int v = 0; v < n; v++) { if (!visited[v] && graph[u, v] != 0 && dist[u] != int.MaxValue && dist[u] + graph[u, v] < dist[v]) { dist[v] = dist[u] + graph[u, v]; } } } PrintSolution(dist); } static int MinDistance(int[] dist, bool[] visited) { int min = int.MaxValue; int minIndex = -1; for (int i = 0; i < dist.Length; i++) { if (!visited[i] && dist[i] <= min) { min = dist[i]; minIndex = i; } } return minIndex; } static void PrintSolution(int[] dist) { Console.WriteLine("Vertex \t Distance from Source"); for (int i = 0; i < dist.Length; i++) { Console.WriteLine(i + " \t\t " + dist[i]); } } } ``` 该代码实现了一个简单的Dijkstra算法,用于寻找从起点0到其他节点的最短路径。其中,graph数组表示图的邻接矩阵,dist数组记录每个节点到起点的距离,visited数组记录每个节点是否已经被访问过。在Dijkstra函数中,首先初始化dist和visited数组,然后从起点开始,每次选择距离起点最近的未访问节点,并更新与该节点相邻的节点的距离。最后输出每个节点到起点的最短距离。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值