0

Here is the implementation of my adjacency list used to form a graph. I have no idea how to access this list and loop through it to fulfill some goals (DFS search for instance).

I tried to do something like graph[i][j] but the compiler would say it's an error

subscripted value is neither array nor pointer

I reckon the graph here is merely a pointer pointing to another list.

What should I go about it?

Note: I was not able to properly format the code hence I opted to use paste bin, sorry for the inconveniences.

graph.c

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>

#include "graph.h"

/* helper function prototypes */

// create a new vertex with a specific label
Vertex* new_vertex(const char* name);

// create a new w-weighted edge from vertex id u to vertex id v
Edge* new_edge(int u, int v, int w);

// destroy a vertex, including its label and all of its edges
void free_vertex(Vertex* vertex);


/* function definitions */

// create a new, empty graph, with space for n vertices
Graph* new_graph(int n) {
    Graph* graph = malloc(sizeof (*graph));
    assert(graph);

    graph->n = 0;
    graph->maxn = n;

    graph->vertices = malloc(n * sizeof (Vertex*));
    assert(graph->vertices);

    return graph;
}

// create a new vertex with a specific label
Vertex* new_vertex(const char* label) {
    assert(label);

    Vertex* vertex = malloc(sizeof (*vertex));
    assert(vertex);

    // make sure to copy the label across
    vertex->label = malloc((1 + strlen(label)) * sizeof (char));
    assert(vertex->label);
    strcpy(vertex->label, label);

    vertex->first_edge = NULL;

    return vertex;
}

// create a new w-weighted edge from vertex id u to vertex id v
Edge* new_edge(int u, int v, int w) {
    Edge* edge = malloc(sizeof (*edge));
    assert(edge);

    edge->u = u;
    edge->v = v;
    edge->weight = w;

    edge->next_edge = NULL;

    return edge;
}

// destroy a graph, its vertices, and their edges
void free_graph(Graph* graph) {
    if (graph) {
        int i;
        for (i = 0; i < graph->n; i++) {
            free_vertex(graph->vertices[i]);
        }

        free(graph->vertices);
        free(graph);    
    }
}

// destroy a vertex, including its label and all of its edges
void free_vertex(Vertex* vertex) {
    if (vertex) {
        while (vertex->first_edge) {
            Edge* edge = vertex->first_edge;
            vertex->first_edge = vertex->first_edge->next_edge;
            free(edge);
        }
        free(vertex->label);
        free(vertex);   
    }
}

// add a new vertex with label 'name' to a graph
void graph_add_vertex(Graph* graph, const char* name) {
    if (graph->n < graph->maxn) {
        graph->vertices[graph->n] = new_vertex(name);   
        graph->n++;
    } else {
        fprintf(stderr, "hey! adding new vertex to full graph\n");
    }
}

// add an undirected edge between u and v with weight w to graph
void graph_add_u_edge(Graph* graph, int u, int v, int w) {
    // an undirected edge is just two directed edges
    graph_add_d_edge(graph, u, v, w);
    graph_add_d_edge(graph, v, u, w);
}

// add a directed edge from u to v with weight w to a graph
void graph_add_d_edge(Graph* graph, int u, int v, int w) {
    if(u < graph->n && u >= 0 && v < graph->n && v >= 0) {
        Edge* edge = new_edge(u, v, w);
        edge->next_edge = graph->vertices[u]->first_edge;
        graph->vertices[u]->first_edge = edge;
    } else {
        fprintf(stderr, "hey! adding edge between non-existant vertices\n");
    }
} 

graph.h

#ifndef GRAPH_H
#define GRAPH_H

typedef struct graph Graph;
typedef struct vertex Vertex;
typedef struct edge Edge;

// a graph knows its order (number of vertices) and an array of pointers to
// those vertices.
// these values can be used, but should not be *modified* outside of graph.c. 
// they are read-only!
struct graph {
    int n, maxn;
    Vertex** vertices;
};

// a vertex has a label and a pointer to the first edge in its adjacency list.
// these values can be used, but should not be *modified* outside of graph.c. 
// they are read-only!
struct vertex {
    char* label;
    Edge* first_edge;
};

// an edge knows the IDs of its two incident vertices; from u, to v
// each edge also knows its weight, and points to the next edge in a list of
// edges from the same vertex (or to NULL if it's the last edge in the list).
// these values can be used, but should not be *modified* outside of graph.c. 
// they are read-only!
struct edge {
    int u, v;
    int weight;
    Edge* next_edge;
};

// create a new, empty graph, with space for a maximum of n vertices
Graph* new_graph(int n);

// destroy a graph, its vertices, and their edges
void free_graph(Graph* graph);


// add a new vertex with label 'name' to a graph
void graph_add_vertex(Graph* graph, const char* name);

// add an undirected edge between u and v with weight w to graph
void graph_add_u_edge(Graph* graph, int u, int v, int w);

// add a directed edge from u to v with weight w to a graph
void graph_add_d_edge(Graph* graph, int u, int v, int w);

#endif
2Xchampion
  • 666
  • 2
  • 10
  • 24

1 Answers1

1

Your graph is a pointer to a Graph object. That object has member vertices, an array of pointer to Vertex objects. So, the vertices are at graph->vertices, and vertex #0 would be at graph->vertices[0].

Each vertex has a member first_edge, which is a pointer to its first edge. The first edge of vertex #0 is, therefore, graph->vertices[0]->first_edge, and its weight is, e.g., at graph->vertices[0]->first_edge->weight.

The next edge on the adjacency list is the first edge's next_edge (e.g., graph->vertices[0]->first_edge->next_edge). To find all edges, you should process the list using a for loop, starting from graph->vertices[0]->first_edge and continuing to the next_edge, until the next_edge is 0.

for(Edge *current = graph->vertices[0]->first_edge; 
    current;
    current = current->next_edge) {
    do_something_with(current);
}

Hope it helps.

DYZ
  • 55,249
  • 10
  • 64
  • 93
  • so the loop itself is aware that if next_edge hits the end of the vertex it will stop automatically? Sorry if I sound dumb... Thank you for the help btw! It's really coming together. – 2Xchampion Apr 02 '17 at 05:49
  • 1
    Nothing happens _automatically_. The loop stops because the condition `current` becomes false. – DYZ Apr 02 '17 at 05:51
  • ah I get it now! It's because now next_edge points to nothing (0 in this case), so the loop will not run right? – 2Xchampion Apr 02 '17 at 05:54