C 使用邻接矩阵创建图形
这是我的结构C 使用邻接矩阵创建图形,c,function,matrix,graph,malloc,C,Function,Matrix,Graph,Malloc,这是我的结构 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
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);
}
当我编译程序时,会询问顶点和边的数量,但一旦输入值,我的程序就会崩溃。我想知道原因。这是因为内存分配失败吗?C99样式的变长数组仅对局部变量或参数有用。因此,有两种经典的C方法可用于实现2D数组
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->adj[i*G->V+j]
,而不是G->adj[i][j]
。宏可能有助于提高可读性。我看到的是小的NIT。不检查有效输入(顶点计数、边计数、输入图形边时的节点编号)、不检查G是否为NULL以及malloc返回NULL时返回语句中没有值。最后一位甚至不会在我使用的编译器上编译。关于邻接矩阵的两个注意事项:首先,calloc()会为您将矩阵归零,如果您的矩阵将全部为0和1值,您可以通过使用char
而不是int
为元素类型节省内存。但首先,你可能想说你使用了什么输入…@MikeHousky,没关系!但是我的记忆力没有问题。我有一个4GB内存。我的代码有问题。你能猜出是怎么回事吗?“但首先,你可能想说你使用的是什么输入。”在返回语句修复后,我在编译时没有发现错误。我使用4表示顶点数,5表示边数。对于邻接矩阵,我将使用0和1,当然有可变长度的2d数组,尽管你是正确的,因为这样的数组不能存储到全局结构中。但是,您使用的assert
是不正确的,因为assert
用于表示不变量,即在正确的代码中永远不会发生的事情,但是calloc
可以返回NULL
内存耗尽,即使程序是正确的。@AnttiHaapala两个维度在2D VLA中是否都会变化?(我不使用它们,因为我需要编译的东西-UGH——Visual C++)。无论如何,断言只是在调试期间停止测试运行,如果有任何故障。断言失败对于生产来说是一个糟糕的UI,即使没有语义上的异议。是的,两个维度都可能不同。但事实上,可变修改类型的有限范围意味着它不是这里的答案。
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->adj = calloc(G->V * G->V, sizeof (int));
assert(G->adj != NULL);