贪婪最佳优先搜索算法(Greedy Best-First Search Algorithm)在C++中的实现

贪婪最佳优先搜索算法(greedy best-first search algorithm)在c++中的实现

计算机科学中良好的问题解决很大程度上依赖于高效的算法,例如贪婪最佳优先搜索(GBFS)。 GBFS 已经确立了作为寻路或优化问题的最佳解决方法的可信度。因此,我们在本文中深入讨论 GBFS,同时探索其使用 C++ 的实现方法。

语法

void greedyBestFirstSearch(Graph graph, Node startNode, Node goalNode);

算法

贪心最佳优先搜索算法旨在找到图中从给定起始节点到目标节点的路径。以下是该算法的一般步骤 –

初始化一个空的优先级队列。

将起始节点放入优先级队列。

立即学习“C++免费学习笔记(深入)”;

创建一个空集来跟踪访问过的节点。

当优先级队列不为空时 –

将优先级最高的节点从队列中出列。

如果出队的节点是目标节点,则算法终止,并找到路径。

否则,将出队节点标记为已访问。

将出队节点的所有未访问的邻居节点放入优先级队列中。

如果优先级队列在到达目标节点之前变空,则不存在路径。

方法一:基于欧氏距离的启发式函数

示例

#include #include #include #include #include using namespace std;// Structure to represent a node in the graphstruct Node {   int x, y; // Coordinates of the node   int cost; // Cost to reach this node};// Euclidean distance heuristic functiondouble euclideanDistance(int x1, int y1, int x2, int y2) {   return sqrt(pow((x1 - x2), 2) + pow((y1 - y2), 2));}// Custom comparison function for nodes in the priority queuestruct NodeCompare {   bool operator()(const Node& node1, const Node& node2) const {      return node1.cost > node2.cost;   }};// Greedy Best-First Search functionvoid greedyBestFirstSearch(vector<vector>& graph, Node start, Node goal) {   int rows = graph.size();   int cols = graph[0].size();   // Priority queue for nodes to be explored   priority_queue<Node, vector, NodeCompare> pq;   // Visited nodes set   unordered_set visited;   // Add the start node to the priority queue   pq.push(start);   while (!pq.empty()) {      // Get the node with the lowest cost      Node current = pq.top();      pq.pop();      // Check if the current node is the goal node      if (current.x == goal.x && current.y == goal.y) {         cout << "Goal node reached!" << endl;         return;      }      // Mark the current node as visited      int nodeId = current.x * cols + current.y;      visited.insert(nodeId);      // Explore the neighboring nodes      int dx[] = {-1, 1, 0, 0}; // Possible x-direction movements      int dy[] = {0, 0, -1, 1}; // Possible y-direction movements      for (int i = 0; i = 0 && newX = 0 && newY < cols) {            // Calculate the heuristic value for the neighboring node            double heuristicValue = euclideanDistance(newX, newY, goal.x, goal.y);            // Check if the neighboring node has not been visited            if (visited.find(newX * cols + newY) == visited.end()) {               // Create a new node for the neighboring position               Node neighbor;               neighbor.x = newX;               neighbor.y = newY;               neighbor.cost = current.cost + graph[newX][newY];               // Add the neighboring node to the priority queue               pq.push(neighbor);            }         }      }   }   cout << "Goal node not reachable!" << endl;}int main() {   // Example graph represented as a 2D vector   vector<vector> graph = {      {3, 5, 1, 2},      {1, 3, 2, 4},      {5, 2, 6, 7},      {4, 3, 1, 2}   };   Node start;   start.x = 0; // Starting x-coordinate   start.y = 0; // Starting y-coordinate   start.cost = 0; // Cost to reach the starting node   Node goal;   goal.x = 3; // Goal x-coordinate   goal.y = 3; // Goal y-coordinate   // Run Greedy Best-First Search algorithm   greedyBestFirstSearch(graph, start, goal);   return 0;}

输出

Goal node reached!

说明

这段代码包含两个关键元素。首先,它包含 Graph 类的定义,该类表示使用邻接表的图结构。

其次,它引入了 CompareEuclideanDistance – 一个自定义比较器,用于通过使用欧几里德距离公式估计节点与目标节点的距离来评估节点。

greedyBestFirstSearch 函数实现贪婪最佳优先搜索算法。它使用优先级队列根据节点的启发值来存储节点。

