矢量迭代器在尝试对图形进行深度优先搜索时导致分割错误 11
Vector Iterator causes Segmentation Fault 11 while attempting Depth First Search on a graph
我正在尝试使用基于矢量迭代器的DFS来计算生成的图形的最大连接集群。然而,当图是一定的大小(种子概率高于0.4)时,DFS函数处会发生分割错误11。
#include <iostream>
#include <vector>
#include <random>
float seedingProbability = 0.6;
int latticeSize = 1024;
int graphSize;
bool *visited;
long largestClusterSize = 0;
std::vector<int> *graph;
std::vector<int> currentCluster;
std::uniform_real_distribution<float> unif(0, 1);
std::random_device rd;
std::mt19937 rand_engine(rd());
//Is a random number between 0 and 1 higher than (1-seeding probability)
bool isCriticalThreshold() {
float r = unif(rand_engine); //a random float between 0 and 1
bool isCritical = r > (1-seedingProbability);
return isCritical;
}
//This helper function is used to determine the site index
int siteFor(int x, int y) {
return (latticeSize*x)+y;
}
//Add an undirected edge to the graph between two sites
void addEdge(int site1, int site2) {
graph[site1].push_back(site2);
graph[site2].push_back(site1);
}
void DFS(int v) {
visited[v] = true;
currentCluster.push_back(v);
for (std::vector<int>::iterator it = graph[v].begin(); it != graph[v].end(); it++) {
if(!visited[*it]) {
DFS(*it);
}
}
}
void connectedComponents() {
for (int i=0; i < (graphSize); i++) {
visited[i] = false;
}
for (int i=0; i<(graphSize); i++) {
if (visited[i] == false) {
currentCluster.clear();
DFS(i);
long clusterSize = currentCluster.size();
if (clusterSize > largestClusterSize) {
largestClusterSize = clusterSize;
}
}
}
}
void createGraph() {
for (int x = 0; x < latticeSize; x++) {
for (int y = 0; y < latticeSize; y++) {
//Down bond
if (isCriticalThreshold()) {
if (y == latticeSize-1) { addEdge(siteFor(x, y), siteFor(x, 0)); }
else { addEdge(siteFor(x, y), siteFor(x, y+1)); }
}
//Right bond
if (isCriticalThreshold()) {
if (x == latticeSize-1) { addEdge(siteFor(x, y), siteFor(0, y)); }
else { addEdge(siteFor(x, y), siteFor(x+1, y)); }
}
}
}
}
int main(int argc, const char * argv[]) {
std::cout << "Running..." << std::endl;
graphSize = latticeSize*latticeSize;
graph = new std::vector<int>[graphSize];
visited = new bool[graphSize];
createGraph();
connectedComponents();
std::cout << "Largest cluster: " << largestClusterSize << std::endl;
return 0;
}
我基于DFS的依据: http://www.geeksforgeeks.org/connected-components-in-an-undirected-graph/
正如jszpilewski所指出的,主要问题是你可能耗尽了堆栈内存。像DFS这样的递归算法可以非常快速地填满堆栈。您可以将非递归 DFS 算法与显式托管堆栈一起使用。
我根据您的代码整理了一个示例程序来说明这一点。我冒昧地用对象替换原始指针,用 std::vector
s 替换数组。我认为这在内存管理方面要安全得多。每个节点都是一个简单的struct
,x
和y
坐标作为晶格上的位置。主要变化是 DFS()
,它显式管理每个未访问节点的堆栈。请随时编辑此内容以满足您的需求。我已经用高达 4096 的 latticeSize
测试了代码,它可以工作。请注意,Node
对象只需要存储到所有目标节点的边缘,而不需要存储到源节点的边缘。
#include <iostream>
#include <vector>
#include <random>
#include <functional>
#include <stack>
class Node;
typedef std::reference_wrapper<Node> NodeRef;
float seedingProbability = 0.8;
size_t latticeSize = 4096;
size_t largestClusterSize = 0;
std::vector<size_t> clusters;
std::vector<std::vector<Node>> graph;
std::uniform_real_distribution<float> unif(0.0, 1.0);
std::random_device rd;
std::mt19937 rand_engine(rd());
struct Node
{
size_t x;
size_t y;
bool visited;
std::vector<NodeRef> targets;
// Add edges
void addEdge(Node& _target)
{
targets.emplace_back(_target);
}
explicit Node(size_t _x, size_t _y)
:
x(_x),
y(_y),
visited(false)
{}
};
// Is a random number between 0 and 1 lower than the seeding probability
bool isCriticalThreshold()
{
return unif(rand_engine) < seedingProbability;
}
void DFS()
{
for (auto& row : graph)
{
for (auto& node : row)
{
node.visited = false;
}
}
for (auto& row : graph)
{
for (auto& node : row)
{
if (!node.visited)
{
size_t clusterSize(0);
std::stack<NodeRef> stack;
stack.push(node);
while (!stack.empty())
{
Node& cur_node(stack.top());
stack.pop();
if (!cur_node.visited)
{
cur_node.visited = true;
++clusterSize;
for (auto& tgt : cur_node.targets)
{
stack.push(tgt);
}
}
}
clusters.push_back(clusterSize);
}
}
}
}
void connectedComponents()
{
largestClusterSize = 0;
for (const auto& clusterSize : clusters)
{
if (clusterSize > largestClusterSize)
{
largestClusterSize = clusterSize;
}
}
}
void createGraph()
{
// Generate the lattice
for (size_t x = 0; x < latticeSize; ++x)
{
graph.emplace_back(std::vector<Node>());
for (size_t y = 0; y < latticeSize; ++y)
{
graph.back().emplace_back(x, y);
}
}
// Add edges
for (size_t x = 0; x < latticeSize; ++x)
{
for (size_t y = 0; y < latticeSize; ++y)
{
// Down bond
if (isCriticalThreshold())
{
graph.at(x).at(y).addEdge(graph.at(x).at((y + 1) % latticeSize));
}
// Right bond
if (isCriticalThreshold())
{
graph.at(x).at(y).addEdge(graph.at((x + 1) % latticeSize).at(y));
}
}
}
}
int main(int argc, const char * argv[]) {
std::cout << "Running..." << std::endl;
createGraph();
DFS();
connectedComponents();
// std::cout << "Cluster sizes:n";
// for (size_t c = 0; c < clusters.size(); ++c)
// {
// std::cout << "tCluster " << c << ": " << clusters.at(c) << "n";
// }
std::cout << "Largest cluster: " << largestClusterSize << std::endl;
return 0;
}
堆栈溢出是在大型图上运行递归 DPS 时最典型的问题。在您的情况下,您还需要构建一个辅助数据收集currentCluster
因此请检查您的程序是否没有用完 32 位内存空间(大约 2-4 GB,具体取决于操作系统)。因此,如果您确实在 32 位模式下编译,请尝试生成和测试程序的 64 位版本。
相关文章:
- 提升图:当我的图使用 listS 作为 VertexList 时,如何调用深度优先搜索()?
- 使用迭代深度优先搜索算法的未加权图的最短路径
- 使用后序遍历递归的深度优先搜索会产生意外输出
- 图上的深度优先搜索算法中的内存泄漏
- 为什么此函数中的运行时错误 C++ 深度优先搜索
- 通过深度优先搜索节点链接到自身进行倾倒.C++
- 矢量迭代器在尝试对图形进行深度优先搜索时导致分割错误 11
- 显示深度优先搜索图遍历C++
- 在C++中实现深度优先搜索
- 深度优先搜索过早终止
- 深度优先搜索树遍历实现在C++
- 使用邻接矩阵进行深度优先搜索
- 深度优先搜索的实施和改进
- 并行深度优先搜索C++
- 在迭代深度优先搜索(DFS)算法中确定堆栈大小
- 为什么我在这里泄漏内存(深度优先搜索)c ++
- Traversal迷宫和深度优先搜索
- 在邻接矩阵上应用广度和深度优先搜索
- 深度优先搜索树边分类
- 在c++中使用深度优先搜索查找图数据结构中所有可能的路径