diff --git a/src/main.c b/src/main.c index 9c901b6..b8530a2 100644 --- a/src/main.c +++ b/src/main.c @@ -29,7 +29,7 @@ int main(int argc, char *argv[]) graph_mco gmc = mcgragh(); // find_funcs("/home/user/files/dot_files/st/x.c", &gv, &gmc); // find_funcs("test.c", &gv, &gmc); - findAndParse("/home/user/files/dot_files/dwm/", &gv, &gmc); + findAndParse("/home/user/files/dot_files/st/", &gv, &gmc); // int n = mcis_in(gmc, m); // printf("%d\n", n); // mcprint_edges(gmc, n); @@ -43,7 +43,8 @@ int main(int argc, char *argv[]) // } // printf("TEST: %s %d\n", gmc.func[2], gmc.vec[2].j); // - // vprint_nodes(gv.node[n]); + // vprint_nodes(gv.node[0]); + vfind_cycles(&gv); mcdelete_graph(&gmc); vdot_graph(gv, true); vdelete_graph(&gv); diff --git a/src/matcom.c b/src/matcom.c index 853f6a9..57f50b8 100644 --- a/src/matcom.c +++ b/src/matcom.c @@ -1,8 +1,10 @@ #include "matcom.h" -#include +#include "stack.h" #include -#include #include +#include +#include +#include graph_mco mcgragh(void) { diff --git a/src/matcom.h b/src/matcom.h index 9672023..cd20522 100644 --- a/src/matcom.h +++ b/src/matcom.h @@ -14,8 +14,8 @@ struct graph_mco { int nbs; // nombre de sommets int nba; // nombre d'aretes int vcap; // capacité de vec - int fcap; // capacité de vec - fix_str *func; // noms de fonction + int fcap; // capacité de func + fix_str *func; // noms de fonctions struct edge *vec; // vecteur d'aretes }; diff --git a/src/stack.c b/src/stack.c new file mode 100644 index 0000000..fd24cb1 --- /dev/null +++ b/src/stack.c @@ -0,0 +1,44 @@ +#include "stack.h" +#include +#include + +stack_t init_stack(void) +{ + stack_t s; + s.p = malloc((s.cap = 128) * sizeof(int)); + assert(s.p); + s.top = -1; + return s; +} + +void push(stack_t *stack, int v) +{ + if (stack->top >= stack->cap) { + stack->p = realloc(stack->p, (stack->cap += 128) * sizeof(int)); + assert(stack->p); + } + stack->top++; + stack->p[stack->top] = v; +} + +int pop(stack_t *stack) +{ + return stack->p[stack->top--]; +} + +int empty(stack_t stack) +{ + return stack.top < 0; +} + +int top(stack_t stack) +{ + return stack.p[stack.top]; +} + +void free_stack(stack_t *s) +{ + if (s->p) + free(s->p); + s->p = NULL; +} diff --git a/src/stack.h b/src/stack.h new file mode 100644 index 0000000..6ef1532 --- /dev/null +++ b/src/stack.h @@ -0,0 +1,20 @@ +#ifndef STACK_H + +#define STACK_H + +typedef struct stack_t stack_t; + +struct stack_t { + int *p; + int top; + int cap; +}; + +void push(stack_t *stack, int v); +int pop(stack_t *stack); +int empty(stack_t stack); +int top(stack_t stack); +stack_t init_stack(void); +void free_stack(stack_t *s); + +#endif /* end of include guard: STACK_H */ diff --git a/src/vec.c b/src/vec.c index 83235f0..729d3e7 100644 --- a/src/vec.c +++ b/src/vec.c @@ -1,3 +1,4 @@ +#include "stack.h" #include "vec.h" #include #include @@ -25,6 +26,7 @@ void vinsert_node(graph_vec *g, fix_str str) n->num = g->n; n->nbs = 0; n->vu = 0; + n->dvu = 0; n->cap = 5; n->succ = malloc(5 * sizeof(nodept)); strcpy(n->func, str); @@ -102,7 +104,7 @@ void main_graph(FILE *fp, nodept node) if (node->vu == 1) return; node->vu = 1; - printf("NODE: %s\n", node->func); + // printf("NODE %d: %s\n", node->num, node->func); for (i = 0; i < node->nbs; ++i) { fprintf(fp, "\t%s -> %s;\n", node->func, node->succ[i]->func); } @@ -137,3 +139,51 @@ void vdot_graph(graph_vec g, bool main) fclose(fp); } + +enum { NOT_VISITED = 0, IN_STACK = 1, DONE = 2 }; + +// NOTE: https://www.baeldung.com/cs/detecting-cycles-in-directed-graph +void print_cycle(graph_vec g, stack_t s, int v) +{ + stack_t s2 = init_stack(); + push(&s2, pop(&s)); + while (top(s2) != v) { + push(&s2, pop(&s)); + } + while (!empty(s2)) { + printf("%s -> ", g.node[pop(&s2)]->func); + } + printf("%s\n", g.node[v]->func); + free_stack(&s2); +} + +void processDFS(nodept n, stack_t *s, graph_vec g) +{ + int i; + for (i = 0; i < n->nbs; ++i) { + int v = n->succ[i]->num; + if (n->succ[i]->dvu == IN_STACK) { + print_cycle(g, *s, v); + } else if (n->succ[i]->dvu == NOT_VISITED) { + push(s, v); + n->succ[i]->dvu = IN_STACK; + processDFS(n->succ[i], s, g); + } + } + n->dvu = DONE; + pop(s); +} + +void vfind_cycles(graph_vec *g) +{ + int v; + for (v = 0; v <= g->n; ++v) { + if (g->node[v]->dvu == NOT_VISITED) { + stack_t s = init_stack(); + push(&s, v); + g->node[v]->dvu = IN_STACK; + processDFS(g->node[v], &s, *g); + free_stack(&s); + } + } +} diff --git a/src/vec.h b/src/vec.h index 6585f24..180b07e 100644 --- a/src/vec.h +++ b/src/vec.h @@ -9,17 +9,18 @@ typedef struct node *nodept; typedef struct nodes graph_vec; struct nodes { - int n; - int cap; - nodept *node; + int n; // nombre de noeuds + int cap; // capacité (pour realloc) + nodept *node; // toutes les nodes }; struct node { + int dvu; int vu; int num; // le numero de noeud int nbs; // nombre de successeurs fix_str func; // noms de fonctions - int cap; + int cap; // capacité (pour realloc) nodept *succ; // les successeurs }; @@ -29,5 +30,6 @@ void vdelete_graph(graph_vec *g); int vis_in(graph_vec g, fix_str func); void vdot_graph(graph_vec g, bool main); void vprint_nodes(nodept node); +void vfind_cycles(graph_vec *g); #endif /* end of include guard: VEC_H */