diff --git a/include/db.h b/include/db.h deleted file mode 100644 index c4a0157965486762021e1b9c034fa14b4cbceff9..0000000000000000000000000000000000000000 --- a/include/db.h +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#include "list.h" - -/* file mode : text or binary */ -typedef enum file_mode { TEXT, BINARY } file_mode_t; - -/** - * @brief read a list from a text or binary file acording to the mode - * @param mode : TEXT or BIN - * @param data_read_fct : ptr to fct that reads datum from file fd ; fct's parameters : (fd, mode) - * @param del_fct : ptr to fct that deallocate datum's memory, ; fct's parameter (datum) - */ -list_t * read_list ( file_mode_t mode, void * (*read_fct) (), void (*del_fct) () ); - - -/** - * @brief write a list into a text or binary file acording to the mode - * @param mode : TEXT or BIN - * @param data_write_fct : ptr to fct that writes datum into file fd ; fct's parameters : (datum, fd, mode) - */ -void write_list ( list_t * L, file_mode_t mode, void (*write_fct) () ); \ No newline at end of file diff --git a/include/io.h b/include/io.h index 19f97583e7731984e0ebe2f06307063744baa8d5..2fb0fc526072c37ee488297109896710930189c0 100644 --- a/include/io.h +++ b/include/io.h @@ -1,36 +1,8 @@ -/* graph.h - * - * Header file for graph-related functions. - */ - #ifndef GRAPH_H - #define GRAPH_H - - #include "list.h" /* Ensure list_t is defined. */ - - /* If you plan to use this header in a C++ project, uncomment the extern "C" section below. */ - /* - #ifdef __cplusplus - extern "C" { - #endif - */ - - /** - * @brief Reads a graph from the file specified by filename. - * - * This function opens the file, reads job names and their relationships, - * and builds a graph represented as a list_t. - * - * @param filename The name of the file to read. - * @return Pointer to the constructed list_t (graph) or NULL on failure. - */ - list_t *read_graph(char *filename); - - /* - #ifdef __cplusplus - } - #endif - */ - - #endif /* GRAPH_H */ - \ No newline at end of file +#ifndef GRAPH_H +#define GRAPH_H + +#include "list.h" +list_t *read_graph(char *filename); + +#endif diff --git a/include/job.h b/include/job.h index 03ae150cb6dcfaee757b8f97e08bdc00a13cbbae..a3bbc2b114cb92c6687a2d6d9ceccee5f6dd5374 100644 --- a/include/job.h +++ b/include/job.h @@ -45,4 +45,4 @@ int titleJobCmp(job_t * J1, job_t * J2); int iDegreeJobCmp(job_t * J1, job_t * J2); int oDegreeJobCmp(job_t * J1, job_t * J2); int rangJobCmp(job_t * J1, job_t * J2); -int InverseRangJobCmp(job_t * J1, job_t * J2); + diff --git a/include/list_elm.h b/include/list_elm.h deleted file mode 100644 index 621dd3228dcc74a6159166ec3c348991527dc1b6..0000000000000000000000000000000000000000 --- a/include/list_elm.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -typedef struct list_elm { - void * data; - struct list_elm * suc, * pred; -} list_elm_t; - -list_elm_t * new_list_elm ( void * data ); -/** - * @brief delete the list element E and optionnaly its datum - * @param ptrf : a ptr to fct that deallocates datum's memory ; - * if ptrf is NULL, datum is not freed - */ -void del_list_elm( list_elm_t * * E, void (*ptrf)() ); - -list_elm_t * get_suc ( list_elm_t * E ); -list_elm_t * get_pred ( list_elm_t * E ); -void * get_data ( list_elm_t * E ); - -void set_suc ( list_elm_t * E, list_elm_t * S ); -void set_pred ( list_elm_t * E, list_elm_t * P ); -void set_data ( list_elm_t * E, void * data ); - -void view_list_elm ( list_elm_t * E, void (*ptrf)() ); diff --git a/obj/db.o b/obj/db.o deleted file mode 100644 index 02a8690f0be0218bc1f329379cdd0383219ac9fd..0000000000000000000000000000000000000000 Binary files a/obj/db.o and /dev/null differ diff --git a/obj/io.o b/obj/io.o deleted file mode 100644 index 10bee52ae486bc83610bea63e627baa252d403ca..0000000000000000000000000000000000000000 Binary files a/obj/io.o and /dev/null differ diff --git a/readme.md b/readme.md index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..967e4196d19d361dff327001e26f0636c839dadc 100644 --- a/readme.md +++ b/readme.md @@ -0,0 +1,90 @@ +# Tri rapide (`quick_sort`) dans notre projet + + +--- + +## 1. Principe général + +1. **Choix du pivot** + On prend simplement le premier élément de la liste comme pivot : + + ```c + elmlist_t * pivot = get_head(L); + ``` + +2. **Partition** + On parcourt tous les autres éléments de la liste et on les répartit en deux sous-listes : + + - **`val_inf_pivot`** : contient les éléments strictement inférieurs au pivot. + - **`val_sup_pivot`** : contient les éléments supérieurs ou égaux au pivot. + + Le code de partition est : + + ```C + static void partition(list_t *L, + elmlist_t *pivot, + list_t *val_inf, + list_t *val_sup, + int (*cmpFct)(void*, void*)) { + elmlist_t *cur = L->head; + while (cur != NULL) { + if (cmpFct(get_data(cur), get_data(pivot)) < 0) { + queue(val_inf, get_data(cur)); + } else { + queue(val_sup, get_data(cur)); + } + cur = get_suc(cur); + } + } + ``` + +3. **Nettoyage de la liste initiale** + Après la partition, la liste d'origine est vidée de ses nœuds (mais pas des données) : + + + clean(L); + + +4. **Tri récursif des sous-listes** + - Si `val_inf_pivot` n'est pas vide, on l'ordonne récursivement, puis on rattache le pivot à sa fin. + - Si `val_sup_pivot` n'est pas vide, on l'ordonne récursivement, puis on rattache son début au pivot. + +5. **Reconstruction de la liste triée** + On met à jour `L->head`, `L->tail` et `L->numelm` pour refléter la combinaison : + + ```C + // Extrait du quick_sort: + if (!is_empty(val_inf_pivot)) { + quick_sort(val_inf_pivot, cmpFct); + L->head = val_inf_pivot->head; + L->tail = val_inf_pivot->tail; + L->numelm = val_inf_pivot->numelm; + + // on rattache le pivot + set_pred(pivot, L->tail); + set_suc(L->tail, pivot); + L->tail = pivot; + L->numelm++; + } + + if (!is_empty(val_sup_pivot)) { + quick_sort(val_sup_pivot, cmpFct); + set_pred(val_sup_pivot->head, pivot); + set_suc(pivot, val_sup_pivot->head); + L->tail = val_sup_pivot->tail; + L->numelm += val_sup_pivot->numelm; + } + + +6. **Libération des ressources temporaires** + Les deux listes auxiliaires (`val_inf_pivot` et `val_sup_pivot`) sont libérées : + + ```C + free(val_inf_pivot); + free(val_sup_pivot); + + + + + + diff --git a/readme_temp.md b/readme_temp.md deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/src/db.c b/src/db.c deleted file mode 100644 index b26b108f88d3de9266f593a5df1baf651a47eb7d..0000000000000000000000000000000000000000 --- a/src/db.c +++ /dev/null @@ -1,74 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <assert.h> -#include "db.h" -#include "list.h" -#include "list_elm.h" - -list_t * read_list( file_mode_t mode, void * (*read_fct) (), void (*del_fct) () ) { - FILE * fd; - char fname[20]; - list_t * L = new_list(); - - if (mode == TEXT) {// Open file in TEXT mode - printf( "\t\tRead list from text file (.txt)\n\tfile name :" ); - scanf( "%s", fname ); - fd = fopen( fname, "rt" ); - } - else {// open file in BIN mode - printf( "\t\tRead list from binary file (.bin)\n\tfile name :" ); - scanf( "%s", fname ); - fd = fopen( fname, "rb" ); - } - //todo - void * datum; - while ((datum = read_fct(fd, mode)) != NULL) { - queue(L, datum); - } - - - list_elm_t * E = get_tail(L); - if (E != NULL && empty_list(E->data)) { - list_elm_t * T = get_pred(E); - if (T != NULL) { - set_suc(T, NULL); - L->tail = T; - } else { - L->head = L->tail = NULL; - } - del_list_elm(&E, del_fct); - } - - /** TODO parcourir le fichier pour y collecter les formulaires et les ranger dans la L - ATTENTION : - il est **possible** que vous créiez un élément de trop (un formulaire vide) en fin de liste. - Il faut alors penser à le supprimer grâce au code suivant : - E = get_tail (L); - struct elmlist * T = getPred(E); - set_suc(T, NULL); - L->tail = T; - del_elmlist(E, ptr_del); - */ - - - fclose(fd); - return L; - } -void write_list( list_t * L, file_mode_t mode, void (*write_fct) () ) { - FILE * fd; - char fname[20]; - if (mode == TEXT) { - printf( "\t\tWrite list to text file (.txt)\n\tfile name :"), scanf( "%s", fname ); - fd = fopen( fname, "wt" ); - } else { - printf("\t\tWrite list to binary file (.bin)\n\tfile name :"), scanf( "%s", fname ); - fd = fopen(fname, "wb" ); - } - - for (list_elm_t * elm = get_head(L); elm != NULL; elm = elm->suc){ - write_fct(elm->data, mode, fd); - } - /// @todo Parcourir L et écrire les formulaires grâce à data_write_fct - fclose(fd); -} - diff --git a/src/io.c b/src/io.c index ba096f4ae54b74e2d749ca35fca6a5330510b8f2..42b21e26ee1d74b37f17e82e5dc73c0c17b554d7 100644 --- a/src/io.c +++ b/src/io.c @@ -17,9 +17,7 @@ list_t * read_graph( char * filename ) { while ( !feof( fd ) ) { fscanf( fd, " %s", job_name ); - if ( !strcmp( job_name, "NIL" ) ) - continue; - printf("DEBUG: job_name lire = %s\n", job_name); + if ( !strcmp( job_name, "NIL" ) ); job_t * J = new_job( job_name ); @@ -37,9 +35,6 @@ list_t * read_graph( char * filename ) { //NOUVEAU if( !is_in_list( G, J, (int (*)(void*, void*)) titleJobCmp ) ) { queue( G, J ); - printf("DEBUG: Inserer %s vers G\n", job_name); - } else { - printf("DEBUG: Job %s déja existé dans G\n", job_name); } //NOUVEAU fscanf( fd, " %lf", &(J->life) ); @@ -49,7 +44,7 @@ list_t * read_graph( char * filename ) { */ job_t * predJ; fscanf( fd, " %s", job_name ); - printf("DEBUG: job_name lire = %s\n", job_name); + while ( strcmp( job_name, "NIL" ) ) { predJ = new_job( job_name ); @@ -58,9 +53,6 @@ list_t * read_graph( char * filename ) { // NOUVEAU if( !is_in_list( G, predJ, (int (*)(void*, void*)) titleJobCmp ) ) { queue( G, predJ ); - printf("DEBUG: Inserer pred %s vers G\n", job_name); - } else { - printf("DEBUG: Pred %s déja existé dans G\n", job_name); } //NOUVEAU ordered_insert( predJ->posteriority, J, &titleJobCmp ); @@ -70,7 +62,6 @@ list_t * read_graph( char * filename ) { incr_job_iDegree( J ); fscanf( fd, " %s", job_name ); - printf("DEBUG: job_name lire = %s\n", job_name); } /** @note valeurs par défaut des autres champs */ diff --git a/src/job.c b/src/job.c index 31e99075dd66410653fcbdfff8d1ba4471b857a5..9fd5ecbfd8afba30a6456c195b093686c7d511bf 100644 --- a/src/job.c +++ b/src/job.c @@ -20,14 +20,17 @@ job_t * new_empty_job ( ) { J->critique = false; return J; } + job_t * new_job ( char * title ) { job_t * J = new_empty_job ( ); J->title = strdup ( title ); return J; } + void free_job(job_t ** ptrJ ) { assert ( ptrJ && *ptrJ ); - if( (*ptrJ)->title ) free ( (*ptrJ)->title ); + if( (*ptrJ)->title ) + free ( (*ptrJ)->title ); free ( *ptrJ ); *ptrJ = NULL; } @@ -54,8 +57,11 @@ void view_job ( job_t * J ) { if(J->au_plus_tard == UNDEF ) printf("U"); else printf ( "%2.2lf",J->au_plus_tard ); printf ( "\ttotale= " ); if ( J->marge_totale == UNDEF ) printf("U"); else printf ( "%2.2lf", J->marge_totale ); + printf ( "\tfree= " );//AJOUTéE FREE SLACK + if ( J->marge_libre == UNDEF ) printf("U"); else printf ( " %2.2lf", J->marge_libre ); printf ( "\tcritical= " ); if ( J->critique ) printf("Y\n"); else printf ( "N\n" ); + } char * get_job_title(job_t * J) { @@ -111,11 +117,6 @@ void decr_job_iDegree(job_t * J) { J->input_degree--; } -int InverseRangJobCmp(job_t * J1, job_t * J2) { - assert(J1 && J2); - return J2->rank - J1->rank; -} - int get_job_oDegree(job_t * J) { assert(J); return J->output_degree; diff --git a/src/job_2.c b/src/job_2.c deleted file mode 100644 index 76c8897c629fe8bdff813c648b4eab6e91f69d3c..0000000000000000000000000000000000000000 --- a/src/job_2.c +++ /dev/null @@ -1,111 +0,0 @@ -#include "job.h" -#include "list.h" -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <assert.h> - -job_t * new_empty_job(){ - job_t * J = calloc ( 1, sizeof (job_t ) ); - assert( J ); - J->precedence = new_list ( ); - J->posteriority = new_list ( ); - J->rank = UNDEF; - J->au_plus_tard = UNDEF; - J->au_plus_tot = UNDEF; - J->marge_totale = UNDEF; - J->critique = false; - return J; -} - -job_t * new_job(char * title){ - job_t * J = new_empty_job ( ); - J->title = strdup ( title ); - return J; -} - -void free_job(job_t ** ptrJ){ - assert ( ptrJ && *ptrJ ); - if( (*ptrJ)->title ) free ( (*ptrJ)->title ); - free ( *ptrJ ); - *ptrJ = NULL; -} - -void view_job ( job_t * J ) { - printf ( "JOB %s\n\tpreceeded by [", get_job_tilte ( J ) ); - for(elmlist_t * E = get_head ( J->precedence ); E; E = get_suc ( E ) ) { - printf ( " %s", get_job_tilte ( get_data ( E ) ) ); - } - printf ( " ]\n" ); - // if ( !get_numelm ( J->posteriority ) ) printf ( "\t" ); - printf ( "\tfollowed by [" ); - for(elmlist_t * E = get_head(J->posteriority); E; E = get_suc(E)){ - printf(" %s", get_job_tilte(get_data(E))); - } - printf ( " ]\n" ); - printf ( "\tiDeg=%d\toDeg=%d\tlife=%2.2lf", J->input_degree, J->output_degree, J->life ); - printf ( "\trank=" ); - if ( J->rank == UNDEF ) printf ( "U" ); else printf ( "%d", J->rank ); - printf ( "\tearly=" ); - if(J->au_plus_tot == UNDEF ) printf("U"); else printf ( "%2.2lf",J->au_plus_tot ); - printf ( "\tlate=" ); - if(J->au_plus_tard == UNDEF ) printf("U"); else printf ( "%2.2lf",J->au_plus_tard ); - printf ( "\ttotale= " ); - if ( J->marge_totale == UNDEF ) printf("U"); else printf ( "%2.2lf", J->marge_totale ); - printf ( "\tcritical= " ); - if ( J->critique ) printf("Y\n"); else printf ( "N\n" ); -} - -char * get_job_title(job_t * J) { - assert(J); - return J->title; -} - -void titleJobCmp(job_t * J, char * title){ - - - -} - -void set_job_title(job_t * J, char * title) { - assert(J && title); - if(J->title) - free(J->title); - J->title = strdup(title); -} - - -double get_job_life(job_t * J) { - assert(J); - return J->life; -} - - -void set_job_life(job_t * J, double life) { - assert(J); - J->life = life; -} - - -int get_job_iDegree(job_t * J) { - assert(J); - return J->input_degree; -} - - -void set_job_iDegree(job_t * J, int iDegree) { - assert(J); - J->input_degree = iDegree; -} - - -void incr_job_iDegree(job_t * J) { - assert(J); - J->input_degree++; -} - - -void decr_job_iDegree(job_t * J) { - assert(J); - J->input_degree--; -} \ No newline at end of file diff --git a/src/job_3.c b/src/job_3.c deleted file mode 100644 index 6ac6944036af9438a4d02686609d6536ca115c44..0000000000000000000000000000000000000000 --- a/src/job_3.c +++ /dev/null @@ -1,55 +0,0 @@ -#include "job.h" -#include <assert.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -//TOUS EST CHANGee -int get_job_oDegree(job_t * J) { - assert(J); - return J->output_degree; -} - -void set_job_oDegree(job_t * J, int oDegree) { - assert(J); - J->output_degree = oDegree; -} - -void incr_job_oDegree(job_t * J) { - assert(J); - J->output_degree++; -} - -void decr_job_oDegree(job_t * J) { - assert(J); - J->output_degree--; -} - -int get_job_rank(job_t * J) { - assert(J); - return J->rank; -} - -void set_rank(job_t * J, int rank) { - assert(J); - J->rank = rank; -} - -int titleJobCmp(job_t * J1, job_t * J2) { - assert(J1 && J2); - return strcmp(J1->title, J2->title); -} - -int iDegreeJobCmp(job_t * J1, job_t * J2) { - assert(J1 && J2); - return J1->input_degree - J2->input_degree; -} - -int oDegreeJobCmp(job_t * J1, job_t * J2) { - assert(J1 && J2); - return J1->output_degree - J2->output_degree; -} - -int rangJobCmp(job_t * J1, job_t * J2) { - assert(J1 && J2); - return J1->rank - J2->rank; -} diff --git a/src/list.c b/src/list.c index 640f44287665d4c5db362fcb5511f7db55b595dd..d54242a74a89d146560eb4a9cd8afa1e496b3a37 100644 --- a/src/list.c +++ b/src/list.c @@ -31,7 +31,7 @@ void del_list(list_t ** ptrL, void (*ptrf)(void *)) { assert(ptrL && *ptrL); list_t * list = *ptrL; elmlist_t * E = list->head; - while (E) { + while (E != NULL) { elmlist_t * temp = E; E = get_suc(temp); if (ptrf) { @@ -112,7 +112,9 @@ void queue(list_t * L, void * data) { } void insert_after(list_t * L, void * data, elmlist_t * elm) { - if (elm == NULL) return; + if (elm == NULL) + printf("VALEUR NULL"); + return; elmlist_t * E = new_list_elm(data); set_suc(E, get_suc(elm)); set_pred(E, elm); @@ -145,9 +147,9 @@ void take_out(list_t * L, void * D) { if (get_data(current) == D) { elmlist_t * p = get_pred(current); elmlist_t * s = get_suc(current); - if (p) set_suc(p, s); + if (p!= NULL) set_suc(p, s); else L->head = s; - if (s) set_pred(s, p); + if (s!= NULL) set_pred(s, p); else L->tail = p; free(current); L->numelm--; @@ -214,13 +216,10 @@ void quick_sort(list_t * L, int (*cmpFct)(void*, void*)) { void find(list_t * L, void ** ptrKey, int (*cmpFct)(void*, void*), void (*delFct)(void*)) { assert(L && ptrKey && cmpFct); - printf("DEBUG (find): trouvant pointer %p\n", *ptrKey); elmlist_t * curr = L->head; - while (curr) { + while (curr != NULL) { if (cmpFct(get_data(curr), *ptrKey) == 0) { - printf("DEBUG (find): double trouvée. Element data vers %p\n", get_data(curr)); if (delFct) { - printf("DEBUG (find): Freeing pointer double %p\n", *ptrKey); delFct(ptrKey); } *ptrKey = get_data(curr); @@ -228,34 +227,35 @@ void find(list_t * L, void ** ptrKey, int (*cmpFct)(void*, void*), void (*delFct } curr = get_suc(curr); } - printf("DEBUG (find): pas de double pour le pointer %p\n", *ptrKey); } -//PENSER A CHANGER VERS ASSERT elmlist_t * get_suc(elmlist_t * E) { - if (E == NULL) return NULL; + assert(E); return E->suc; } elmlist_t * get_pred(elmlist_t * E) { - if (E == NULL) return NULL; + assert(E); return E->pred; } void * get_data(elmlist_t * E) { - if (E == NULL) return NULL; + assert(E); return E->data; } void set_suc(elmlist_t * E, elmlist_t * suc) { - if (E != NULL) E->suc = suc; + assert(E); + E->suc = suc; } void set_pred(elmlist_t * E, elmlist_t * pred) { - if (E != NULL) E->pred = pred; + assert(E); + E->pred = pred; } void set_data(elmlist_t * E, void * data) { - if (E != NULL) E->data = data; + assert(E); + E->data = data; } bool is_in_list(list_t *L, void *key, int (*cmpFct)(void*, void*)) { diff --git a/src/list_1 (1).c b/src/list_1 (1).c deleted file mode 100644 index ef9df30293f795e48da03e19b70ddab29d65bed9..0000000000000000000000000000000000000000 --- a/src/list_1 (1).c +++ /dev/null @@ -1,74 +0,0 @@ -#include "list_1 (1).h" -#include "list" -#include <stdlib.h> -#include <stdbool.h> -#include <stdio.h> -#include <assert.h> - -typedef struct{ - elmlist_t * head; - elmlist_t * tail; - int numelm; - } list_t ; - // Create an empty list - list_t * new_list(){ - list_t * t = calloc(1, sizeof(list_t)); - assert(t); - return t; - } - // Delete list, its elements and possibly the data - //DOIT CONFIRMER LE STRUCT - void del_list(list_t ** ptrL, void (*ptrf) ()){ - assert(ptrL && *ptrL); - list_t * L = *ptrL; - if(ptrf){ - for(elmlist_t * E = L->head; E; ){ - elmlist_t * T = E; - E = E->suc; - (*ptrf)(T->data); - free(T); - } - } - } else { - for(elmlist_t * E = L->head; E ; ){ - elmlist_t * T = E; - E = E->suc; - free(T); - } - free(*ptrL); - (*ptrL) = NULL; -} - // Clean list; delete its elments but keep data and the list - void clean(list_t * L){ - assert(L); - elmlist_t *curr = L->head; - while (curr != NULL) { - elmlist_t *temp = curr; - curr = curr->suc; - free(temp); - } - L->head = NULL; - L->tail = NULL; - L->numelm = 0; -} - // Is list L empty ? - bool is_empty(list_t * L){ - assert(L); - if (L->numelm == 0) return true; - return false; - } - - elmlist_t * get_head(list_t * L){ - assert(L); - L = L->head; - return L; - } - - elmlist_t * get_tail(list_t * L){ - assert(L); - L = L->tail; - return L; - } - - - \ No newline at end of file diff --git a/src/list_2.c b/src/list_2.c deleted file mode 100644 index ed867d3c8d7217ea6321afb1404c48dbfb069be8..0000000000000000000000000000000000000000 --- a/src/list_2.c +++ /dev/null @@ -1,226 +0,0 @@ -#include "list_1 (1).h" -#include "list.h" -#include <stdlib.h> -#include <stdio.h> -#include <assert.h> - -// Gimme the number of elements of L -int get_numelm(struct list_t * L){ - assert(L); - return L->numelm; -} -// Take out the data D of the list L if it is present -void take_out(struct list_t * L, void * D){ - assert(L); - elmlist_t * current = L->head; - while (current != NULL) { - if (get_data(current) == D) { - elmlist_t * p = get_pred(current); - elmlist_t * s = get_suc(current); - // Update predecessor’s successor - if (p) set_suc(p, s); - else L->head = s; // current was head - // Update successor’s predecessor - if (s) set_pred(s, p); - else L->tail = p; // current was tail - free(current); - L->numelm--; - return; - } - current = get_suc(current); - } -} - -// Add a element holding data to the head of L -void cons(struct list_t * L, void * data){ - elmlist_t * E = calloc(1, sizeof(elmlist_t)); - assert(L && E); - set_data(E, data); - set_suc(E, L->head); - set_head(L, E); - if(is_empty(L)) L->tail = E; - L->numelm += 1; - } - - - - -// Add a element holding data to the tail of L -void queue(struct list_t * L, void * data){ - assert(L); - elmlist_t * E = calloc(1, sizeof(elmlist_t)); - assert(E); - set_data(E, data); - E->suc = NULL; - if (is_empty(L)) { - E->pred = NULL; - L->head = E; - L->tail = E; - } else { - E->pred = L->tail; - L->tail->suc = E; - L->tail = E; - } - L->numelm++; - } -// Insert in L a element holding data wrt order given by cmp_ptrf -void ordered_insert(struct list_t * L, void * data, int (*cmp_ptrf)()){ - assert(L && cmp_ptrf); - elmlist_t * E = calloc(1, sizeof(elmlist_t)); - assert(E); - set_data(E, data); - // if list is empty, simply add the element - if (is_empty(L)) { - E->pred = E->suc = NULL; - L->head = L->tail = E; - L->numelm++; - return; - } -} - -// Elements qui sont moins = val_inf et le reste val_sup. -static void partition(list_t * L, elmlist_t * pivot, list_t * val_inf, list_t * val_sup, int (*cmpFct)(void*, void*)) { - for (elmlist_t * cur = L->head; cur != NULL; cur = cur->suc) { - if (cmpFct(get_data(cur), get_data(pivot)) < 0) - queue(val_inf, get_data(cur)); - else - queue(val_sup, get_data(cur)); - } -} - -void quick_sort(list_t * L, int (*cmpFct)(void*, void*)) { - assert(L && cmpFct); - - if (L->numelm > 1) { - - elmlist_t * pivot = get_head(L); - L->head = get_suc(pivot); - pivot->pred = NULL; - pivot->suc = NULL; - - - /** @note - * La listes des données inférieures à pivot - * La listes des données supérieures à pivot - */ - list_t * val_inf_pivot = new_list(); - list_t * val_sup_pivot = new_list(); - - /** @note Déplacement des données de L dans val_inf_pivot et val_sup_pivot */ - partition(L,pivot,val_inf_pivot,val_sup_pivot,cmpFct); - - /** @note On supprimer les éléments de L sans supprimer ni L ni les jobs */ - // elmlist_t * S; - // for(elmlist_t * E = L->head; E; E = S){ - // S = E->suc; - // free(E); - // } - - /** @note - * Si la partie inf est vide alors L commence par le pivot - * Sinon on tri grâce à cmpFct la partie inf puis on ajoute en queue le pivot - */ - - - if (is_empty(val_inf_pivot)) { - L->head = pivot; - L->tail = pivot; - L->numelm = 1; - } else { - quick_sort(val_inf_pivot, cmpFct); - L->head = val_inf_pivot->head; - L->tail = val_inf_pivot->tail; - L->numelm = val_inf_pivot->numelm; - pivot->pred = L->tail; - L->tail->suc = pivot; - L->tail = pivot; - L->numelm += 1; - } - /** @note - * Si la partie sup n'est pas vide alors - * On la trie puis on la concatène à la partie inf - */ - if (!is_empty(val_sup_pivot)) { - quick_sort(val_sup_pivot, cmpFct); - val_sup_pivot->head->pred = pivot; - pivot->suc = val_sup_pivot->head; - L->tail = val_sup_pivot->tail; - L->numelm += val_sup_pivot->numelm; - } - free(val_inf_pivot); - free(val_sup_pivot); - } -} - -// void quick_sort(list_t * L, int (*cmpFct)()){ - -// if (L == NULL || L->numelm < 2) -// return; - - -// elmlist_t * pivotNode = L->head; -// void * pivotData = pivotNode->data; - - -// list_t * less = new_list(); -// list_t * greater = new_list(); - - -// for (elmlist_t * cur = L->head; cur != NULL; cur = cur->suc) { - -// if (cur == pivotNode) -// continue; - -// if (cmpFct(cur->data, pivotData) < 0) -// queue(less, cur->data); -// else -// queue(greater, cur->data); -// } - - -// clean(L); - - -// quick_sort(less, cmpFct); -// quick_sort(greater, cmpFct); - -// for (elmlist_t * node = less->head; node != NULL; node = node->suc) -// queue(L, node->data); - - -// queue(L, pivotData); - -// for (elmlist_t * node = greater->head; node != NULL; node = node->suc) -// queue(L, node->data); - -// free(less); -// free(greater); -// } - - - - - -void view_list(list_t * L, void (*ptrf)()) { - assert(L && ptrf); - elmlist_t * curr = L->head; - while (curr) { - ptrf(get_data(curr)); - curr = curr->suc; - } - -} -// Return un ptr vers element else NULL -void find(list_t * L, void ** ptrKey, int (*cmpFct)(), void (*delFct)()) { - assert(L && ptrKey && cmpFct); - elmlist_t * curr = L->head; - while (curr) { - if (cmpFct(get_data(curr), *ptrKey) == 0) { - if (delFct) - delFct(ptrKey); - *ptrKey = get_data(curr); - return; - } - curr = curr->suc; - } -} diff --git a/src/list_elm.c b/src/list_elm.c deleted file mode 100644 index aa173dfff979ad64483a740e38fcb96bc7977d6b..0000000000000000000000000000000000000000 --- a/src/list_elm.c +++ /dev/null @@ -1,52 +0,0 @@ -#include <stdlib.h> -#include <assert.h> -#include "list_elm.h" - -list_elm_t * new_list_elm ( void * data ){ - list_elm_t * E = calloc(1,sizeof(list_elm_t)); - assert(E); - E->data = data; - return E; -} - -void del_list_elm( list_elm_t * * E, void (*ptrf)() ){ - assert(E && *E); - if (ptrf) { - ptrf((*E)->data); - } - free(*E); - *E = NULL; -} - -list_elm_t * get_suc ( list_elm_t * E ){ - assert(E); - return E->suc; -} -list_elm_t * get_pred ( list_elm_t * E ); -void * get_data ( list_elm_t * E ){ - assert(E); - return E->data; -} - -void set_suc ( list_elm_t * E, list_elm_t * S ){ - assert(E); - E->suc = S; -} - -void set_pred ( list_elm_t * E, list_elm_t * P ){ - assert(E); - E->pred = P; -} - -void set_data ( list_elm_t * E, void * data ){ - assert(E); - E->data = data; -} - -void view_list_elm ( list_elm_t * E, void (*ptrf)() ){ - assert(E && ptrf); - for(elmlist_t * courant = E->head; courant; courant = get_suc(E)){ - void * data = E->data; - (*ptrf)(data); - } -} \ No newline at end of file diff --git a/src/main (1).c b/src/main (1).c deleted file mode 100644 index 5bb714ba220f0f322ccdfd5505a945425a638a11..0000000000000000000000000000000000000000 --- a/src/main (1).c +++ /dev/null @@ -1,32 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> - -#include "job.h" -#include "list.h" -#include "list_elm.h" - - -int main(int argc, char ** argv){ - if(argc < 2) exit(-1); - - list_t * G = read_graph(argv[1]); - printf("Liste des tâches lue\n"); - view_list(G, &view_job); - - printf("Liste des tâches triée par degré d'entrée croissant\n"); - quick_sort(G, &iDegreeJobCmp); - view_list(G,&view_job); - - printf("Liste des tâches triée par rang croissant\n"); - ranking(G); - view_list(G,&view_job); - - printf("Prune edges\n"); - prune(G); - view_list(G,&view_job); - - printf("\nMarges totales des tâches\n"); - marges(G); - view_list(G,&view_job); - return 0; -} diff --git a/src/rank.c b/src/rank.c index 48ba4813f289a37cd03fdf4ec0539a00641476ba..0d9885a769c88fe2a5c965dacaf1e3d4238ba2f7 100644 --- a/src/rank.c +++ b/src/rank.c @@ -8,30 +8,32 @@ #include <assert.h> #include <stdbool.h> + + // Calcul des rangs et tri de la liste par rang. void ranking(list_t *G) { assert(G); list_t *tachequeue = new_list(); int rank = 0; // Enfile toutes les tâches sans prédécesseurs (input_degree = 0) - for (elmlist_t *E = get_head(G); E; E = get_suc(E)) { - job_t *J = (job_t *)get_data(E); + for (elmlist_t *E = get_head(G); E != NULL; E = get_suc(E)) { + job_t *J = get_data(E); J->dyn_input_degree = J->input_degree; if (J->input_degree == 0) { queue(tachequeue, J); } } - // Traiter les tâches à l'aide du tri topologique + // Traitement topologique par niveaux while (!is_empty(tachequeue)) { list_t *next_level = new_list(); - for (elmlist_t *E = get_head(tachequeue); E; E = get_suc(E)) { - job_t *J = (job_t *)get_data(E); + for (elmlist_t *E = get_head(tachequeue); E != NULL; E = get_suc(E)) { + job_t *J = get_data(E); set_rank(J, rank); - // Mettre à jour les successeurs + // Mise à jour des successeurs for (elmlist_t *S = get_head(J->posteriority); S; S = get_suc(S)) { - job_t *succ = (job_t *)get_data(S); + job_t *succ = get_data(S); succ->dyn_input_degree--; if (succ->dyn_input_degree == 0) { queue(next_level, succ); @@ -43,31 +45,114 @@ void ranking(list_t *G) { rank++; } del_list(&tachequeue, NULL); + + // Trier la liste par rang croissant pour la visualisation + quick_sort(G, (int (*)(void*,void*))rangJobCmp); } + + //suppressions des arcs redondants. + void prune(list_t *G) { assert(G); - for (elmlist_t *E = get_head(G); E; E = get_suc(E)) { - job_t *J = (job_t *)get_data(E); - elmlist_t *S = get_head(J->posteriority); - while (S) { - job_t *succ = (job_t *)get_data(S); - elmlist_t *next_S = get_suc(S); - - // Vérifier les arcs transitifs - for (elmlist_t *T = get_head(succ->posteriority); T; T = get_suc(T)) { - job_t *trans = (job_t *)get_data(T); - if (is_in_list(J->posteriority, trans, (int (*)(void*, void*))titleJobCmp)) { - printf("arc inutile effacée: %s -> %s\n", J->title, succ->title); - take_out(J->posteriority, succ); + // Pour chaque tâche J du graphe + for (elmlist_t *E = get_head(G); E != NULL; E = get_suc(E)) { + job_t *J = get_data(E); + // Pour chaque successeur direct succ1 + for (elmlist_t *s1 = get_head(J->posteriority); s1 != NULL; s1 = get_suc(s1)) { + job_t *succ1 = get_data(s1); + // Pour chaque successeur de succ1 + for (elmlist_t *t2 = get_head(succ1->posteriority); t2 != NULL; t2 = get_suc(t2)) { + job_t *trans = get_data(t2); + // Si trans est aussi un successeur direct de J, supprimer l'arc J->trans + if (trans != succ1 && + is_in_list(J->posteriority, trans, (int (*)(void*,void*))titleJobCmp)) { + printf("arc inutile effacée: %s -> %s\n", J->title, trans->title); + take_out(J->posteriority, trans); decr_job_oDegree(J); - take_out(succ->precedence, J); - decr_job_iDegree(succ); - break; + take_out(trans->precedence, J); + decr_job_iDegree(trans); } } - S = next_S; } } } +//Calcul des dates au plus tôt, au plus tard, marges totales et libres, et chemin critique. + +void marges(list_t *G) { + assert(G); + + // 1) Forward‑pass : initialisation + for (elmlist_t *E = get_head(G); E != NULL; E = get_suc(E)) { + job_t *J = get_data(E); + if (J->input_degree == 0) { + J->au_plus_tot = 0.0; + } else { + J->au_plus_tot = UNDEF; + } + } + // Propagation des dates au plus tôt en ordre topologique (liste déjà triée par rang) + for (elmlist_t *E = get_head(G); E != NULL; E = get_suc(E)) { + job_t *J = get_data(E); + for (elmlist_t *P = get_head(J->precedence); P != NULL; P = get_suc(P)) { + job_t *pred = get_data(P); + double candidate = pred->au_plus_tot + pred->life; + if (candidate > J->au_plus_tot) { + J->au_plus_tot = candidate; + } + } + } + + // 2) Détermination du temps de fin du projet + double end_time = 0.0; + for (elmlist_t *E = get_head(G); E != NULL; E = get_suc(E)) { + job_t *J = get_data(E); + double finish = J->au_plus_tot + J->life; + if (finish > end_time) end_time = finish; + } + + // 3) Initialisation des temps au plus tard + for (elmlist_t *E = get_head(G); E != NULL; E = get_suc(E)) { + job_t *J = get_data(E); + if (J->output_degree == 0) { + J->au_plus_tard = end_time; + } else { + J->au_plus_tard = UNDEF; + } + } + + // 4) Backward‑pass en ordre inverse + for (elmlist_t *E = get_tail(G); E != NULL; E = get_pred(E)) { + job_t *J = get_data(E); + for (elmlist_t *S = get_head(J->posteriority); S != NULL; S = get_suc(S)) { + job_t *succ = get_data(S); + double candidate = succ->au_plus_tard - succ->life; + if (J->au_plus_tard == UNDEF || candidate < J->au_plus_tard) { + J->au_plus_tard = candidate; + } + } + } + + // 5) Calcul des marges et identification du chemin critique + for (elmlist_t *E = get_head(G); E != NULL; E = get_suc(E)) { + job_t *J = get_data(E); + double latest_start = J->au_plus_tard - J->life; + J->marge_totale = latest_start - J->au_plus_tot; + + // marge libre + if (get_head(J->posteriority) == NULL) { + J->marge_libre = J->marge_totale; + } else { + double minSuccES = __DBL_MAX__; + for (elmlist_t *S = get_head(J->posteriority); S != NULL; S = get_suc(S)) { + job_t *succ = get_data(S); + if (succ->au_plus_tot < minSuccES) minSuccES = succ->au_plus_tot; + } + J->marge_libre = minSuccES - (J->au_plus_tot + J->life); + } + + // critique si marge totale nulle + J->critique = (J->marge_totale == 0.0); + } +}