Post

DS1 2023 2024 Correction Informatique3-DS PREING2 S1

Voir le DS1 2023 2024 en pdf

Exercices : 1 2

Exercice 1

Télécharger l’exercice exo1.c

exercice 1

  • On inclut les bibliothèques nécessaires pour l’affichage et la gestion de la mémoire
  • On définit la structure Chainon pour représenter un élément d’une liste chaînée,
  • On définit la structure File pour représenter une file (queue) de chainons
  • 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
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <stdio.h>
#include <stdlib.h>

typedef struct chainon_struct
{
    int value; // Valeur stockée dans le chainon
    struct chainon_struct* next; // Pointeur vers le prochain chainon dans la liste
} Chainon;


typedef struct file_struct
{
    Chainon* tete; // Pointeur vers le sommet de la file (premier élément)
    Chainon* fin; // Pointeur vers le pied de la file (dernier élément)
    int nb; // Nombre d'éléments (personnes) dans la file
} File;


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 ajouter un nouveau chainon dans la file pfile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void entrerFile(File* pfile) {
    int nb = 2 + rand() % 9; // Génère un nombre aléatoire entre 2 et 10 pour la taille du groupe
    if (pfile == NULL) // Vérification que la file existe
    {
        exit(EXIT_FAILURE);
    }
    if (pfile->fin == NULL) // Si la file est vide, initialise le premier élément
    {
        pfile->fin = creationChainon(nb); // Création du premier chainon
        pfile->tete = pfile->fin; // La tête et la fin pointent sur le même chainon
    } else {
        pfile->fin->next = creationChainon(nb); // Ajoute le nouveau chainon à la fin de la file
        pfile->fin = pfile->fin->next;
    }
    pfile->nb += nb; // Met à jour le nombre total dans la file
}

  • On crée la fonction qui permet de retirer le premier chainon de la file et mettre à jour le nombre de personnes
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
File* sortirFile(File* pfile, int* groupe) {
    if (pfile == NULL) // Vérifie que la file existe
    {
        exit(EXIT_FAILURE);
    }
    if (pfile->tete == NULL || pfile->fin == NULL) // Si la file est vide, renvoie la file inchangée
    {
        return pfile;
    }

    Chainon* tmp = pfile->tete->next; // Sauvegarde l'élément suivant de la tête
    *groupe = pfile->tete->value; // Stocke la valeur du premier élément
    pfile->nb -= *groupe; // Déduit ce nombre du total de la file
    free(pfile->tete); // Libère la mémoire de l'ancien premier élément
    pfile->tete = tmp; // Met à jour la tête de la file

    return pfile; // Retourne la file mise à jour
}

  • On crée la fonction qui vérifie si la file est pleine (>= 500 personnes)
1
2
3
4
5
6
7
8
int filePleine(File* pfile) {
    if (pfile == NULL) // Vérifie que la file existe
    {
        exit(EXIT_FAILURE);
    }
    return pfile->nb >= 500; // Retourne vrai si la file est pleine
}

  • On crée la fonction qui permet de remplir un train avec les groupes contenue dans la file
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
void remplirTrain(File* pfile) {
    if (pfile == NULL) // Vérifie que la file existe
    {
        exit(EXIT_FAILURE);
    }
    if (pfile->tete != NULL) // Si la file n'est pas vide
    {
        int groupe; // Taille du groupe retiré
        int reduction; // Facteur de réduction pour chaque rangée en fonction de la taille du groupe
        int nb_rangee = 8; // Nombre de rangées disponibles dans le train
        int nb_siege = nb_rangee * 4; // Nombre total de sièges dans le train
        
        while (nb_rangee > 0) // Tant qu'il reste des rangées
        {
            // Détermine le nombre de rangées à déduire en fonction de la taille du groupe
            if (pfile->tete->value <= 4)
            {
                reduction = 1;
            } else if (pfile->tete->value <= 8) {
                reduction = 2;
            } else {
                reduction = 3;
            }

            if (nb_rangee >= reduction) // Si assez de rangées sont disponibles
            {
                nb_rangee -= reduction; // Réduit le nombre de rangées
                sortirFile(pfile, &groupe); // Retire un groupe de la file
                nb_siege -= groupe; // Met à jour le nombre de sièges disponibles
            } else {
                nb_rangee = 0; // Si plus de rangées disponibles, sort de la boucle
            }
        }
        printf("Nombre de sièges vides : %d/%d\n", nb_siege, 4 * 8); // Affiche le nombre de sièges libres
    }
}

  • On crée la fonction qui permet de simuler une période de trois minutes dans la gestion de la file
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void three_minutes(File* pfile) {
    if (pfile == NULL) // Vérifie que la file existe
    {
        exit(EXIT_FAILURE);
    }
    remplirTrain(pfile); // Remplit le train une première fois
    remplirTrain(pfile); // Remplit à nouveau le train
    
    for (int i = 0; i < 16; i++) // Effectue 16 entrées dans la file, sauf si elle est pleine
    {   
        if (!filePleine(pfile)) // Vérifie si la file n'est pas encore pleine
        {
            entrerFile(pfile); // Ajoute un groupe dans la file
        }
    }
}

