【问题标题】:BFS (breadth first search) adjacency matrix C++BFS(广度优先搜索)邻接矩阵 C++
【发布时间】:2018-09-05 19:45:44
【问题描述】:

我正在尝试使用邻接矩阵学习 BFS(广度优先搜索)。

我尝试了什么:

  • 根本不知道 BFS 是什么,所以我学习了概念和伪代码
  • 尝试查看示例
  • 尝试使用指向以下数组版本的指针来实现

目标:

  • 想确保我使用指向数组矩阵的指针正确地执行 BFS

邻接矩阵的图形类:

#include <iostream>
#include <queue>
using namespace std;

class Graph {
private:
    bool** adjMatrix;
    int numVertices;
    bool* visited;
public:
    //constructor
    Graph(int numVertices) {
        this->numVertices = numVertices;
        adjMatrix = new bool*[numVertices];
        for(int i = 0; i < numVertices; i++) {
            adjMatrix[i] = new bool[numVertices];
            for(int j = 0; j < numVertices; j++)
                adjMatrix[i][j] = false;
        }

        visited[numVertices]; //init visited array


    }

    //member function
    void BFS(int sp) {
        //make a queue of type int
        queue<int> Q;

        //make bool visited array & mark all positions unvisited
        for(int i = 0; i < numVertices; i++)
            visited[i] = false;

        //push sp into queue
        Q.push(sp);

        //mark sp as visited
        visited[sp] = true;

        //while queue isn't empty
        while(!Q.empty()) {

            //make temp node
            int temp = Q.front();

            //pop temp node
            Q.pop();

            //use loop & check if it has children
            int rows =  sizeof adjMatrix / sizeof adjMatrix[0]; //get row size
            for(int i = 0; i < rows; i++) { //check neighboring nodes
                if(!visited[i] && adjMatrix[sp][i] == true) {
                    Q.push(i); //if so push them into queue
                    visited[i] = true; //mark children as visited
                }
            }
        }

    }



};

【问题讨论】:

  • 问题出在哪里?
  • 我正在尝试找出是否有问题。我认为它可能在while循环内
  • 我的意思是,问题是什么?有什么不正常吗?您是否尝试编译并运行它?
  • 更重要的是,您从未问过问题。无论如何,我绝对不怀疑sizeof adjMatrix / sizeof adjMatrix[0] 是错误的。 adjMatrix 是一个指向指针的指针(指向bool,但现在并不真正相关),所以sizeof adjMatrix / sizeof adjMatrix[0] 将是1 总是。很确定numVerticies 将进入这张图片,假设你的指针数组确实在所有行中都那么宽。
  • 如果您不确定发生了什么,修复它的第一步是在调试器中单步调试代码。

标签: c++ data-structures queue


【解决方案1】:

好的,由于您没有附加错误日志或测试用例输出,请考虑以下实现

#include <iostream>
#include <queue>
#include <vector>
#include <set>
#include <cstdlib>

// using namespace std;   Don't do this. Good CPP production code uses separate namespaces 

const int BUFFER_CLEAR_VALUE = 999;

class Graph {
private:
    std::vector<std::vector<bool> > adj_mat;

public:
    //constructor
    Graph() {
        std::cout << "Enter vertex num" << std::endl;
        int num_vertices;
        std::cin >> num_vertices;
        while (std::cin.fail()) {
            std::cout << "Enter a valid num" << std::endl;
            std::cin.clear();
            std::cin.ignore(BUFFER_CLEAR_VALUE, '\n');
            std::cin >> num_vertices;
        }
        for (int i = 0; i < num_vertices; i++) {
            std::vector<bool> temp;
            temp.resize(num_vertices);
            adj_mat.push_back(temp);
        }
    }

    // member fn
    void initialize() {
        for (int i = 0; i < adj_mat.size(); i++) {
            for (int j = 0; j < adj_mat[0].size(); j++) {
                char choice;
                do {
                    std::cout << "Enter adj mat value for [y/n] " << i << ":" << j << std::endl;
                    std::cin >> choice;
                    if (choice == 'y') {
                        adj_mat[i][j] = true;
                    } else {
                        adj_mat[i][j] = false;
                    }

                    if (std::cin.fail() || (choice!='y' && choice!='n' )) {
                        std::cout << "enter a valid value please!!" << std::endl;
                        std::cin.clear();
                        std::cin.ignore(BUFFER_CLEAR_VALUE,'\n');
                    }
                } while( std::cin.fail() || (choice!='y' && choice!='n' ));
            }
        }
    }

