Post

TD1 Listes Chainees Correction Informatique3 PREING2 S1

Télécharger le TD1 Listes Chainees en pdf

Exercices : 1 2 3 4 5

Exercice 1

Télécharger l’exercice exo1.c

exercice 1

  • On inclue les bibliothèques utiles
1
2
3
#include <stdio.h>
#include <stdlib.h>

  • On définie la structure Chainon pour représenter un élément d’une liste chaînée
1
2
3
4
5
6
typedef struct chainon_struct
{
    int value; // Valeur stockée dans le chainon
    struct chainon_struct* next; // Pointeur vers le prochain chainon
} Chainon;

  • On crée la fonction qui crée un nouveau chainon avec la valeur ‘a’ et renvoie un pointeur vers celui-ci
1
2
3
4
5
6
7
8
9
10
11
12
Chainon* creationChainon(int a){
    Chainon* nouveau = malloc(sizeof(Chainon)); // Allocation mémoire pour un nouveau chainon
    if (nouveau == NULL) // Vérification de l'échec d'allocation
    {
        exit(EXIT_FAILURE); // Quitter le programme en cas d'échec
    }
    
    nouveau->value = a; // Initialisation de la valeur du chainon
    nouveau->next = NULL; // Le chainon est initialisé sans successeur
    return nouveau; // Retourne un pointeur vers le nouveau chainon
}

  • On crée la fonction pour insérer un chainon au début de la liste
1
2
3
4
5
6
7
8
9
10
11
12
Chainon* insertDebut(Chainon* pliste, int a){
    if (pliste == NULL) // Si la liste est vide
    {
        pliste = creationChainon(a); // Créer un nouveau chainon
    } else {
        Chainon* nouveau = creationChainon(a); // Créer un nouveau chainon
        nouveau->next = pliste; // L'ancien premier élément devient le suivant du nouveau chainon
        pliste = nouveau; // Le nouveau chainon devient le premier de la liste
    }
    return pliste; // Retourner la nouvelle tête de liste
}

  • On crée la fonction pour insérer un chainon à la fin de la liste
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Chainon* insertFin(Chainon* pliste, int a){
    if (pliste == NULL) // Si la liste est vide
    {
        pliste = creationChainon(a); // Créer un nouveau chainon
    } else {
        Chainon* actual = pliste; // Commencer au début de la liste
        while (actual->next != NULL) // Parcourir la liste jusqu'à la fin
        {
            actual = actual->next;
        }
        actual->next = creationChainon(a); // Ajouter le nouveau chainon à la fin
    }
    return pliste; // Retourner la tête de la liste
}

  • On crée la fonction pour afficher la liste chainée
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void afficheListe(Chainon* pliste){
    if (pliste == NULL) // Si la liste est vide
    {
        printf("liste vide\n"); // Afficher un message
    }
    Chainon* actual = pliste; // Commencer au début de la liste
    while (actual->next != NULL) // Parcourir la liste jusqu'à l'avant-dernier élément
    {  
        printf("%d -> ", actual->value); // Afficher la valeur de chaque chainon
        actual = actual->next;
    }
    printf("%d", actual->value); // Afficher la dernière valeur sans flèche
    printf("\n");
}

  • On crée la fonction pour lire un entier sécurisé depuis l’utilisateur
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int better_scan(const char * message){
    int ret_var = 0; // Variable pour capturer le résultat de scanf
    int value = 1; // Initialisation de la variable à retourner
    while (ret_var != 1) // Boucle jusqu'à obtenir une saisie valide
    {   
        if (message != NULL)
        {
            printf("%s", message); // Afficher le message si non nul
        }
        ret_var = scanf("%d", &value); // Lecture de la valeur
        while(getchar()!='\n'){} // Vider le buffer de saisie (sécurisation)
    }
    return value; // Retourner la valeur saisie
}

  • On teste le tout dans la fonction principale
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
int main(){
    
    Chainon* pliste = NULL; // Initialiser la liste vide
    int nb = 0; // Variable de contrôle de la boucle
    int i = 1; // Compteur pour les valeurs insérées
    while (nb == 0) // Tant que l'utilisateur souhaite ajouter des éléments
    {   
        pliste = insertFin(pliste, i); // Insérer la valeur i à la fin de la liste
        afficheListe(pliste); // Afficher la liste actuelle
        i = i * 2; // Doubler la valeur de i pour la prochaine insertion
        nb = better_scan("Nombre suivant ? \n0 - oui \nautre - non\n"); // Demander à l'utilisateur s'il veut continuer
    }
    
    // On libére la mémoire allouée pour la liste
    Chainon* actual = pliste;
    while (pliste != NULL)
    {
        actual = pliste->next; // Sauvegarder le prochain chainon
        free(pliste); // Libérer la mémoire du chainon actuel
        pliste = actual; // Passer au chainon suivant
    }
    
    return 0; // Fin du programme
}

