graph

unidirected graph implementation using adjacency list
Index Commits Files Refs README LICENSE
commit 70840ab67036bfd6007dcfb41269131053752dc9
parent b99e54745f24a3eca97315343094b97d56545ee2
Author: mjkloeckner <martin.cachari@gmail.com>
Date:   Tue, 31 Jan 2023 22:19:29 -0300

added queue module for breath first search

Diffstat:
Mmain.c | 43+++++++++++++++++++++++++++++++++++++++----
Aqueue.c | 64++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aqueue.h | 29+++++++++++++++++++++++++++++
3 files changed, 132 insertions(+), 4 deletions(-)
diff --git a/main.c b/main.c
@@ -5,6 +5,7 @@
 #include <stdbool.h>
 
 #include "stack.h"
+#include "queue.h"
 
 #define GRAPH_INITIAL_ALLOC 5
 #define GRAPH_GROWTH_FACTOR 2
@@ -35,6 +36,7 @@ typedef struct {
 void graph_new(Graph **G);
 void graph_print(const Graph *G);
 void graph_print_gv(const Graph *G);
+void graph_bfs(const Graph *G, const Vertex *v);
 void graph_dfs(const Graph *G, const Vertex *v);
 void graph_add_vertex(Graph *G, Vertex *v);
 void graph_rm_vertex(Graph *G, Vertex *v);
@@ -139,22 +141,52 @@ void graph_dfs(const Graph *G, const Vertex *v) {
     stack_new(&S, sizeof(Vertex *));
     stack_push(S, &v);
 
+    puts("strict digraph G {");
     while(S->len) {
         stack_pop(S, &aux);
 
         if (!aux->visited) {
             aux->visited = true;
             vertex_get_value(aux, &x);
-            printf("%d -> ", x);
+            printf("    %d -> {", x);
 
             for(size_t j = 0; j < aux->edges_no; j++) {
                 stack_push(S, &(aux->edges[j]));
                 vertex_get_value(aux->edges[j], &x);
-                printf("%d%s", x, (j < (aux->edges_no - 1)) ? " -> " : "");
+                printf("%d%s", x, (j < (aux->edges_no - 1)) ? "," : "}");
             }
             printf("\n");
         }
     }
+    puts("}");
+}
+
+/* non-recursive Breadth-First Search */
+void graph_bfs(const Graph *G, const Vertex *v) {
+    Queue *Q;
+    Vertex *aux;
+    int x;
+
+    queue_new(&Q, sizeof(Vertex *));
+    queue_enqueue(Q, &v);
+
+    puts("strict digraph G {");
+    while(queue_is_empty(Q)) {
+        queue_dequeue(Q, &aux);
+        if(!aux->visited) {
+            aux->visited = true;
+            vertex_get_value(aux, &x);
+            printf("    %d -> {", x);
+            for(size_t j = 0; j < aux->edges_no; j++) {
+                vertex_get_value(aux->edges[j], &x);
+                printf("%d%s", x, (j < (aux->edges_no - 1)) ? "," : "}");
+                if(!aux->edges[j]->visited)
+                    queue_enqueue(Q, &(aux->edges[j]));
+            }
+            printf("\n");
+        }
+    }
+    puts("}");
 }
 
 void vertex_new(Vertex **x, const Vertex_getter getter,
@@ -182,7 +214,7 @@ void vertex_add_edge(Vertex *x, Vertex *edge) {
 
     else if (x->edges_no == x->edges_alloc)
         x->edges = realloc(x->edges,
-                x->edges_alloc + (1 * VERTEX_EDGES_GROWTH_FACTOR));
+                (x->edges_alloc *= VERTEX_EDGES_GROWTH_FACTOR));
 
     x->edges[x->edges_no++] = edge;
 }
@@ -242,7 +274,10 @@ int main (void) {
 
     vertex_add_edge(graph->vertices[5], graph->vertices[3]);
 
-    graph_dfs(graph, graph->vertices[0]);
+    /* graph_bfs(graph, graph->vertices[0]); */
+    /* graph_dfs(graph, graph->vertices[0]); */
+    /* graph_print_gv(graph); */
+
     graph_destroy(graph);
     return 0;
 }
diff --git a/queue.c b/queue.c
@@ -0,0 +1,64 @@
+#include "queue.h"
+
+/* FIFO: First In First Out */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+void queue_new(Queue **Q, size_t type_size) {
+    (*Q) = malloc(sizeof(Queue));
+    (*Q)->first = NULL;
+    (*Q)->end = NULL;
+    (*Q)->type_size = type_size;
+}
+
+void queue_enqueue(Queue *Q, void *data) {
+    Node *new = malloc(sizeof(Node));
+    new->data = malloc(Q->type_size);
+    memcpy(new->data, data, Q->type_size);
+
+    if(!Q->first) Q->first = new;
+
+    if(!Q->end) Q->end = new;
+    else Q->end->next = new;
+
+    new->prev = Q->end;
+    new->next = NULL;
+    Q->end = new;
+}
+
+void queue_dequeue(Queue *Q, void *data) {
+    assert(Q->first);
+    assert(Q->end);
+
+    memcpy(data, Q->first->data, Q->type_size);
+
+    Q->first->prev = Q->first;
+    Q->first = Q->first->next;
+    if(Q->first == NULL) return;
+
+    free(Q->first->prev->data);
+    free(Q->first->prev);
+    Q->first->prev = NULL;
+}
+
+bool queue_is_empty(Queue *Q) {
+    return Q->first;
+}
+
+void queue_destroy(Queue *Q) {
+    for(Node *n = Q->first; n; n = n->next)
+        free(n->prev);
+
+    if(Q->end)
+        free(Q->end->data);
+
+    free(Q->end);
+    if(Q->first)
+        free(Q->first->data);
+
+    free(Q->first);
+    free(Q);
+}
diff --git a/queue.h b/queue.h
@@ -0,0 +1,29 @@
+#ifndef QUEUE_H_
+#define QUEUE_H_
+
+#include <stddef.h>
+#include <stdbool.h>
+
+typedef struct Node Node;
+typedef struct Queue Queue;
+
+struct Node {
+    void *data;
+    Node *next;
+    Node *prev;
+};
+
+struct Queue {
+    size_t type_size;
+    Node *first;
+    Node *end;
+};
+
+void queue_new(Queue **Q, size_t type_size);
+void queue_enqueue(Queue *Q, void *data);
+void queue_dequeue(Queue *Q, void *data);
+void queue_destroy(Queue *Q);
+
+bool queue_is_empty(Queue *Q);
+
+#endif