Coding adjacency list representing graph
Code style: Use typedef struct instead of struct for cleanliness.

This looks generally OK, but is not strictly speaking an adjacency list representation. In an adjacency list representation you store a list of verticies, and each of those verticies store a list of its neighbours. This structure implicitly encodes the edges of the graph.

A more compact adjacency representation might look something more like this:

typedef struct{
    char *data;
    struct vertex **neighbours;
    char **weight; // edge to neighbours[i] stored in weight[i] 
} vertex;

typedef struct{
    int num_verticies;
    struct vertex **V;
} graph;


The edges can be recovered by traversing the graph. To improve performance we may choose a structure other than a linked list to store the neighbours of a vertex.

Which further annotations you keep in the graph struct will depend on the final use case. For certain algorithm having an explicit edge list will be vital, whereas for others it will be wasteful.