该算法首先将起始节点放入优先级队列中。

在每次迭代中,它将最高优先级的节点出队并检查它是否是目标节点。

如果找到目标节点,则会显示“路径已找到!”消息被打印。否则,算法将出队的节点标记为已访问,并将其未访问的相邻节点放入队列。

如果优先级队列变空而没有找到目标节点,则会显示“不存在路径!”消息已打印。

main函数通过创建图、定义起始节点和目标节点以及调用greedyBestFirstSearch函数演示了算法的用法。

方法2:基于曼哈顿距离的启发式函数

我们解决此问题的策略需要使用依赖于曼哈顿距离概念的启发式函数。这种距离度量有时称为出租车距离,涉及将节点之间的水平和垂直距离相加。

示例

#include #include #include #include #include using namespace std;// Structure to represent a node in the graphstruct Node {   int x, y; // Coordinates of the node   int cost; // Cost to reach this node};// Manhattan distance heuristic functionint manhattanDistance(int x1, int y1, int x2, int y2) {   return abs(x1 - x2) + abs(y1 - y2);}// Custom comparison function for nodes in the priority queuestruct NodeCompare {   bool operator()(const Node& node1, const Node& node2) const {      return node1.cost > node2.cost;   }};// Greedy Best-First Search functionvoid greedyBestFirstSearch(vector<vector>& graph, Node start, Node goal) {   int rows = graph.size();   int cols = graph[0].size();   // Priority queue for nodes to be explored   priority_queue<Node, vector, NodeCompare> pq;   // Visited nodes set   unordered_set visited;   // Add the start node to the priority queue   pq.push(start);   while (!pq.empty()) {      // Get the node with the lowest cost      Node current = pq.top();      pq.pop();      // Check if the current node is the goal node      if (current.x == goal.x && current.y == goal.y) {         cout << "Goal node reached!" << endl;         return;      }      // Mark the current node as visited      int nodeId = current.x * cols + current.y;      visited.insert(nodeId);      // Explore the neighboring nodes      int dx[] = {-1, 1, 0, 0}; // Possible x-direction movements      int dy[] = {0, 0, -1, 1}; // Possible y-direction movements      for (int i = 0; i = 0 && newX = 0 && newY < cols) {            // Calculate the heuristic value for the neighboring node            int heuristicValue = manhattanDistance(newX, newY, goal.x, goal.y);            // Check if the neighboring node has not been visited            if (visited.find(newX * cols + newY) == visited.end()) {               // Create a new node for the neighboring position               Node neighbor;               neighbor.x = newX;               neighbor.y = newY;               neighbor.cost = current.cost + graph[newX][newY];               // Add the neighboring node to the priority queue               pq.push(neighbor);            }         }      }   }   cout << "Goal node not reachable!" << endl;}int main() {   // Example graph represented as a 2D vector   vector<vector> graph = {      {3, 5, 1, 2},      {1, 3, 2, 4},      {5, 2, 6, 7},      {4, 3, 1, 2}   };   Node start;   start.x = 0; // Starting x-coordinate   start.y = 0; // Starting y-coordinate   start.cost = 0; // Cost to reach the starting node   Node goal;   goal.x = 3; // Goal x-coordinate   goal.y = 3; // Goal y-coordinate   // Run Greedy Best-First Search algorithm   greedyBestFirstSearch(graph, start, goal);   return 0;}

输出

Goal node reached!

说明

该代码遵循与方法 1 类似的结构,但使用自定义比较器 CompareManhattanDistance,该比较器使用曼哈顿距离公式根据到目标节点的估计距离来比较节点。

greedyBestFirstSearch 函数使用曼哈顿距离启发式实现贪婪最佳优先搜索算法。

main函数演示了算法的使用,创建一个图,定义起始节点和目标节点,并调用greedyBestFirstSearch函数。

结论

在本文中,我们探讨了贪婪最佳优先搜索算法及其在 C++ 中的实现。通过采用这些方法,程序员可以有效地找到图中的路径并解决优化问题。启发式函数的选择,例如欧氏距离或曼哈顿距离,可以显着影响算法在不同场景下的性能。

以上就是贪婪最佳优先搜索算法(Greedy Best-First Search Algorithm)在C++中的实现的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1445111.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年12月17日 22:11:56
下一篇 2025年12月17日 22:12:04

