diff --git a/CMakeLists.txt b/CMakeLists.txt index d4917e8..5a918db 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,7 +10,9 @@ add_executable(Mini_Database student.c student.h undo_stack.c - undo_stack.h) + undo_stack.h + arbres_binaire.c + arbres_binaire.h) # Executable pour les tests add_executable(Test_Student @@ -18,7 +20,9 @@ add_executable(Test_Student student.c student.h undo_stack.c - undo_stack.h) + undo_stack.h + arbres_binaire.c + arbres_binaire.h) # Activer CTest enable_testing() diff --git a/arbres_binaire.c b/arbres_binaire.c new file mode 100644 index 0000000..8ac91aa --- /dev/null +++ b/arbres_binaire.c @@ -0,0 +1,57 @@ +#include +#include +#include +#include "arbres_binaire.h" + +ab_node_student *create_ab_node(student *student) { + if (student == NULL) return NULL; + + ab_node_student *node = (ab_node_student *) malloc(sizeof(ab_node_student)); + if (node == NULL) { + printf("Erreur d'allocation memoire!\n"); + return NULL; + } + + node->std = student; + + node->filsd = NULL; + node->filsg = NULL; + + return node; +} + +ab_racine_student *create_ab_racine() { + ab_racine_student *racine = (ab_racine_student *) malloc(sizeof(ab_racine_student)); + if (racine == NULL) { + printf("Erreur d'allocation memoire!\n"); + return NULL; + } + racine->racine = NULL; + return racine; +} + +ab_node_student *insert_recursive_worker(ab_node_student *currant, ab_node_student *new_node) { + if (currant == NULL) return new_node; + + if (new_node->std->moyenne < currant->std->moyenne) { + currant->filsg = insert_recursive_worker(currant->filsg, new_node); + } else { + currant->filsd = insert_recursive_worker(currant->filsd, new_node); + } + return currant; +} + +void insert_bst(ab_racine_student *racine, ab_node_student *node) { + if (racine == NULL || node == NULL) return; + + racine->racine = insert_recursive_worker(racine->racine, node); +} + +void free_bst_nodes(ab_node_student *node) { + if (node == NULL) return; + + free_bst_nodes(node->filsg); + free_bst_nodes(node->filsd); + + free(node); +} diff --git a/arbres_binaire.h b/arbres_binaire.h new file mode 100644 index 0000000..48f73e4 --- /dev/null +++ b/arbres_binaire.h @@ -0,0 +1,25 @@ +#ifndef MINI_DATABASE_ARBRES_BINAIRE_H +#define MINI_DATABASE_ARBRES_BINAIRE_H +#include "undo_stack.h" + +// structure de node d'arbre +typedef struct ab_node_student { + student *std; + struct ab_node_student *filsg; + struct ab_node_student *filsd; +} ab_node_student; + +// structure de racine d'arbre +typedef struct ab_racine_student { + ab_node_student *racine; +} ab_racine_student; + +ab_node_student *create_ab_node(student *student); +void insert_bst(ab_racine_student *racine, ab_node_student *node); + +ab_racine_student *create_ab_racine(); + +void afficher_arbres_trie(ab_racine_student *racine); + +void free_bst_nodes(ab_node_student *node); +#endif //MINI_DATABASE_ARBRES_BINAIRE_H diff --git a/main.c b/main.c index d49bedb..8b8b249 100644 --- a/main.c +++ b/main.c @@ -1,5 +1,7 @@ #include #include +#include +#include "arbres_binaire.h" #include "undo_stack.h" // #include // pour les Accents /** @@ -15,11 +17,9 @@ int main() { list_student *my_db = creat_list_student(); UndoStack *my_stack = create_undo_stack(); load_database(my_db, "my_data.db"); - int choice = 0; char cne_buffer[15]; - do { printf("\n=== MINI DATABASE MENU ===\n"); printf("1. Ajouter un etudiant\n"); @@ -87,11 +87,28 @@ int main() { search_student_by_cne(my_db, cne_buffer); break; case 6: - sort_students_by_grade(my_db); + // sort_students_by_grade(my_db); + if (my_db->tete == NULL) { + printf("La Base de donnee est vide, rien a trier.\n"); + break; + } + + ab_racine_student *temp_tree = create_ab_racine(); + // temp_tree->racine = NULL; + + student *current_s = my_db->tete; + while (current_s != NULL) { + ab_node_student *new_node = create_ab_node(current_s); + insert_bst(temp_tree, new_node); + current_s = current_s->next; + } + + afficher_arbres_trie(temp_tree); + free_bst_nodes(temp_tree->racine); break; case 7: printf("\nATTENTION: Cette action supprimera tous les etudiants!\n"); - printf("NB : les etudiants apres la suppression n'ajoute pas dans Historique!!!"); + printf("NB : les etudiants apres la suppression n'ajoute pas dans Historique!!!\n"); printf("Etes-vous sur? (1=Oui, 0=Non): "); int confirm; scanf("%d", &confirm); diff --git a/myApp b/myApp index 32563dc..2faafb9 100755 Binary files a/myApp and b/myApp differ diff --git a/student.c b/student.c index c00e4eb..746d3ef 100644 --- a/student.c +++ b/student.c @@ -2,6 +2,7 @@ #include #include +#include "arbres_binaire.h" #include "undo_stack.h" /** * @brief Crée et initialise une liste d'étudiants vide. @@ -90,6 +91,33 @@ void display_all_student(list_student *list_student) { } } +void display_student(list_student *list_student, char *cne) { + if (list_student == NULL || list_student->tete == NULL) { + printf("la Base de donnee et vide!!!\n"); + } + int trouver = 0; + student *courent = list_student->tete; + while (courent != NULL && strcmp(courent->CNE, cne) != 0) { + trouver = 1; + printf("\n"); + printf("+--------------------------------------------+\n"); + printf("| INFORMATION ETUDIANT |\n"); // J'ai ajouté %-2d pour l'alignement + printf("+--------------------------------------------+\n"); + printf("| CNE : %-25.25s |\n", courent->CNE); + printf("| Nom : %-25.25s |\n", courent->nom); + printf("| Prenom : %-25.25s |\n", courent->prenom); + printf("| Date Naissance : %02d/%02d/%-19d |\n", courent->date_naissance.jour, + courent->date_naissance.mois, courent->date_naissance.annee); + printf("| Filiere : %-25.25s |\n", courent->filiere); + printf("| Moyenne : %-25.2f |\n", courent->moyenne); + printf("+--------------------------------------------+\n"); + courent = courent->next; + } + if (trouver == 0) { + printf("etudiant n'est pas trouver!!!\n"); + } +} + /** * @brief Supprime un étudiant de la liste en utilisant son CNE. * @@ -523,3 +551,35 @@ void sort_students_by_grade(list_student *list) { printf("Liste triee par moyenne avec succes.\n"); } + +static void display_student_arbre(student *student) { + printf("+--------------------------------------------+\n"); + printf("| INFORMATION ETUDIANT |\n"); // J'ai ajouté %-2d pour l'alignement + printf("+--------------------------------------------+\n"); + printf("| CNE : %-25.25s |\n", student->CNE); + printf("| Nom : %-25.25s |\n", student->nom); + printf("| Prenom : %-25.25s |\n", student->prenom); + printf("| Date Naissance : %02d/%02d/%-19d |\n", student->date_naissance.jour, + student->date_naissance.mois, student->date_naissance.annee); + printf("| Filiere : %-25.25s |\n", student->filiere); + printf("| Moyenne : %-25.2f |\n", student->moyenne); + printf("+--------------------------------------------+\n"); +} + +static void sort_by_arbre_recursive(ab_node_student *node) { + if (node != NULL) { + sort_by_arbre_recursive(node->filsd); + display_student_arbre(node->std); + sort_by_arbre_recursive(node->filsg); + } +} + +void afficher_arbres_trie(ab_racine_student *racine) { + if (racine == NULL || racine->racine == NULL) { + printf("L'arbre est vide.\n"); + return; + } + printf("\n=== Liste des etudiants triee par moyenne (Decroissant) ===\n"); + sort_by_arbre_recursive(racine->racine); + printf("===========================================================\n"); +} diff --git a/student.h b/student.h index 71838a6..0acee02 100644 --- a/student.h +++ b/student.h @@ -37,10 +37,14 @@ student *creat_student(); // Crée et initialise un nouvel étudiant. void display_all_student(list_student *list_student); // Affiche les informations de tous les étudiants de la liste. +void display_student(list_student *list_student, char *cne); + void save_database(list_student *list, char *filename); // Sauvegarde la liste des étudiants dans un fichier. + void load_database(list_student *list, char *filename); // Charge la liste des étudiants à partir d'un fichier. + void search_student_by_cne(list_student *list, char *cne); void delete_all_students(list_student *list); @@ -52,4 +56,5 @@ student *get_middle(student *head); student *merge_sorted_lists(student *left, student *right); student *merge_sort_recursive(student *head); + #endif //MINI_DATABASE_STUDENT_H diff --git a/test_student.c b/test_student.c index bb4d80e..4ce5616 100644 --- a/test_student.c +++ b/test_student.c @@ -3,6 +3,7 @@ #include #include "student.h" #include "undo_stack.h" +#include "arbres_binaire.h" // Déclarations des fonctions manquantes dans student.h void add_student(list_student *list, student *new_student, UndoStack *stack); @@ -439,6 +440,232 @@ void test_merge_sort_recursive() { } } +/** + * @brief Test de création d'un noeud d'arbre binaire. + */ +void test_create_ab_node() { + printf("\n\n=== Test de creation d'un noeud d'arbre binaire ===\n"); + + // Test avec un étudiant valide + student *s = create_test_student("Alami", "Ahmed", "CNE001", 15.5); + ab_node_student *node = create_ab_node(s); + + if (node != NULL && node->std == s && node->filsg == NULL && node->filsd == NULL) { + printf("SUCCESS: Noeud cree avec succes.\n"); + printf(" Etudiant: %s %s, Moyenne: %.2f\n", node->std->nom, node->std->prenom, node->std->moyenne); + } else { + printf("ECHEC: Creation de noeud incorrecte.\n"); + } + + // Test avec NULL + ab_node_student *null_node = create_ab_node(NULL); + if (null_node == NULL) { + printf("SUCCESS: create_ab_node retourne NULL pour un etudiant NULL.\n"); + } else { + printf("ECHEC: create_ab_node devrait retourner NULL.\n"); + } + + free(node); + free(s); +} + +/** + * @brief Test de création de la racine d'arbre binaire. + */ +void test_create_ab_racine() { + printf("\n\n=== Test de creation de la racine d'arbre ===\n"); + + ab_racine_student *racine = create_ab_racine(); + + if (racine != NULL && racine->racine == NULL) { + printf("SUCCESS: Racine d'arbre creee avec succes (racine vide).\n"); + } else { + printf("ECHEC: Creation de racine incorrecte.\n"); + } + + free(racine); +} + +/** + * @brief Test d'insertion dans un arbre binaire de recherche. + */ +void test_insert_bst() { + printf("\n\n=== Test d'insertion dans un arbre binaire de recherche ===\n"); + + ab_racine_student *racine = create_ab_racine(); + + // Insérer plusieurs étudiants + student *s1 = create_test_student("Alami", "Ahmed", "CNE001", 15.0); + student *s2 = create_test_student("Bennani", "Fatima", "CNE002", 12.0); + student *s3 = create_test_student("Cherif", "Hassan", "CNE003", 18.0); + student *s4 = create_test_student("Drissi", "Salma", "CNE004", 14.0); + student *s5 = create_test_student("El Amrani", "Youssef", "CNE005", 16.0); + + ab_node_student *n1 = create_ab_node(s1); + ab_node_student *n2 = create_ab_node(s2); + ab_node_student *n3 = create_ab_node(s3); + ab_node_student *n4 = create_ab_node(s4); + ab_node_student *n5 = create_ab_node(s5); + + insert_bst(racine, n1); + insert_bst(racine, n2); + insert_bst(racine, n3); + insert_bst(racine, n4); + insert_bst(racine, n5); + + // Vérifier que la racine n'est pas NULL + if (racine->racine != NULL) { + printf("SUCCESS: Les noeuds ont ete inseres dans l'arbre.\n"); + printf(" Racine (moyenne): %.2f\n", racine->racine->std->moyenne); + + // Vérifier la structure BST + if (racine->racine->std->moyenne == 15.0) { + printf(" Fils gauche (moyenne < 15.0): "); + if (racine->racine->filsg != NULL) { + printf("%.2f\n", racine->racine->filsg->std->moyenne); + } else { + printf("NULL\n"); + } + + printf(" Fils droit (moyenne >= 15.0): "); + if (racine->racine->filsd != NULL) { + printf("%.2f\n", racine->racine->filsd->std->moyenne); + } else { + printf("NULL\n"); + } + } + } else { + printf("ECHEC: L'arbre est vide apres insertion.\n"); + } + + // Test avec NULL + insert_bst(NULL, n1); + insert_bst(racine, NULL); + printf("SUCCESS: Aucun crash avec parametres NULL.\n"); + + free_bst_nodes(racine->racine); + free(racine); + free(s1); + free(s2); + free(s3); + free(s4); + free(s5); +} + +/** + * @brief Test d'affichage de l'arbre trié. + */ +void test_afficher_arbres_trie() { + printf("\n\n=== Test d'affichage d'arbre trie ===\n"); + + ab_racine_student *racine = create_ab_racine(); + + // Test avec arbre vide + printf("\nTest avec arbre vide:\n"); + afficher_arbres_trie(racine); + + // Ajouter des étudiants + student *s1 = create_test_student("Alami", "Ahmed", "CNE001", 15.0); + student *s2 = create_test_student("Bennani", "Fatima", "CNE002", 12.0); + student *s3 = create_test_student("Cherif", "Hassan", "CNE003", 18.0); + student *s4 = create_test_student("Drissi", "Salma", "CNE004", 14.0); + student *s5 = create_test_student("El Amrani", "Youssef", "CNE005", 16.0); + + insert_bst(racine, create_ab_node(s1)); + insert_bst(racine, create_ab_node(s2)); + insert_bst(racine, create_ab_node(s3)); + insert_bst(racine, create_ab_node(s4)); + insert_bst(racine, create_ab_node(s5)); + + printf("\nAffichage de l'arbre (ordre decroissant):\n"); + afficher_arbres_trie(racine); + + printf("\nSUCCESS: L'arbre a ete affiche (verifiez visuellement l'ordre decroissant).\n"); + + free_bst_nodes(racine->racine); + free(racine); + free(s1); + free(s2); + free(s3); + free(s4); + free(s5); +} + +/** + * @brief Test de libération de la mémoire de l'arbre. + */ +void test_free_bst_nodes() { + printf("\n\n=== Test de liberation de memoire de l'arbre ===\n"); + + ab_racine_student *racine = create_ab_racine(); + student *students[10]; + + // Ajouter des étudiants + for (int i = 0; i < 10; i++) { + char cne[20]; + sprintf(cne, "CNE%03d", i); + students[i] = create_test_student("Nom", "Prenom", cne, 10.0 + i); + insert_bst(racine, create_ab_node(students[i])); + } + + printf("10 noeuds inseres dans l'arbre.\n"); + + // Libérer tous les noeuds + free_bst_nodes(racine->racine); + racine->racine = NULL; + + printf("SUCCESS: Tous les noeuds ont ete liberes (aucun crash).\n"); + + // Test avec NULL + free_bst_nodes(NULL); + printf("SUCCESS: Aucun crash avec free_bst_nodes(NULL).\n"); + + // Libérer les étudiants + for (int i = 0; i < 10; i++) { + free(students[i]); + } + + free(racine); +} + +/** + * @brief Test complet de l'arbre binaire de recherche. + */ +void test_bst_complete() { + printf("\n\n=== Test complet de l'arbre binaire de recherche ===\n"); + + ab_racine_student *racine = create_ab_racine(); + + // Créer et insérer des étudiants dans un ordre aléatoire + float moyennes[] = {15.0, 10.0, 20.0, 8.0, 12.0, 18.0, 22.0}; + int count = sizeof(moyennes) / sizeof(moyennes[0]); + student *students[7]; // Garder les références + + printf("Insertion des moyennes dans l'ordre: "); + for (int i = 0; i < count; i++) { + printf("%.1f ", moyennes[i]); + char cne[20]; + sprintf(cne, "CNE%03d", i); + students[i] = create_test_student("Etudiant", "Test", cne, moyennes[i]); + insert_bst(racine, create_ab_node(students[i])); + } + printf("\n"); + + printf("\nAffichage de l'arbre trie (devrait etre en ordre decroissant):\n"); + afficher_arbres_trie(racine); + + printf("\nSUCCESS: Test complet termine.\n"); + printf("Attendu (ordre decroissant): 22.0, 20.0, 18.0, 15.0, 12.0, 10.0, 8.0\n"); + + free_bst_nodes(racine->racine); + free(racine); + + // Libérer les étudiants + for (int i = 0; i < count; i++) { + free(students[i]); + } +} + /** * @brief Test de la fonction de modification d'étudiant. */ @@ -588,6 +815,15 @@ int main() { printf("\n\n*** TESTS DE MODIFICATION ***\n"); test_modify_student(); + // Tests des arbres binaires + printf("\n\n*** TESTS DES ARBRES BINAIRES DE RECHERCHE ***\n"); + test_create_ab_node(); + test_create_ab_racine(); + test_insert_bst(); + test_afficher_arbres_trie(); + test_free_bst_nodes(); + test_bst_complete(); + printf("\n========================================\n"); printf(" FIN DE TOUS LES TESTS\n"); printf("========================================\n");