我有以下功能:
std::vector<Node> BFS(Graph g, Node source, Node target) {
std::queue<std::vector<Node> > q;
std::vector<Node> path = {source};
q.push(path);
while (!q.empty()) {
std::vector<Node> cur_path = q.front();
q.pop();
Node cur_node = cur_path[cur_path.size() - 1];
if (cur_node.data == target.data) {
return cur_path;
}
// for (int i = 0; i < g.edge_map[cur_path].size(); i++) {
// std::vector<Node> new_path = cur_path;
// new_path.push_back(g.edge_map[cur_path][i]);
// q.push(new_path);
// }
}
}
现在,我并没有声称这会完成搜索,我只是想知道它为什么会导致分段错误。我知道这是因为我有q.pop();有点,但为什么?这是因为向量本身就是引用吗?如果需要,我可以包含更多代码,只是尝试将问题封装起来。
编辑:这是main()驱动程序:
int main(int argc, char **argv) {
// double normals[][3] = {
// #include "normals.txt"
// };
Graph g;
Node n0 {0, "red"};
Node n1 {1, "yellow"};
Node n2 {2, "black"};
Node n3 {3, "black"};
Node n4 {4, "red"};
Node n5 {5, "yellow"};
Node n6 {6, "black"};
Node n7 {7, "black"};
Node n8 {8, "red"};
Node n9 {9, "yellow"};
Node n10 {10, "black"};
Node n11 {11, "black"};
g.add_neighbor(n0, n1, true);
g.add_neighbor(n0, n2, true);
g.add_neighbor(n0, n3, true);
g.add_neighbor(n2, n4, true);
g.add_neighbor(n4, n5, true);
g.add_neighbor(n4, n6, true);
g.add_neighbor(n4, n7, true);
g.add_neighbor(n6, n8, true);
g.add_neighbor(n8, n9, true);
g.add_neighbor(n8, n10, true);
g.add_neighbor(n8, n11, true);
BFS(g, n0, n11);
return 0;
}
给出:
graph. yup
Segmentation fault (core dumped)
FWIW,我的图形有一个edge_map成员,它是一个以Node结构为键的映射,Node的向量结构为值,表示图形邻接列表。构造函数输出'图。是的,如果您需要更多信息,请告诉我
编辑2:我只是将其余部分用于完整性,对于冗长而感到遗憾,但我正在努力理解为什么会这样。
graph.h:
#include <iostream>
#include <map>
#include <vector>
struct Node {
int data;
std::string color;
};
inline bool operator<(const Node & left, const Node & right) {
return left.data < right.data;
}
class Graph {
public:
std::map< Node, std::vector<Node> > edge_map;
Graph();
void add_neighbor(Node cur_node, Node new_node, bool both_ways=false);
void remove_neighbor(Node cur_node, Node del_node, bool both_ways=false);
void print_neighbors(Node cur_node);
virtual ~Graph();
};
graph.cpp:
#include <iostream>
#include <vector>
#include <algorithm>
#include "graph.h"
#include <map>
Graph::Graph() {
std::cout << "graph. yup" << std::endl;
}
void Graph::add_neighbor(Node cur_node, Node new_node, bool both_ways) {
edge_map[cur_node].push_back(new_node);
if (both_ways) {
edge_map[new_node].push_back(cur_node);
}
}
void Graph::remove_neighbor(Node cur_node, Node del_node, bool both_ways) {
// TODO: convert vector values in map of <Node, vector<Node> > into maps, so this function can be easy and have sensible complexity
std::cout << "Not implemented yet." << std::endl;
// if (both_ways) {
// edge_map[del_node].remove(cur_node);
// }
//this->edge_map[cur_node].erase(std::remove(this->edge_map[cur_node].begin(), this->edge_map[cur_node].end(), del_node), this->edge_map[cur_node].end());
}
void Graph::print_neighbors(Node cur_node) {
for (int i = 0; i < edge_map[cur_node].size(); i++) {
std::cout << edge_map[cur_node][i].data << " " << edge_map[cur_node][i].color << std::endl;
}
}
Graph::~Graph() {
std::cout << "ded graph :(" << std::endl;
}
任何一般的提示也值得赞赏,我是绿色的。
答案 0 :(得分:1)
一个很大的,明显的错误:
您的BFS
函数不会返回所有控制路径的值,即使它应该返回std::vector<Node>
。因此,您的程序具有未定义的行为。 BFS
返回的唯一路径是while
循环中的条件语句:
if (cur_node.data == target.data) {
return cur_path;
但是,如果在运行外部cur_node.data
循环期间target.data
永远不等于while
,则不会返回,从而触发未定义的行为(在您的情况下,是一个分段错误)。
运行程序here, using the triggering output statement, "I'm in trouble!!"表明您正在导致未定义的行为。请注意,使用的编译器是Visual Studio 2015。
但为了显示未定义行为的后果,请注意gcc
as shown here只会在不打印消息的情况下崩溃。要让它打印消息,必须用std::endl
刷新缓冲区以查看“麻烦!!”字符串as seen here。
鉴于所有这些,因为你必须返回一些东西,你必须决定在找不到节点的情况下返回什么。您可以返回std::vector<Node>()
,但调用者BFS
如何确定此节点是否是存在的节点?我认为你需要理清BFS
关于该函数的输出应该表示什么的基本规则。
此外:
Node cur_node = cur_path[cur_path.size() - 1];
可能只是:
Node cur_node = cur_path.back();
答案 1 :(得分:-1)
(我没有足够的声誉来添加评论)
据我所知,可能会发生什么:
q.pop调用std :: vector
~std :: vector销毁每个节点
也许Node析构函数做了非法的事情?