【问题标题】:How to write BFS function in C++?如何用 C++ 编写 BFS 函数?
【发布时间】:2020-06-03 02:34:55
【问题描述】:
#include <iostream>
#include <string>
#include <queue>

using namespace std;
void BFS(const string&, const string[], int[][10]);

int main()
{
    const int CAP = 10;

    string states[CAP] = { "Arizona", "California", "Idaho", "Nevada", "Oregon", "Utah", "Washington" };
    string Point;

    int matrix[CAP][CAP] =
    {
    {0,1,0,1,0,1,0},
    {1,0,0,1,1,0,0},
    {0,0,0,1,1,1,1},
    {0,1,1,1,0,0,1},
    {1,1,1,1,0,0,0},
    {0,0,1,0,1,0,0},
    {0,0,1,0,1,0,0}
    };


    BFS("California", states, matrix);


}

void BFS(const string& Point, const string states[], int matrix[][10])
{
    int SPoint = 0;
    queue<string> visited;
    queue<string> Queue;


    string temp = Point;

    visited.push(temp);
    do
    {

        for (int i = 0; i < 10; i++)
        {
            if (states[i] == temp)
            {
                SPoint = i;
            }
        }
        for (int i = 0; i < 10; i++)
        {
            if (matrix[SPoint][i] == 1)
            {
                Queue.push(states[i]);
            }
        }

        visited.push(Queue.front());
        Queue.pop();

        temp = visited.back();

    } while (!Queue.empty());


    for (int i = 0; i < 10; i++)
    {
        cout << visited.front();
        visited.pop();
    }


}

我正在做一个练习,我必须创建一个执行广度优先搜索并打印出访问路径的函数。但我的功能不会打印任何东西。我在这里做错了什么?

注意:矩阵按字母顺序排列,表示状态之间的联系。

我的预期输出:加利福尼亚 亚利桑那 俄勒冈 内华达 犹他 爱达荷 华盛顿

Exercise description

【问题讨论】:

  • 您的“预期输出”似乎有七个值。从应该只包含 7 个值的队列中删除 10 个值,您期望会发生什么?

标签: c++ matrix graph nodes breadth-first-search


【解决方案1】:

虽然我不会提供完整的解决方案,但我可以帮助确定代码中存在的一些问题。

主要问题

  • 由于您有一个循环图,因此在 BFS 期间将节点标记为已访问非常重要,否则您将陷入无限循环(这就是为什么在当前实现中没有打印任何内容的原因)。您的visited 队列可能是unordered_set。当节点被访问时,将它们添加到集合中并编写条件以避免再次访问它们。
  • 邻接矩阵看起来不正确。由于它是一个无向图,我预计矩阵将从左上角镜像到右下角,但事实并非如此。此外,图中没有自边,但 Nevada 似乎在矩阵中对自己有边。
  • 无需遍历邻接矩阵——您可以通过适当地映射数字索引和字符串名称来对其进行索引。如果确实需要循环,则在 7x7 矩阵上运行到 10 是超出范围的。

小问题

  • 任意限制矩阵大小是没有意义的。尽管分配强制执行此操作,但这是一个糟糕的设计选择,因为任何时候您想要使用不同的输入图都需要重写代码。
  • 这里的矩阵似乎是一个有点尴尬的数据结构,因为它引入了一个额外的间接层来将字符串转换为整数并返回。虽然项目不允许,但我更喜欢使用如下结构:

    std::unordered_map<std::string, std::vector<std::string>> graph({
        {"California", {"Oregon", "Nevada", "Arizona"}},
        // ... more states ...
    });
    

    理想情况下,这些将是带有neighbor 向量成员而不是字符串的Node 对象。

  • C++ 提供std::vectorstd::array,它们比C 数组更可取。我认为它们尚未在您的课堂上介绍或不允许在作业中使用,但如果您遇到困难,您可以尝试使用它们编写代码,然后在您开始工作后重新介绍讲师的约束。如果不出意外,这将是一次学习体验。
  • 避免using namespace std;
  • 为类名保留大写变量名。对象和原语应该是小写的。

BFS 的伪代码

这假设了上面的首选数据结构;您可以根据需要在字符串和邻接矩阵索引之间进行转换。

func BFS(string start, unordered_map<string, vector<string>> graph):
    vector traversal
    queue worklist = {start}
    unordered_set visited = {start}

    while !worklist.empty():
        curr = worklist.pop_front()            
        traversal.push_back(curr)

        for neighbor in graph[curr]:
            if neighbor not in visited:
                visited.insert(neighbor)
                worklist.push(neighbor)

    return traversal

由于这是一项作业,我将把它留在这里,让您再破解一下代码。祝你好运。

【讨论】:

  • 非常感谢!这绝对有帮助。我真的很高兴你不只是给我答案。我会去解决的!!
  • 我必须按照说明进行操作,但我使用了一组来跟踪访问过的状态,它就像一个魅力! :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-01-15
  • 2021-02-18
  • 1970-01-01
  • 1970-01-01
  • 2015-07-10
  • 1970-01-01
  • 2012-04-21
相关资源
最近更新 更多