【问题标题】:Creating a graph by using adjacency matrix使用邻接矩阵创建图
【发布时间】:2018-12-02 05:34:06
【问题描述】:

这是我的结构

struct node{
    int V,E;
    int **adj;
};

这是我创建图表的代码:

struct node* create()
{
    int i,j,x,y;
    struct node *G=malloc(sizeof(struct node));
    printf("Write the number of vertex and edges\n");
    scanf("%d%d",&G->V,&G->E);
    G->adj=malloc(sizeof(int)*(G->V * G->V));
    if(!G->adj){
        printf("Out of memory\n");
        return;
    }
    for(i=0;i<G->V;i++)
    for(j=0;j<G->V;j++)
    G->adj[i][j]=0;
    printf("\nWrite the source node and destination: ");
    for(i=0;i<G->E;i++){
    scanf("%d%d",&x,&y);
    G->adj[x][y]=1;
    G->adj[y][x]=1;
    }
    return(G);
}

我将这个函数返回的指针存储在另一个指针中,如下所示:

int main()
{
    struct node *G=create();
}

当我编译程序时,我被要求输入顶点和边的数量,但只要我输入值,我的程序就会崩溃。我想知道原因。这是因为内存分配失败吗?

【问题讨论】:

  • 我看到的是小尼特。不检查有效输入(输入图形边时的顶点数、边数、节点号),不检查 G 是否为 NULL,并且当 malloc 返回 NULL 时,return 语句中没有值。最后一点甚至无法在我使用的编译器上编译。
  • 关于邻接矩阵的两个注意事项:首先, calloc() 将为您将矩阵归零,如果您的矩阵将全部为 0 和 1 值,您可以使用 char 来节省内存int 的元素类型。但首先,您可能想说明您使用的是什么输入...
  • @MikeHousky 没关系!但我不能有任何记忆问题。我有一个 4 GB 的 RAM。我的代码有问题。你能猜出是怎么回事吗?
  • “但首先,您可能想说明您使用的是什么输入。”在 return 语句修复之后,我在编译时没有收到任何错误。
  • 我使用 4 作为顶点数,使用 5 作为边数。对于邻接矩阵,我将使用 0 和 1

标签: c function matrix graph malloc


【解决方案1】:

C99 样式的可变长度数组仅对局部变量或参数有用。因此,您可以使用两种经典的 C 方法来实现二维数组。

  1. 指针数组:

这就是你的结构的样子。这样,您需要为指针数组和数据分别分配:

G->adj = calloc(G->V, sizeof (int*));
assert(G->adj != NULL); /* need assert.h for this */
for (i=0; i<G-V; ++i)
{
    G->adj[i] = calloc(G->V, sizeof (int));
    assert(G->adj[i] != NULL);
}

在内存上对数组数据进行一次批量分配,然后使用指针运算来设置G-&gt;adj[] 指针会更容易一些,但上面给出的想法是,就 C 而言,每一行都是一个单独的数组。

  1. 只有一个大容量数组,每次访问都会进行显式单元位置计算。这就是 C 在内部对嵌套数组所做的事情。

adj 的类型更改为int*,然后:

G->adj = calloc(G->V * G->V, sizeof (int));
assert(G->adj != NULL);

就是这样。现在当你访问一个元素时,使用G-&gt;adj[i*G-&gt;V + j],而不是G-&gt;adj[i][j]。宏可能有助于提高可读性。

【讨论】:

  • 当然有可变长度的二维数组,虽然你是对的,因为它不能存储到全局结构中。但是,您对assert 的使用是不正确的,因为assert 用于说明不变量,即在正确代码中永远不会发生但calloc 可以返回NULL 内存已用尽,即使程序是正确的.
  • @AnttiHaapala 在 2D VLA 中两个维度可以变化吗? (我不使用它们,因为我需要在--呃--Visual C++ 上编译东西。)无论如何,如果出现任何故障,断言只是在调试期间停止测试运​​行。断言失败对于生产来说是一个糟糕的 UI,即使没有语义上的反对。
  • 是的,两个维度都可以变化。但事实上,可变修改类型的有限范围意味着它不是这里的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多