Exercice 2

Télécharger l’exercice exo2.c

exercice 2

  • On utilise les fonctions et structures précédentes
1
2
3
4
5
#include <stdio.h>
#include <stdlib.h>
...

  • On crée la fonction pour insérer un élément dans une liste triée
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Chainon* InsertTrie(Chainon* pliste, int a) {
    if (a <= pliste->value) { // Si l'élément est plus petit ou égal à la première valeur
        return insertDebut(pliste, a); // Insère au début de la liste
    }

    Chainon* borne1 = pliste; // Pointeur sur l'élément actuel
    Chainon* borne2 = pliste->next; // Pointeur sur l'élément suivant

    while (borne2 != NULL) { // Parcourt la liste jusqu'à trouver la bonne position pour insérer 'a'
        if (borne1->value < a && a <= borne2->value) { // Si 'a' est compris entre les deux valeurs
            Chainon* a_chainon = creationChainon(a); // Crée un nouveau chainon avec la valeur 'a'
            a_chainon->next = borne2; // Le nouveau chainon pointe vers 'borne2'
            borne1->next = a_chainon; // 'borne1' pointe maintenant vers le nouveau chainon
            return pliste; // Retourne la tête de la liste
        }
        borne1 = borne2; // Passe la borne1 à l'élément suivant a chaque tour de bouvle
        borne2 = borne2->next; // Passe la borne2 à l'élément suivant a chaque tour de boucle
    }

    return insertFin(pliste, a); // Si 'a' est plus grand que toutes les valeurs, insère à la fin
}

  • On teste le tout dans la fonction principale
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
int main() {
    Chainon* pliste = NULL; // Initialise la liste à vide
    for (int i = 0; i < 20; i += 5) { // Insère des multiples de 5 dans la liste
        pliste = insertFin(pliste, i); // Insère chaque élément à la fin
    }
    afficheListe(pliste); // Affiche la liste après insertion

    InsertTrie(pliste, 2); // Insère 2 dans la liste
    InsertTrie(pliste, 12); // Insère 12 dans la liste
    InsertTrie(pliste, 22); // Insère 22 dans la liste

    afficheListe(pliste); // Affiche la liste après les insertions triées

    Chainon* actual = pliste;
    while (pliste != NULL)
    {
        actual = pliste->next; // Sauvegarder le prochain chainon
        free(pliste); // Libérer la mémoire du chainon actuel
        pliste = actual; // Passer au chainon suivant
    }
    
    return 0; // Fin du programme
}

Exercice 3

Télécharger l’exercice exo3.c

exercice 3

  • On utilise les fonctions et structures précédentes
