【问题标题】:Implementing undirected graph with adjacency matrix用邻接矩阵实现无向图
【发布时间】:2019-04-24 16:01:06
【问题描述】:

我试图用邻接矩阵实现一个无向图。
顶点值的类型是整数。并且我使用双指针来表示邻接矩阵。

问题就在我输入了所有顶点值之后,
我从下面发布的代码中进行了编程,运行时错误
发生了。然后,我在发生错误的错误内容行添加了注释。我知道原因一定是我分配的双指针
。但是我真的不知道如何调试它。
有人可以帮我吗?谢谢!

#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
    int adj;
}verNode;
typedef struct graph
{
    verNode **matrix;
    int* verList;
    int verNum;
    int edgeNum;
}graph;
graph* createGraph(int v)
{
    graph *g=malloc(sizeof(graph));
    if(!g) exit(-1);
    g->matrix=NULL;
    g->verList=malloc(sizeof(verNode)*v);
    if(!g->verList) exit(-1);
    g->verNum=v;
    printf("Enter the value of vertices:\n");
    for(int i=0;i<g->verNum;i++)
    {
        printf("Enter the value of vertex %d:\n",i);
        scanf("%d",g->verList);
    }
    return g;
}
verNode** createMatrix(graph *g)
{
    if(!g) exit(-1);
    g->matrix=malloc(sizeof(int*)*g->verNum*g->verNum);
    if(!g->matrix) exit(-1);
    for(int i=0;i<g->verNum;i++)
    {
        for(int j=0;j<g->verNum;j++)
        {
            (*g->matrix)->adj=0; //error:EXC_BAD_ACCESS (code=1,           //address=0x0)
        }
    }
    return g->matrix;
}
void addEdge(graph *g,int v)
{
    if(!g||!g->matrix||!g->verList) exit(-1);
    int ver1,ver2;
    g->edgeNum=v;
    printf("Enter the indexes of the vertices:\n");
    for(int i=0;i<g->edgeNum;i++)
    {
        printf("Enter the index of vertex 1:\n");
        scanf("%d",&ver1);
        printf("Enter the index of vertex 2:\n");
        scanf("%d",&ver2);
        if(ver1>g->verNum-1||ver2>g->verNum-1) exit(-1);
        g->matrix[ver1][ver2].adj=1;
        g->matrix[ver2][ver1].adj=1;
    }
}
void printMatrix(graph *g)
{
    if(!g||!g->matrix||!g->verList) exit(-1);
    printf("Print the adjacency matrix:");
    for(int i=0;i<g->verNum;i++)
    {
        for(int j=0;j<g->verNum;j++)
        {
            printf("%d ",g->matrix[i][j].adj);
        }
        printf("\n");
    }
}
int main() {
    graph *g=createGraph(5);
    verNode **matrix =createMatrix(g);
    g->matrix=matrix;
    addEdge(g,7);

    return 0;
}

【问题讨论】:

    标签: c double-pointer undirected-graph


    【解决方案1】:

    这里:

    g->matrix = malloc(sizeof(int*) * g->verNum * g->verNum);
    

    您分配一个大小为 V×V 的平面一维数组。您可以像访问二维数组一样访问该数组:g-&gt;matrix[i][j].adj

    将邻接矩阵表示为二维数组是一个好主意,但您的分配也必须是二维的:分配一个 V 指针数组到int,然后使每个指向 V 个整数数组的句柄:

    g->matrix = malloc(g->verNum * sizeof(*g->matrix));
    
    for (int i = 0; i < g->verNum; i++) {
        g->matrix[i] = calloc(g->verNum, sizeof(*g->matrix[i]));    
    }
    

    注意事项:

    • calloc(n, size) 类似于 malloc(n*size),但它首先将内存清零,因此您可以从一个未连接的图开始。
    • p = malloc(n * sizeof(*p)) 是一个有用的习惯用法,它从 p 推断类型,而不是显式指定类型。
    • 还有其他方法可以获取二维数组。例如,您可以分配一个维度为 V×V 的平面数组,然后将 matrix 设为指向该数组的指针数组,这样 matrix[i]表示平面数组中的一行。我认为出于学习目的,上述方法更好,因为它更直接。
    • 当然你以后必须free分配的内存。以相反的顺序执行此操作:首先释放 matrix[i],然后是正确的 matrix

    【讨论】:

      【解决方案2】:

      您已将graph.matrix 声明为vernode **。您已经为特定实例g-&gt;matrix 分配了内存,显然是成功的。 *g-&gt;matrix 指定出现在该空间开头的vernode *(并且鉴于您打算将该空间用作数组,将该元素指定为g-&gt;matrix[0] 更为传统,这是等效的)。 但是你从来没有给那个对象赋值。它的值是不确定的,您通过尝试访问它来调用未定义的行为。

      总体而言,您似乎已经将多种不同方法的各个方面融合在一起。这个分配...

      g->matrix=malloc(sizeof(int*)*g->verNum*g->verNum);
      

      ... 首先是错误的,因为假设sizeof(int *)sizeof(vernode *) 相同是不安全的,而后者是您实际需要的g-&gt;matrix 声明类型。这似乎也是错误的,因为您分配的空间比我预期的基于双指针的方法要多得多。通常会为每一行分配一个指针,而不是每个元素一个,然后分别为每一行的元素分配内存。这将支持双索引,就好像您有一个真正二维数组:g-&gt;matrix[i][j].adj = 0;

      可以对所有顶点只使用一个分配,但是您需要一个单个指针(vernode *matrix;),并且您需要使用不同的指数计算:g-&gt;matrix[i * g-&gt;verNum + j].adj = 0;.

      【讨论】:

      • "假设sizeof(int *)sizeof(vernode *) 相同是不安全的" ?指针的大小总是一样的,不依赖于指向的类型,幸运的是
      • @bruno 经常是这种情况,在许多实现中系统地如此,但实际上它是保证的。
      • 非常感谢
      猜你喜欢
      • 2017-07-24
      • 1970-01-01
      • 1970-01-01
      • 2014-05-04
      • 2017-10-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多