    // member fn
    void showMatrix() {
        std::cout << std::endl << "Adjacency Matrix" << std::endl;
        for (int i = 0; i < adj_mat.size(); i ++) {
            for (int j = 0; j < adj_mat[i].size(); j++) {
                std::cout << adj_mat[i][j] << "\t";
            }
            std::cout << std::endl;
        }
    }

    // member fn
    void breadthFirstSearch(int start_point, int end_point) {
        std::queue<int> vertex_queue;
        std::set<int> visited_vertices;
        vertex_queue.push(start_point);

        while(!vertex_queue.empty()) {
            // Get next vertex
            int current_vertex = vertex_queue.front();
            vertex_queue.pop();

            // Make note of current visit
            visited_vertices.insert(current_vertex);
            std::cout << "Looking at " << current_vertex << std::endl;

            for (int j = 0; j < adj_mat[current_vertex].size(); j++) {
                if (adj_mat[current_vertex][j]) {
                    if (j == end_point) {
                        std::cout << "Found it " << j << std::endl;
                        return;
                    } else if (!(visited_vertices.find(j) != visited_vertices.end())) {
                        vertex_queue.push(j);
                    }
                }
            }
        }
        std::cout << "Could not find it!" << std::endl;
    }
};


int main() {
    Graph g;
    g.initialize();
    g.showMatrix();
    g.breadthFirstSearch(0, 1);
    g.breadthFirstSearch(0, 4);
    return 0;
}

几点

  • 这是 C++,为什么不使用 vector 等来代替你处理内存之类的东西呢? (如果这不是你想要的,你没有这样表示)
  • BFS 背后的关键思想是
    • 查看当前节点的所有邻居,开始处理邻居的邻居
    • 仅在您之前没有处理过节点的情况下处理一个节点
  • 您做事的方式无所不在。该矩阵只有false。您是否打算在某个时候更改此设置?
  • 您的大小计算错误,它们只对指针起作用!
  • 您没有有效的终止标准。您在寻找 BFS 什么?您还需要知道何时停止搜索。并报告发生的事情
  • 我改变了什么
    • 改用 cpp 的 std 容器
    • 删除了using namespace std; 的使用
    • main中提供了一个非常基础的测试用例
    • 添加了初始化和打印矩阵的方法

运行我上面分享的代码以获得这样的图表

$ ./Adjacency                       
Enter vertex num                             
5                                            
Enter adj mat value for [y/n] 0:0            
y                                            
Enter adj mat value for [y/n] 0:1            
y                                            
Enter adj mat value for [y/n] 0:2            
n                                            
Enter adj mat value for [y/n] 0:3            
n                                            
Enter adj mat value for [y/n] 0:4            
n                                            
Enter adj mat value for [y/n] 1:0            
y                                            
Enter adj mat value for [y/n] 1:1            
y                                            
Enter adj mat value for [y/n] 1:2            
y                                            
Enter adj mat value for [y/n] 1:3            
y                                            
Enter adj mat value for [y/n] 1:4            
n                                            
Enter adj mat value for [y/n] 2:0            
n                                            
Enter adj mat value for [y/n] 2:1            
y                                            
Enter adj mat value for [y/n] 2:2
y
Enter adj mat value for [y/n] 2:3
n
Enter adj mat value for [y/n] 2:4
n
Enter adj mat value for [y/n] 3:0
n
Enter adj mat value for [y/n] 3:1
y
Enter adj mat value for [y/n] 3:2
n
Enter adj mat value for [y/n] 3:3
y
Enter adj mat value for [y/n] 3:4
n
Enter adj mat value for [y/n] 4:0
n
Enter adj mat value for [y/n] 4:1
n
Enter adj mat value for [y/n] 4:2
n
Enter adj mat value for [y/n] 4:3
n
Enter adj mat value for [y/n] 4:4
y

Adjacency Matrix
1       1       0       0       0
1       1       1       1       0
0       1       1       0       0
0       1       0       1       0
0       0       0       0       1
Looking at 0
Found it 1
Looking at 0
Looking at 1
Looking at 2
Looking at 3
Could not find it!

建议的可能改进

  1. 更好的抽象功能,现在Graph是神级了
  2. 不要为列 = 行的邻接矩阵中的输入收集输入
  3. 根据先前的值推断矩阵的值,例如:如果 1 在 2 旁边,那么您知道 2 在 1 旁边
  4. 处理输入越来越好,我忘了cin东西的干净方式

如果您坚持使用指向数组的指针,您只需更改构造函数和.size() 调用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-16
    • 1970-01-01
    • 2017-08-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多