0

I am trying to implement graph using adjacency list ,according to my knowledge that i have learnt so far if i created variable array pointer to struct adjlistnode of size v*sizeof(struct adjlistnode) thin i can store the addresses of v struct adjlistnode type node in each index of array

Means that each index of array will point to the node of type struct adjlistnode but when i am assigning G->array[i]=NULL it gives me error

||=== Build: Debug in teeest (compiler: GNU GCC Compiler) ===| C:\Users\Mahi\Desktop\DATA STR\teeest\main.c||In function 'creategraph':| C:\Users\Mahi\Desktop\DATA STR\teeest\main.c|59|error: incompatible types when assigning to type 'struct adjlistnode' from type 'void *'| ||=== Build failed: 1 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===|

why i am not able to assign NULL to index of array

what should i do if i want to access adjacency list like using G->array[i]=first node address adjacent to ith vertex of graph and later i will add another node if needed

struct adjlistnode{
    int dest;
    struct adjlistnode* next;
};
struct graph{
   int V;
   struct adjlistnode* array;
};
struct adjlistnode* getnewnode(int dest){
   struct adjlistnode* newnode =(struct adjlistnode*)malloc(sizeof(struct adjlistnode));
   newnode->dest=dest;
   newnode->next=NULL;
   return newnode;
}
struct graph* creategraph(int v){
   struct graph* G=(struct graph*)malloc(sizeof(struct graph));
   G->V=v;
   G->array=(struct adjlistnode*)malloc(v*sizeof(struct adjlistnode));

   for(int i=0;i<v;i++){
      G->array[i] =NULL;
   }
   return G;

}
alk
  • 69,737
  • 10
  • 105
  • 255
david12345
  • 32
  • 10

3 Answers3

2

G->array is of type struct adjlistnode *

But

G->array[i] is of type struct adjlistnode.

Thus you cannot assign NULL (of type void *) to G->array[i] of type struct adjlistnode

You should probably have to define array in the struct graph as pointer to pointer

struct graph{
   int V;
   struct adjlistnode** array;
};

and then the following should work for you

struct graph* creategraph(int v){
   struct graph* G=malloc(sizeof(struct graph));
   G->V=v;
   G->array=malloc(v*sizeof(struct adjlistnode*));

   for(int i=0;i<v;i++){
      G->array[i] =NULL;
   }
   return G;

}

** Note1 (as also mentioned by @alk in the comments) that in C, at least since C89 standard, malloc returns void *. void * can be assigned to any other pointer type (and visa versa), thus casting the return value of malloc is not required.

** Note2 (also noted by @alk) that malloc signature is defined with the parameter of type size_t and not int so better to modify the code a little and use the proper type ( Read comparing int with size_t and size_t vs int in C++ and/or C for more info)

Alex Lop.
  • 6,810
  • 1
  • 26
  • 45
  • Nitpicking again: All those `int`s should be `size_t`s. – alk Sep 27 '18 at 12:16
  • @alk, I agree that it would be the most correct and potentially prevent `signed vs unsigned` bugs but it is rather related to *code review* area than to the question itself. But I don't mind to add another note. – Alex Lop. Sep 27 '18 at 12:31
  • if i want to pass `v`as `size_t` then is there any need to change the `int` to `size_t` in my structures – david12345 Sep 27 '18 at 14:11
  • 2
    @david12345 yes, better to be aligned with the proper type. There is no reason for `v` ever be negative – Alex Lop. Sep 27 '18 at 14:13
1

array is a (single) pointer to struct adjlistnode. So it can be set to NULL.

 G->array = NULL; //is okay

But it is not an array of pointers, so you cannot access the elements of the array and they cannot be set to NULL as well.

For dynamic allocation, you should do this:

struct graph{
   int V;
   struct adjlistnode** array;
};
struct graph* creategraph(int v){
   struct graph* G = malloc(sizeof(struct graph));
   G->V = v;   
   G->array = malloc(v * sizeof(struct adjlistnode*)); //allocation for an array of v pointers 

   for(int i = 0; i < v; i++){    
      G->array[i] = NULL;
   }
   return G;
}

As suggested by @alk, it is better if you pass v as size_t instead of int, as malloc takes size_t.

P.W
  • 26,289
  • 6
  • 39
  • 76
1

G->array[i] returns *(array + i * sizeof(struct adjlistnode)) as if array was struct adjlistnode array[].

What you do is store v objects of struct, but you try to initialize them with NULL, like you would a pointer.

What you probably want is

struct graph{
   int V;
   struct adjlistnode** array;
};

[...]

G->array=(struct adjlistnode**)malloc(v*sizeof(struct adjlistnode*));

That would make array a pointer to an array of pointers.

Then G->array[i] would return a struct adjlistnode* pointer to an object of struct, that you can then initialize with your getnewnode().

IcedLance
  • 406
  • 3
  • 12