1
2
3
4
5
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
...

  • On crée la fonction pour supprimer la première occurrence d’un élément ‘a’ dans la liste
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Chainon* SupprimerPremier(Chainon* pliste, int a){
    if (pliste == NULL){
        return pliste; // Liste vide
    }

    if (pliste->value == a){// Cas où le premier élément de la liste doit être supprimé
        Chainon* suppr = pliste; // Stocke l'élément à supprimer
        pliste = pliste->next; // Le suivant devient le premier élément
        free(suppr); // Libère la mémoire
        return pliste; // Retourne la nouvelle tête de liste
    }

    Chainon* actual = pliste;
    Chainon* suppr = NULL;
    
    while (actual->next != NULL){
        if (actual->next->value == a){ // Trouve l'élément à supprimer
            suppr = actual->next; // Stocke l'élément à supprimer
            actual->next = actual->next->next; // Saute cet élément dans la liste
            free(suppr); // Libère la mémoire
            return pliste; // Retourne la tête de la liste
        }
        actual = actual->next; // Continue à parcourir la liste
    }
    return pliste; // Retourne la liste si l'élément n'a pas été trouvé
}

  • On crée la fonction pour supprimer toutes les occurrences d’un élément ‘a’ dans la liste
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
Chainon* SupprimerTout(Chainon* pliste, int a){
    if (pliste == NULL){
        return pliste; // Liste vide
    }

    
    while (pliste != NULL && pliste->value == a){// Cas où le premier élément doit être supprimé (si c'est 'a')
        Chainon* suppr = pliste;
        pliste = pliste->next; // Le suivant devient le premier
        free(suppr); // Libère la mémoire du chainon supprimé
    }

    Chainon* actual = pliste;
    Chainon* suppr = NULL;
    
    
    while (actual != NULL && actual->next != NULL){// Parcourt la liste à partir du deuxième élément
        if (actual->next->value == a){ // Trouve l'élément à supprimer
            suppr = actual->next;
            actual->next = actual->next->next; // Saute l'élément dans la chaîne
            free(suppr); // Libère la mémoire
        } else {
            actual = actual->next; // Passe au chainon suivant
        }
    }
    return pliste; // Retourne la tête de la liste modifiée
}

  • On teste le tout dans la fonction principale
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
int main(){
    srand(time(NULL)); 
    Chainon* pliste = NULL;
    
    for (int i = 0; i < 10; i++){
        pliste = insertFin(pliste, rand() % 6);
    }
    
   
    afficheListe(pliste);
    
   
    pliste = SupprimerPremier(pliste, 2);
    afficheListe(pliste); 

    pliste = SupprimerTout(pliste, 5);
    afficheListe(pliste); 

    Chainon* actual = pliste;
    while (pliste != NULL){
        actual = pliste->next;
        free(pliste);
        pliste = actual;
    }
    
    return 0;
}

Exercice 4

Télécharger l’exercice exo4.c

exercice 4

  • On utilise les fonctions et structures précédentes
1
2
3
4
5
6
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

...

  • On crée la fonction pour inverser la liste en créant une nouvelle liste
1
2
3
4
5
6
7
8
9
10
11
Chainon* Inverse(Chainon* pliste){
    Chainon* newliste = NULL; // Nouvelle liste initialement vide

    Chainon* actual = pliste; // Commence à parcourir la liste originale
    while (actual != NULL){
        newliste = insertDebut(newliste, actual->value); // Insère au début de la nouvelle liste
        actual = actual->next; // Passe au chainon suivant
    }
    return newliste; // Retourne la nouvelle liste inversée
}

  • On crée la fonction pour inverser la liste en modifiant les pointeurs directement sans passer par une liste intermédiaire
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Chainon* Inverse2(Chainon* pliste){
    if (pliste == NULL){
        return NULL; // Retourne NULL si la liste est vide
    }

    Chainon* previous = pliste->next; // Pointeur sur le deuxième élément
    Chainon* actual = pliste; // Pointeur sur le premier élément
    Chainon* tmp = NULL; // Variable temporaire pour la manipulation des pointeurs
    actual->next = NULL; // Le premier élément devient le dernier, donc son pointeur 'next' est NULL

    while (previous != NULL){
        tmp = previous->next; // Sauvegarde le prochain élément
        previous->next = actual; // Inverse le pointeur du chainon actuel
        actual = previous; // Avance le chainon actuel
        previous = tmp; // Passe au chainon suivant
    }
    return actual; // Retourne la nouvelle tête de la liste inversée
}

  • On test le tout dans la fonction principale sans oublier de free les différentes listes a la fin
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
int main(){
    srand(time(NULL));
    Chainon* pliste = NULL;
    

    for (int i = 0; i < 10; i++){
        pliste = insertFin(pliste, rand() % 6);
    }
    
    afficheListe(pliste); 

    Chainon* pliste2 = Inverse(pliste); 
    afficheListe(pliste2); 
    
    pliste2 = Inverse2(pliste2); 
    afficheListe(pliste2); 


    Chainon* actual = pliste;
    while (pliste != NULL){
        actual = pliste->next;
        free(pliste);
        pliste = actual;
    }
    actual = pliste2;
    while (pliste2 != NULL){
        actual = pliste2->next;
        free(pliste2);
        pliste2 = actual;
    }
    
    return 0;
}

