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算法使用优先队列来管理待处理的节点,通过不断选择最短距离的节点进行扩展,更新相邻节点的距离值。最后,输出从起点到终点的最短距离。

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/601428.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【unity小技巧】FPS游戏实现相机的偏移震动、武器射击后退和后坐力效果

最终效果 文章目录 最终效果前言相机偏移震动相机震动脚本换弹节点震动 武器射击后退效果武器后坐力效果完结 前言 关于后坐力之前其实已经分享了一个&#xff1a;FPS游戏后坐力制作思路 但是实现起来比较复杂&#xff0c;如果你只是想要简单的实现&#xff0c;可以看看这个&…

JAVA计算组合数

JAVA计算组合数 /*** 计算组合数&#xff0c;即C(n, m) n!/((n-m)! * m!)* param n* param m* return*/public static long combination(int n, int m) {return (n > m) ? factorial(n) / factorial(n - m) / factorial(m) : 0;}

ROS OpenCV 级联分类器

Haar级联分类器、HOG级联分类器和LBP级联分类器都是计算机视觉中用于目标检测的特征提取与分类方法&#xff0c;它们各自利用不同的图像特征进行训练&#xff0c;并且通常结合级联结构来提升实时性。 一、Haar级联分类器 1. 特征描述&#xff1a; Haar特征由Paul Viola和Michae…

使用printJS使网页打印成PDF、网页html结合printJS导出为pdf

先放几个参考链接 感谢&#xff01; Vue使用PrintJS实现页面打印功能_vue print.js 设置打印pdf的大小-CSDN博客 前台导出pdf经验汇总 &#xff08;html2canvas.js和浏览器自带的打印功能-print.js&#xff09;以及后台一些导出pdf的方法_iqc后台管理系统怎么做到导出pdf-CSD…

大创项目推荐 深度学习图像分类算法研究与实现 - 卷积神经网络图像分类

