BFS(宽度优先搜索)邻接矩阵C ++

时间:2018-09-05 19:45:45

标签: c++ data-structures queue

我正在尝试使用邻接矩阵学习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
                }
            }
        }

    }



};

1 个答案:

答案 0 :(得分:2)

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

#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中提供了一个非常基本的测试用例
    • 添加了初始化和打印矩阵的方法

运行我在上面为这样的图共享的代码

Simple Graph

$ ./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. 不要在column = row的邻接矩阵中收集输入信息
  3. 根据先前的值外推矩阵的值,例如:如果1在2旁边,那么您知道2在1旁边
  4. 处理输入变得越来越好,我忘记了cin东西的干净方法

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