Exercice 5

Télécharger l’exercice exo5.c

exercice 5

exercice 5

  • On definie les différentes structure/definitions/fonctions utiles pour le programme
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#define Nb_notes 10

typedef struct etudiant_struct {
    char nom[50];
    char prenom[50];
    int groupe;
    int notes[Nb_notes];
} Etudiant;

typedef struct chainon_struct {
    Etudiant etudiant;
    struct chainon_struct* next;
} Chainon;

int better_scan(const char * message){
    int ret_var = 0;
    int value = 1;
    while (ret_var != 1)
    {   
        if (message != NULL)
        {
            printf("%s", message);
        }
        ret_var = scanf("%d", &value);
        while(getchar()!='\n'){} // Ligne facultative de sécurisation
    }
    return value;
    
}

  • On crée la fonction pour créer un nouvel étudiant
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Etudiant creerEtudiant() {
    Etudiant etudiant;
    printf("Nom: ");
    if (fgets(etudiant.nom, 50, stdin) == NULL){
        exit(EXIT_FAILURE); 
    }
    etudiant.nom[strlen(etudiant.nom)-1] = '\0';
    printf("Prenom: ");
    if (fgets(etudiant.prenom, 50, stdin) == NULL){
        exit(EXIT_FAILURE); 
    }
    etudiant.prenom[strlen(etudiant.prenom)-1] = '\0';
    printf("Groupe: ");
    etudiant.groupe = better_scan("Saisir numero grp :\n");
    
    for (int i = 0; i < Nb_notes; i++) {
        etudiant.notes[i] = rand() % 21; // Notes entre 0 et 20
    }
    return etudiant;
}

  • On crée la fonction pour ajouter un étudiant à la fin de la liste
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void saisirEtudiant(Chainon** lst) { //on utilise un double pointeur pour ne pas avoir besoin de retourner la liste
    Chainon* nouveau = (Chainon*)malloc(sizeof(Chainon));
    if (nouveau == NULL) {
        printf("Erreur d'allocation mémoire.\n");
        exit(EXIT_FAILURE);
    }
    nouveau->etudiant = creerEtudiant();
    nouveau->next = NULL;

    if (*lst == NULL) {
        *lst = nouveau;
    } else {
        Chainon* tmp = *lst;
        while (tmp->next != NULL) {
            tmp = tmp->next;
        }
        tmp->next = nouveau;
    }
}

  • On crée la fonction pour afficher les étudiants par groupe
1
2
3
4
5
6
7
8
9
10
void listeParGroupe(Chainon* lst, int groupe) {
    Chainon* tmp = lst;
    while (tmp != NULL) {
        if (tmp->etudiant.groupe == groupe) {
            printf("%s %s\n", tmp->etudiant.nom, tmp->etudiant.prenom);
        }
        tmp = tmp->next;
    }
}

  • On crée la fonction pour calculer la moyenne d’un tableau de notes
1
2
3
4
5
6
7
8
float moyTab(int* tab) {
    float somme = 0;
    for (int i = 0; i < Nb_notes; i++) {
        somme += tab[i];
    }
    return somme / Nb_notes;
}

  • On crée la fonction pour trouver un étudiant par nom et prénom
1
2
3
4
5
6
7
8
9
10
11
Chainon* trouveEtudiant(char* nom, char* prenom, Chainon* lst) {
    Chainon* tmp = lst;
    while (tmp != NULL) {
        if (strcmp(tmp->etudiant.nom, nom) == 0 && strcmp(tmp->etudiant.prenom, prenom) == 0) {
            return tmp;
        }
        tmp = tmp->next;
    }
    return NULL;
}

  • On crée la fonction pour calculer la moyenne d’un étudiant spécifique