文章目录 0 前言1 常用的分类网络介绍1.1 CNN1.2 VGG1.3 GoogleNet 2 图像分类部分代码实现2.1 环境依赖2.2 需要导入的包2.3 参数设置(路径&#xff0c;图像尺寸&#xff0c;数据集分割比例)2.4 从preprocessedFolder读取图片并返回numpy格式(便于在神经网络中训练)2.5 数据预…

ssm基于JSP的网络游戏交易系统的设计与实现+jsp论文

摘 要 传统信息的管理大部分依赖于管理人员的手工登记与管理&#xff0c;然而&#xff0c;随着近些年信息技术的迅猛发展&#xff0c;让许多比较老套的信息管理模式进行了更新迭代&#xff0c;商品管理信息因为其管理内容繁杂&#xff0c;管理数量繁多导致手工进行处理不能满足…

面试题理解深层次的数组名

目录 引言 一&#xff1a;一维数组 举例如下 1.铺垫知识 数组名是数组首元素的地址&#xff0c;但是有两个特殊情况 &#xff08;1&#xff09;sizeof(数组名) &#xff08;2&#xff09;&数组名 2.分析讲解上述代码结果 2.字符数组 举例一如下 1.知识铺垫 …

(三)其他的输入输出

文章目录 getchar();单个字符输入使用&#xff1a; putchar();单个字符输出(自带换行)使用 puts();字符串输出与printf区别使用 gets();后面补充 代码现象 getchar(); 单个字符输入 使用&#xff1a; 变量 getchar(); 例&#xff1a;char a&#xff1b; a getchar(); put…

软件测试之单元测试、系统测试、集成测试知识总结

一、单元测试的概念 单元测试是对软件基本组成单元进行的测试&#xff0c;如函数或一个类的方法。当然这里的基本单元不仅仅指的是一个函数或者方法&#xff0c;有可能对应多个程序文件中的一组函数。 单元也具有一些基本的属性。比如&#xff1a;明确的功能、规格定义&#…

PHP进阶-实现网站的QQ授权登录

授权登录是站点开发常见的应用场景&#xff0c;通过社交媒体一键授权可以跳过注册站点账户的繁琐操作。本文将讲解如何用PHP实现QQ授权登录。首先&#xff0c;我们需要申请QQ互联开发者账号获得APPID和密钥&#xff1b;接着&#xff0c;我们下载QQ官方SDK&#xff1a;PHP SDK v…

【Docker】 Docker 开发注意事项

在使用 Docker 进行开发时,需要注意以确保开发过程顺利和高效: 1. 了解 Docker 基础:在开始之前,了解 Docker 的基本概念,如镜像(Images)、容器(Containers)、仓库(Repositories)和 Dockerfile 的基本语法。 2. 编写清晰的 Dockerfile:Dockerfile 应该清晰、简洁,…

IP地址定位技术的应用及其重要性

随着网络技术的快速发展&#xff0c;网络安全问题日益凸显&#xff0c;IP地址定位技术在网络安全领域的应用也越来越广泛。本文将介绍IP地址定位技术在网络安全领域的应用及其重要性。 一、IP地址定位技术概述 IP地址定位技术是指通过一定的技术手段&#xff0c;将虚拟网络中的…

关于《码农翻身》一书的读后感以及自己的一些拙见汇总

书籍名称 《码农翻身》 | 刘欣&#xff08;码农翻身&#xff09; 著 | 文章将以问答的形式进行叙述 1.是从什么渠道接触到《码农翻身》的 一个工作日的下午&#xff0c;手上的任务基本结束&#xff0c;翻了翻桌上的书和笔记之类的&#xff0c;同事见我在看书&#xff0c;于是向…

Java 标准注解和元注解

Java 标准注解 Java 1.5开始自带的标准注解&#xff0c;包括Override、Deprecated和SuppressWarnings&#xff1a; Override&#xff1a;表示当前的方法定义将覆盖父类中的方法Deprecated&#xff1a;表示代码被弃用&#xff0c;如果使用了被Deprecated注解的代码则编译器将发…

华为云服务介绍(二)

在 华为云服务介绍(一) 中我们看到华为云提供了一系列的云服务,包括计算、存储、网络、数据库、安全等方面的解决方案。通过灵活的系统架构设计,可以充分利用这些云服务技术,从而更好地满足用户的需求。 本文从系统架构的角度出发,通过充分利用华为云提供的各种云服务技…

阿里后端实习一面面经

阿里后端实习一面面经 项目中使用到了es&#xff0c;es的作用&#xff1f; elasticsearch是一款非常强大的开源搜索引擎&#xff0c;具备非常多强大功能&#xff0c;可以帮助我们从海量数据中快速找到需要的内容 es中的重要概念&#xff1f; 群集&#xff1a;一个或多个节点…

PostgreSQL的常见错误和解决方法

转载说明&#xff1a;如果您喜欢这篇文章并打算转载它&#xff0c;请私信作者取得授权。感谢您喜爱本文&#xff0c;请文明转载&#xff0c;谢谢。 在学习新的东西时&#xff0c;会犯很多的错误&#xff0c;会遇到很多坑。我们在填坑与犯错中不断进步成长。 以下是在学习pgsql中…

Pytorch详细安装过程

1、安装anaconda 官网&#xff08;https://www.anaconda.com/products/distribution#Downloads&#xff09;下载&#xff0c;使用管理员身份运行&#xff08;不使用似乎也没事&#xff09; 这里选择Just me&#xff08;至于为啥&#xff0c;咱也不是很清楚&#xff09; 更改路…

编程基础 - 初识shell

编程基础 - 初识shell 返回序言及专栏目录 文章目录 编程基础 - 初识shell前言一、Linux的路径1、绝对路径2、相对路径3、特殊路径 二、交互式工作1、先联系上shell2、交互式命令 三、执行脚本四、sh和bash的区别总结 前言 shell是Linux内核外的一层壳&#xff0c;是用户与Li…

大数据 MapReduce如何让数据完成一次旅行?

专栏上一期我们聊到MapReduce编程模型将大数据计算过程切分为Map和Reduce两个阶段&#xff0c;先复习一下&#xff0c;在Map阶段为每个数据块分配一个Map计算任务&#xff0c;然后将所有map输出的Key进行合并&#xff0c;相同的Key及其对应的Value发送给同一个Reduce任务去处理…