c++ - 特定值的段错误

标签 c++ graph segmentation-fault

我写了一段代码,它首先将矩阵的维度 (n X m) 作为输入,然后是它的元素 01s。现在我正在尝试使用此矩阵构建一个图(邻接列表表示),以便所有 1 都连接到它们相邻的所有其他 1(即,垂直,水平或对角)。矩阵的元素以行主要方式编号,以便将它们表示为图的顶点。

代码如下:

#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
#include <stdlib.h>
#include <list>
#include <deque>

using namespace std;

class Graph
{
 public:

    list<int> *adjlist;
    int v;

    Graph(int v)
    {
        this->v=v;
        adjlist=new list<int> [v];      
    }

    void add_edge(int src, int dest)
    {
        cout<<src<<" "<<dest<<"\n";
        adjlist[src].push_back(dest);
    }

    void dfs_util(int src, bool *visited)
    {
        if(!visited[src])
        {
            cout<<src<<" ";
            visited[src]=true;
            list<int>::iterator i;
            for(i=adjlist[src].begin(); i!=adjlist[src].end(); i++)
            {
                if(!visited[*i])
                {
                    dfs_util(*i, visited);
                }
            }
        }
    }

    void dfs(int src)
    {
        bool visited[v];
        int i;
        for(i=0; i<v; i++)
            visited[i]=false;
        dfs_util(src, visited);
    }

    void bfs(int src)
    {
        int j;
        bool visited[v];
        for(j=0; j<v; j++)
        {
            visited[j]=false;
        }

        int front;
        deque<int> q;
        q.push_back(src);
        list<int>::iterator i;
        visited[src]=true;


        while(!q.empty())
        {
            front=q.front();
            q.pop_front();
            cout<<front<<" ";

            for(i=adjlist[front].begin(); i!=adjlist[front].end(); i++)
            {
                cout<<*i<<"\n";
                if(!visited[*i])
                {
                    visited[*i]=true;
                    q.push_back((*i));
                }
            }
        }
    }

    void display()
    {
        list<int>::iterator it;
        int i;
        //list<int>::iterator it;

        for(i=0; i<v; i++)
        {           
            cout<<"Adj list for "<<i<<"\n";
            for(it=adjlist[i].begin(); it != adjlist[i].end(); ++it)
            {
                cout<<*it<<"->";
            }
            cout<<"\n";
        }
    }
};


int main() {
    int arr[11][11], n, m, i, j, node;
    cin>>n;
    cin>>m;

    for(i=0; i<n; i++)
    {
        for(j=0; j<m; j++)
        {
            cin>>arr[i][j];
        }
    }

    Graph g(n*m-1);

    for(i=0; i<n; i++)
    {
        for(j=0; j<m; j++)
        {
            node=m*i+j;
            if(arr[i][j]==1)
            {
                if((i-1)>=0 && arr[i-1][j]==1)
                    g.add_edge(node, m*(i-1)+j);

                if((i-1)>=0 && (j+1)<m && arr[i-1][j+1]==1)
                    g.add_edge(node, m*(i-1)+(j+1));

                if((j+1)<m && arr[i][j+1]==1)
                    g.add_edge(node, m*(i)+(j+1));

                if((i+1)<n && (j+1)<m && arr[i+1][j+1]==1)
                    g.add_edge(node, m*(i+1)+(j+1));

                if((i+1)<n && arr[i+1][j]==1)
                    g.add_edge(node, m*(i+1)+(j));

                if((i+1)<n && (j-1)>=0 && arr[i+1][j-1]==1)
                    g.add_edge(node, m*(i+1)+(j-1));

                if((j-1)>=0 && arr[i][j-1]==1)
                    g.add_edge(node, m*(i)+(j-1));

                if((i-1)>=0 && (j-1)>=0 && arr[i-1][j-1]==1)
                    g.add_edge(node, m*(i-1)+(j-1));
            }
        }       
    }

    //g.bfs(0);
    //g.dfs(0);
    g.display();
    return 0;
}

现在这段代码在调用 g.bfs(0)g.dfs(0) 时给了我段错误。所以我写了一个简单的显示函数来缩小错误范围,但即使调用 g.display() 也会给我 segmentation fault

然而,当我将 display() 函数中的外循环更改为:

for(i=1; i<n; i++)

它工作得很好,不会出现段错误

我不明白为什么我会收到这些段错误,以及如何将外循环的初始化更改为1 来阻止它。谁能解释一下原因?

这是我使用的示例输入:

5
5
1 1 0 0 0
0 1 1 0 0
0 0 1 0 1
1 0 0 0 1
0 1 0 1 1

最佳答案

问题

您的邻接表是一个数组,而不是列表或 vector :

list<int> *adjlist;

您在构造函数中根据参数 v 对其进行初始化:

adjlist=new list<int> [v];      

因此,在构建图形时,您需要提前提供有多少个邻接表?所以最好不要弄错!

不幸的是,在 main() 中,您使用缺少的项目对其进行了初始化

Graph g(n*m - 1);   //  <----- why -1 ?  Don't you have n*m nodes ?

解决方案

只需调用具有正确大小的构造函数

Graph g(n*m);   //  n*m nodes ! 

如果遇到这样的问题,您可以通过添加一些绑定(bind)检查来帮助自己:

void add_edge(int src, int dest)   // src should be smaller than v 
{
    if (src>=v) {         // nice diagnostic message in case of problem
       cout <<"FAILURE: "<<src<<" out of bound ("<<v<<")"<<endl; 
    }
    else {
        cout<<src<<" "<<dest<<"\n";
        adjlist[src].push_back(dest);
    }
}

如果不总是像那样实现漂亮的错误消息,它至少应该成为对 assert 的反射。满足先决条件:

assert (src<v && dest<v);   

更好的办法是让你的邻接列表 adjlist 成为一个 vector 或 map ,并让它动态增长。

关于c++ - 特定值的段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39809960/

相关文章:

c++ - 您如何找出谁创建了私有(private)堆?

algorithm - 一个有趣的迷宫

Git 日志图在一个地方显示每个分支的提交

c++ - 来自 MPI 的奇怪段错误

c - 总线错误与段错误

c++ - 将字符串转换为 int

c++ - 单纯形法的C/C++实现

graph - 在 OCaml 中定义带有循环的图形节点变体

iOS SIGSEGV SEGV_ACCERR 在layoutSubviews 中崩溃

c++ - Critical Section 对象如何适用于多种方法