相关推荐

  • 为什么在C++代码中使用extern “C”?

    在C++中,当声明一个在C中实现/编译的函数时,需要使用extern “C”。 使用extern “C”让编译器知道我们想要使用C的命名和调用约定。这使得编译器在我们的C++代码内部进入了一种类似于C模式的状态。这是必要的,因为C++编译器在其符号表中…

    好文分享 2025年12月17日
    000
  • 获取和设置C语言中线程属性的堆栈大小

    要在C中获取和设置线程属性的堆栈大小,我们使用以下线程属性: pthread_attr_getstacksize() 用于获取线程堆栈大小。stacksize属性给出了分配给线程堆栈的最小堆栈大小。如果成功运行,则返回0,否则返回任何值。 它接受两个参数: pthread_attr_getstack…

    2025年12月17日
    000
  • 具有相同数量小写字母和大写字母的子字符串数量

    在这个问题中,我们需要计算给定字符串中包含相同数量的小写和大写字符的字符串的总数。解决这个问题的朴素方法是找到所有的子字符串,并计算具有相同数量的小写和大写字符的子字符串的总数。 有效的方法是使用子数组求和问题。我们可以将小写字符视为-1,将大写字符视为+1,我们将学习这两种方法来解决问题。 问题陈…

    2025年12月17日
    000
  • C++ 查询给定范围内偶数或奇数的概率

    求给定范围内数字奇偶性的概率,即是偶数还是奇数。对于每个查询,我们需要打印 p 和 q,例如用 p / q 表示概率。 Input : N = 5, arr[] = { 6, 5, 2, 1, 7 }query 1: 0 2 2query 2: 1 2 5query 3: 0 1 4Output :…

    2025年12月17日
    000
  • 在C程序中,将以下内容翻译为中文:查找链表倒数第n个节点的程序

    给定 n 个节点,任务是打印链表末尾的第 n 个节点。程序不得更改列表中节点的顺序,而应仅打印链表最后一个节点中的第 n 个节点。 示例 Input -: 10 20 30 40 50 60 N=3Output -: 40 在上面的例子中,从第一个节点开始,遍历到 count-n 个节点,即 10,…

    2025年12月17日
    000
  • 给定一个数,其与原始数之和等于另一个给定的数的排列方式

    在本文中,我们将深入探讨一个涉及数字和排列的迷人问题:“一个数与原始数的和等于另一个给定数的排列”。这个问题将数论和组合数学独特地结合在一起,使它成为一个引人入胜的挑战。 为了澄清,给定一个原始数和一个目标数,我们需要找到原始数的一个排列,使得当我们将原始数和它的排列相加时,得到目标数。 理解问题 …

    2025年12月17日
    000
  • 在C语言中的弧函数

    函数在C语言中是在graphics.h库中定义的。 在C编程语言中,有一个选项可以使用给定的半径、中心坐标和弧度来创建一个圆弧。 arc()函数在C的graphics.h库中定义 function 用于创建一个弧。这个弧函数包含在C语言的graphics.h库中,该库包含可以在输出屏幕上绘制图形的方…

    2025年12月17日
    000
  • 在C++中,将二叉树中的最大二叉搜索树(Largest BST in a Binary Tree)进行翻译

    在二叉树中,每个子节点只有两个节点(左和右)。树结构只是数据的表示。二叉搜索树(BST)是满足这些条件的特殊类型的二叉树 – 与其父节点相比,左子节点较小 右子节点的父节点比子节点大 假设给定一棵二叉树,我们有应该找出其中最大的二叉搜索树 (BST)。 立即学习“C++免费学习笔记(深入…

    2025年12月17日
    000
  • 使用UDP进行文件传输的C程序

    数据可以在两台使用 C 语言实现 Socket 编程的计算机之间传输。 在同样的情况下,可以轻松地通过实现用户数据报协议 (UDP) 和简单的客户端/服务器。 安全性 – 通过加密处理。 协议 – UDP 加密 – 异或加密 算法 服务器启动并等待文件名。 客户端…

    2025年12月17日 好文分享
    000
  • 将C程序转换为机器码的四个步骤是什么?

    创建和运行程序的过程 程序包含一组用编程语言编写的指令。 程序员的工作是编写和测试程序。 将’C’程序转换为机器语言的4个步骤是: 编写和编辑程序编译程序链接程序执行程序 编写和编辑程序 使用文本编辑器编写程序。 借助文本编辑器,用户可以输入、更改和存储字符数据。 所有特殊的…

    2025年12月17日
    000
  • 在一个范围内评估给定方程的查询

    对区间 [L, R] 内的所有方程进行评估,为我们提供了这些变量的一系列值。如何使用它的示例包括建模、数据分析和解决问题的场景。 在这种情况下,我们为范围内的所有点定义方程变量值。因此,可以通过指定范围的步长并评估范围内每个变量值的方程来完成。 规格 这可以称为向数据库询问信息的请求。当满足某些要求…

    2025年12月17日
    000
  • C/C++中的函数原型的目的是什么?

    在这里我们将了解在 C 或 C++ 中使用函数原型的目的是什么。函数原型用于告诉编译器参数的数量以及函数参数所需的数据类型,它还告诉编译器函数的返回类型。根据此信息,编译器在调用函数之前会交叉检查函数签名。如果没有提到函数原型,那么程序编译时可能会出现一些警告,有时会生成一些奇怪的输出。 如果某个函…

    2025年12月17日
    000
  • 在C语言中,局部作用域是指在特定代码块内部定义的变量、函数或其他实体的可见范围。局部作用域的实体只能在其所在的代码块内部访问和使用,超出该范围将无法访问

    结构是不同数据类型变量的集合,以单个名称分组在一起。 结构声明的一般形式 结构声明如下如下 – struct tagname{ datatype member1; datatype member2; datatype member n;}; 这里,struct 是关键字。 立即学习“C语…

    2025年12月17日
    000
  • C++程序:在数组中找到最大的可整除子集

    本教程将讨论一个问题,其中给定一个不同的正整数数组。我们需要找到最大的子集,使得每对较大的元素除以较小的元素,例如 – Input: nums[ ] = { 1, 4, 2, 6, 7}Output: 1 2 4Explanation:All Divisible subsets are:…

    2025年12月17日
    000
  • C++程序:对数组元素进行升序排序

    为了有效地解决一些问题,将数据项排列在正确的位置非常重要顺序。最流行的排列问题之一是元素排序问题。这本文将演示如何在 C++ 中按升序排列数组成员(根据值不断上升)。 要按特定顺序排列数字或非数字元素,有多种方法排序算法可用于该领域。只需两种简单的排序技术即可将在本文中介绍。选择排序和冒泡排序。让我…

    2025年12月17日
    000
  • 在C++中,将以下内容翻译成中文:Return语句与Main()中的Exit()函数的区别

    If you are a programmer, you write the code; If you write the code, you use the function; if you use the function, you use return and exit statements …

    2025年12月17日
    000
  • 为什么我们认为C/C++中的strncpy是不安全的?

    函数strncpy()用于将指定数量的字符从源复制到目标。 以下是strncpy()的语法 char *strncpy( char *destination, char *source, size_t n); 在这里,destination是指向目标数组的指针,源字符串将被复制到该数组中,sourc…

    2025年12月17日
    000
  • C语言编写的汉诺塔程序

    汉诺塔是一个数学难题。它由三根杆和若干个不同大小的圆盘组成,这些圆盘可以滑动到任意一根杆上。难题以圆盘按大小升序整齐堆叠在一根杆上开始,最小的圆盘在顶部。我们必须将相同的堆叠移到第三根杆上。 难题的目标是将整个堆叠移动到另一根杆上,遵守以下简单规则− 一次只能移动一个圆盘。 每次移动包括从一根堆中取…

    2025年12月17日
    000
  • C vs BASH Fork bomb? C对BASH的Fork炸弹?

    Fork() 炸弹是针对基于 Linux 的系统的 Dos(拒绝服务)攻击。这会无限次调用 Fork() 系统,从而填满程序的内存并意图危害系统。 fork 炸弹的 Bash 脚本 :(){ :|: & };: 代码解释为:( ) 是函数定义,{ } 定义循环体。 :|:& 创建一个…

    2025年12月17日
    000
  • 在C语言中,fork()和exec()之间的区别是什么?

    在这里,我们将看到在C语言中fork()和exec()系统调用的效果。fork用于通过复制调用进程来创建一个新的进程。新进程是子进程。请参考以下属性。 子进程有自己独特的进程ID。子进程的父进程ID与调用进程的进程ID相同。子进程不继承父进程的内存锁和信号量。 fork()返回子进程的PID。如果值…

    2025年12月17日
    000

发表回复

登录后才能评论
关注微信