Exercice 2

Télécharger l’exercice exo2.c

exercice 2

  • On définit la structure Chainon pour représenter un élément d’une liste doublement chaînée
1
2
3
4
5
6
7
8
9
10
#include <stdio.h>
#include <stdlib.h>

typedef struct chainon_struct
{
    char* value; // Valeur stockée dans le chainon
    struct chainon_struct* prev; // Pointeur vers le chaînon précédent
    struct chainon_struct* next; // Pointeur vers le prochain chaînon
} Chainon;

  • On définit la structure Deque pour représenter une file doublement chaînée (Deque)
1
2
3
4
5
6
7
typedef struct deque_struct
{
    Chainon* tete; // Pointeur vers le sommet (début de la deque)
    Chainon* fin; // Pointeur vers la fin de la deque
    int nb; // Nombre d'éléments dans la deque
} Deque;

  • On nous donne les fonctions suivantes comme déjà écrites
1
2
3
Chainon* creerChainon(char* a);
void supprimerChainon(Chainon* a);

  • On crée la fonction qui ajoute un élément au début de la deque
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void ajoutDebutDeque(Deque* pdeque, char* a) {
    if (pdeque == NULL || ((pdeque->tete == NULL) ^ (pdeque->fin == NULL)) || a == NULL) // Vérification des paramètres
    {
        exit(EXIT_FAILURE); // Quitte en cas d'erreur
    }
    if (pdeque->tete == NULL || pdeque->fin == NULL) // Si la deque est vide, initialise le premier élément
    {
        pdeque->tete = creerChainon(a); // Crée un nouveau chainon avec la valeur 'a'
        pdeque->fin = pdeque->tete; // La tête et la fin pointent sur le même chainon
    } else {
        pdeque->tete->prev = creerChainon(a); // Crée un nouveau chainon et le lie avant la tête actuelle
        pdeque->tete->prev->next = pdeque->tete; // Lie l'ancien sommet avec le nouveau chainon
        pdeque->tete = pdeque->tete->prev; // Met à jour la tête de la deque
    }
    pdeque->nb++; // Augmente le nombre d'éléments dans la deque
}

Le signe ^ est une operation booléenne correspond au $XOR$ appelé aussi “ou exclusif”, on l’utilise car si un des deux est NULL et l’autre non alors il y’a un problème

  • On crée la fonction qui supprime un élément de la fin de la deque
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
int supprimerFinDeque(Deque* pdeque) {
    if (pdeque == NULL || ((pdeque->tete == NULL) ^ (pdeque->fin == NULL))) // Vérification des paramètres
    {
        exit(EXIT_FAILURE);
    }
    if (pdeque->tete != NULL && pdeque->fin != NULL) // Si la deque contient des éléments
    {
        Chainon* tmp = pdeque->fin; // Sauvegarde le chainon actuel à la fin
        pdeque->fin = pdeque->fin->prev; // Déplace le pointeur de fin au chainon précédent
        free(tmp); // Libère la mémoire de l'ancien dernier chainon
        if (pdeque->fin == NULL) // Si la deque devient vide après la suppression
        {
            pdeque->tete = pdeque->fin; // Met la tête et la fin à NULL
        }
        pdeque->nb--; // Diminue le nombre d'éléments
        return 1; // Indique que la suppression a été effectuée
    }
    return 0; // Renvoie 0 si aucune suppression n'a eu lieu
}

  • On crée la fonction qui ajoute un élément en début d’historique dans la deque, et supprime l’élément le plus ancien si nécessaire
1
2
3
4
5
6
7
8
9
10
11
12
void ajoutHistorique(Deque* pdeque, char* a) {
    if (pdeque == NULL || ((pdeque->tete == NULL) ^ (pdeque->fin == NULL)) || a == NULL) // Vérification des paramètres
    {
        exit(EXIT_FAILURE);
    }
    ajoutDebutDeque(pdeque, a); // Ajoute l'élément en début de deque
    if (pdeque->nb > 10) // Si la deque contient plus de 10 éléments
    {
        supprimerFinDeque(pdeque); // Supprime l'élément le plus ancien (à la fin)
    }
}

  • On crée la fonction qui retourne la valeur de l’élément précédent dans l’historique
1
2
3
4
5
6
7
8
char* precedant(Deque* pdeque) {
    if (pdeque == NULL || ((pdeque->tete == NULL) ^ (pdeque->fin == NULL))) // Vérification des paramètres
    {
        exit(EXIT_FAILURE);
    }
    return pdeque->tete->prev->value; // Retourne la valeur de l'élément précédent en tête de la deque
}

Exercices : 1 2

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