1
2
3
4
5
6
7
8
9
void moyenneEtudiant(Chainon* lst, char* nom, char* prenom) {
    Chainon* etudiant = trouveEtudiant(nom, prenom, lst);
    if (etudiant) {
        printf("Moyenne de %s %s: %f\n", nom, prenom, moyTab(etudiant->etudiant.notes));
    } else {
        printf("Erreur: aucun étudiant avec le nom %s %s trouvé.\n", nom, prenom);
    }
}

  • On crée la fonction pour calculer la moyenne de toute la promotion
1
2
3
4
5
6
7
8
9
10
11
12
13
float moyennePromotion(Chainon* lst) {
    float somme = 0;
    int count = 0;
    Chainon* tmp = lst;
    while (tmp != NULL) {
        somme += moyTab(tmp->etudiant.notes);
        count++;
        tmp = tmp->next;
    }

    return count ? somme / count : 0;
}

  • On crée la fonction pour afficher l’étudiant avec la plus mauvaise moyenne
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void etudiantPireMoyenne(Chainon* lst) {
    if (lst == NULL) {
        printf("Pas d'étudiants dans la liste.\n");
        return;
    }

    Chainon* tmp = lst;
    Chainon* pire = lst;
    float pireMoyenne = moyTab(tmp->etudiant.notes);

    while (tmp != NULL) { //calcul classique de minimum
        float moyenneActuelle = moyTab(tmp->etudiant.notes);
        if (moyenneActuelle < pireMoyenne) {
            pire = tmp;
            pireMoyenne = moyenneActuelle;
        }
        tmp = tmp->next;
    }

    printf("L'étudiant avec la plus mauvaise moyenne est %s %s avec %f de moyenne.\n", pire->etudiant.nom, pire->etudiant.prenom, pireMoyenne);
}

  • On crée le main pour choisir ce que l’on veut faire
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
int main() {
    srand(time(NULL));
    Chainon* etudiant_plist = NULL;
    int choix, groupe;
    char nom[50], prenom[50];

    do {
        printf("\nMenu:\n");
        printf("1. Saisir un nouvel étudiant\n");
        printf("2. Afficher les étudiants par groupe\n");
        printf("3. Calculer la moyenne d'un étudiant\n");
        printf("4. Calculer la moyenne de la promotion\n");
        printf("5. Afficher l'étudiant avec la plus mauvaise moyenne\n");
        printf("6. Quitter\n");
        printf("Votre choix: ");
        choix = better_scan("Votre choix: ");

        switch (choix) {
            case 1:
                saisirEtudiant(&etudiant_plist);
                break;
            case 2:
                groupe = better_scan("Entrez le numéro du groupe: ");
                listeParGroupe(etudiant_plist, groupe);
                break;
            case 3:
                printf("Entrez le nom de l'étudiant: ");
                if (fgets(nom, 50, stdin) == NULL){
                    exit(EXIT_FAILURE); 
                }
                nom[strlen(nom)-1] = '\0';
                printf("Entrez le prénom de l'étudiant: ");
                if (fgets(prenom, 50, stdin) == NULL){
                    exit(EXIT_FAILURE); 
                }
                prenom[strlen(prenom)-1] = '\0';
                moyenneEtudiant(etudiant_plist, nom, prenom);
                break;
            case 4:
                printf("Moyenne de la promotion: %f\n", moyennePromotion(etudiant_plist));
                break;
            case 5:
                etudiantPireMoyenne(etudiant_plist);
                break;
            case 6:
                printf("Salem !\n");
                break;
            default:
                printf("Choix invalide!\n");
                break;
        }
    } while (choix != 6);

    Chainon* actual = etudiant_plist; //On oublie pas de free la memoire
    while (etudiant_plist != NULL){
        actual = etudiant_plist->next;
        free(etudiant_plist);
        etudiant_plist = actual;
    }
    return 0;
}

Exercices : 1 2 3 4 5

Cet article est sous licence BSD 2-Close licence par l'auteur.