diff --git a/lessons/contenu_cours_struct_pile.md b/lessons/contenu_cours_struct_pile.md index 95633cf60980852edbcaa2d2e84fbbec1e7e2b9a..64002212eaaba036ebcb033b966fe7bbf20c3e70 100644 --- a/lessons/contenu_cours_struct_pile.md +++ b/lessons/contenu_cours_struct_pile.md @@ -1,6 +1,6 @@ # Algorithmes et structures de données -# Structure de piles +# Structure de pile ***** diff --git a/lessons/contenu_cours_struct_queue.md b/lessons/contenu_cours_struct_queue.md new file mode 100644 index 0000000000000000000000000000000000000000..6c456fa5096d138412a90886c80c143ff7ea6256 --- /dev/null +++ b/lessons/contenu_cours_struct_queue.md @@ -0,0 +1,114 @@ +# Algorithmes et structures de données + +# Structure de file d'attente + +***** + +## 1. Définition + +Une file d'attente ou queue est une structure de données dans laquelle la première information entrée est la première à ressortir (en anglais : FIFO, First In First Out) + +On considère ici une implémentation de queue dynamique et donc à capacité « infinie » (dépend en réalité de la mémoire disponible). + +## 2. Spécification de la structure + +Si le type des éléments qu'on insère, n'est pas précisé, on parle de spécification générique. + +Les opérations possibles sur une file d'attente (ou queue) en définissent l'interface : + +* Opérations de manipulation + * Créer une liste vide + * Détruire une liste + * Insérer un nouvel élément en queue de la file d'attente + * Extraire un élément en tête de la file d'attente (i.e. le premier élément introduit) + * +* Fonctions de consultation + * Lire l'élément en tête de la file d'attente + * Lire l'élément en queue de la file d'attente + * Tester si la file d'attente est vide + +L'interface de la file d'attente est l'ensemble des fonctionnalités offertes à l'utilisateur pour interagir +avec celle-ci. + +## 3. Structure de file d'attente + +On considère une liste chaînée d'articles avec deux pointeurs de tête et de queue. Chaque article comportera un champ pour stocker les valeurs dans cette liste et un champ contenant une variable de type accès pour assurer le chaînage. On considère à titre d'exemple le cas de valeurs entières. + +Schématiquement: + + + +L'accès à la file d'attente se fera par les pointeurs de tête et de queue. + +Une telle file d'attente basée sur une liste chaînée sera déclarée par exemple sous la forme suivante: + +```C + struct _element { // Elément de liste + int data; + struct _element* next; + } element; + + struct _queue { // File d'attente: + element* tete; // tête de file d'attente + element* debut; // queue de file d'attente + } +``` + +## 4. Implémentation des fonctionnalité d'une file d'attente + +### a) Consultations + +On considère la fonction queue_est_vide qui teste si la file d'attente est vide et les fonctions `queue_tete` et `queue_debut` qui retournent l'élément en tête, respectivement en queue, de la file d'attente. + +```C + bool queue_est_vide(queue fa) { + return (NULL == fa.tete && NULL == fa.debut); + } + + int queue_tete(queue fa) { + assert(!queue_est_vide(fa)); + return fa.tete>data; + } + + int queue_debut(queue fa) { + assert(!queue_est_vide(fa)); + return fa.debut>data; + } +``` + +### b) Manipulations + +#### Insertion en queue de file d'attente + +Voici l'entête de la fonction: `void queue_inserer(queue* fa,int val);` + +Il faut considérer plusieurs cas: + +* La file d'attente est vide + + + +* L'insertion se fait en queue d'une file d'attente non vide + + + +#### Extraction en tête de file d'attente + +Voici l'entête de la procédure: +`int queue_extraire(queue* fa);` + +On commence par récupérer, la valeur en tête de file d'attente via l'appel `queue_tete(*fa);` + +Puis on met un pointeur temporaire sur l'élément en tête, avant de déplacer le pointeur de tête sur l'élément suivant. +Finalement, on désalloue la mémoire + + + +Si la file d'attente n'avait qu'un seul élément, alors il faudrait mettre le pointeur `fa->debut` à `NULL`. +Dans ce cas, à la suite du point (3), le pointeur `fa->tete` se retrouve à `NULL`. On doit donc ajouter l'instruction : + +```C + if (NULL == fa>tete) { + fa>debut = NULL; + } +``` diff --git a/lessons/figures/fig_empty_queue_insert.png b/lessons/figures/fig_empty_queue_insert.png new file mode 100644 index 0000000000000000000000000000000000000000..0d7aad80007c8a2d0f1a3ae0a3d9561479737a23 Binary files /dev/null and b/lessons/figures/fig_empty_queue_insert.png differ diff --git a/lessons/figures/fig_non_empty_queue_insert.png b/lessons/figures/fig_non_empty_queue_insert.png new file mode 100644 index 0000000000000000000000000000000000000000..8093d290f00bd6f8c320f138374dc28b6a343385 Binary files /dev/null and b/lessons/figures/fig_non_empty_queue_insert.png differ diff --git a/lessons/figures/fig_queue_extract.png b/lessons/figures/fig_queue_extract.png new file mode 100644 index 0000000000000000000000000000000000000000..b103ee95bb0cd145678ece54c2ef5cb6b89d337e Binary files /dev/null and b/lessons/figures/fig_queue_extract.png differ diff --git a/lessons/figures/fig_queue_representation.png b/lessons/figures/fig_queue_representation.png new file mode 100644 index 0000000000000000000000000000000000000000..262d9a7ee941a10e3d50a19ac87a287d6f42ce71 Binary files /dev/null and b/lessons/figures/fig_queue_representation.png differ diff --git a/source_codes/queues/queue_array_int.c b/source_codes/queues/queue_array_int.c new file mode 100644 index 0000000000000000000000000000000000000000..752ef9cf4a4b573bf05d463167a092106bf5fa1e --- /dev/null +++ b/source_codes/queues/queue_array_int.c @@ -0,0 +1,72 @@ +#include <stdlib.h> +#include <stdbool.h> +#include <assert.h> +#include <limits.h> +#include"queue_array_int.h" + +bool queue_est_valide(queue fa) { + return (fa.capacite > 0 && fa.debut >= -1); +} + +bool queue_est_vide(queue fa) { + assert(queue_est_valide(fa)); + return (-1 == fa.debut); +} + +bool queue_est_pleine(queue fa) { + assert(queue_est_valide(fa)); + return (fa.capacite-1 == fa.debut); +} + +int queue_count(queue fa) { + assert(queue_est_valide(fa)); + return fa.debut+1; +} + +int queue_tete(queue fa) { + assert(!queue_est_vide(fa)); + return fa.data[0]; +} + +int queue_debut(queue fa) { + assert(!queue_est_vide(fa)); + return fa.data[fa.debut]; +} + +queue queue_creer() { + queue fa; + fa.capacite = INCR; + fa.debut = -1; + fa.data = malloc(INCR*sizeof(int)); + return fa; +} + +void queue_resize(queue* fa,int max) { + assert(queue_est_valide(*fa)); + if (max > fa->capacite) { + fa->capacite = max; + fa->data = realloc(fa->data,max*sizeof(int)); + } +} + +void queue_detruire(queue* fa) { + fa->capacite = -1; + fa->debut = INT_MIN; + free(fa->data); +} + +void queue_inserer(queue* fa,int val) { + if (queue_est_pleine(*fa)) { + queue_resize(fa,fa->capacite+INCR); + } + fa->debut++; + fa->data[fa->debut] = val; +} + +int queue_extraire(queue* fa) { + int val = queue_tete(*fa); + fa->debut--; + fa->data = memmove(fa->data,fa->data+1,queue_count(*fa)*sizeof(int)); + return val; +} + diff --git a/source_codes/queues/queue_array_int.h b/source_codes/queues/queue_array_int.h new file mode 100644 index 0000000000000000000000000000000000000000..9c9c53ead2839abb4191f2180ea37b95d94ae345 --- /dev/null +++ b/source_codes/queues/queue_array_int.h @@ -0,0 +1,35 @@ +#ifndef QUEUE_ARRAY_INT_H +#define QUEUE_ARRAY_INT_H + +#include <stdbool.h> +const int INCR = 100; + +typedef struct _queue { + int* data; + int debut; //tete à l'index 0 + int capacite; +} queue; + +//Créer une nouvelle queue vide +queue queue_creer(); +//Libérer le tableau, mettre la capacité à < -1 +void queue_detruire(queue* fa); +//Inserer un élement en début de queue +void queue_inserer(queue* fa,int val); +//Extraire un élément en tête de queue +int queue_extraire(queue* fa); +//Consulter l'élément en tête de queue +int queue_tete(queue fa); +//Consulter l'élément au début de queue +int queue_debut(queue fa); +//Tester si la queue est vide +bool queue_est_vide(queue fa); +//Compter du nombre d'éléments de la queue: +int queue_count(queue fa); + +#endif + + + + + diff --git a/source_codes/queues/queue_array_int_partiel.c b/source_codes/queues/queue_array_int_partiel.c new file mode 100644 index 0000000000000000000000000000000000000000..e964c9888d71d0f2b61e73fad405545693c120c6 --- /dev/null +++ b/source_codes/queues/queue_array_int_partiel.c @@ -0,0 +1,66 @@ +#include <stdlib.h> +#include <stdbool.h> +#include <assert.h> +#include"queue_array_int.h" + +bool queue_est_valide(queue fa) { + return (fa.capacite > 0 && fa.debut >= -1); +} + +bool queue_est_vide(queue fa) { + assert(queue_est_valide(fa)); + return (-1 == fa.debut); +} + +bool queue_est_pleine(queue fa) { + // à compléter +} + +int queue_count(queue fa) { + // à compléter +} + +int queue_tete(queue fa) { + assert(!queue_est_vide(fa)); + return fa.data[0]; +} + +int queue_debut(queue fa) { + assert(!queue_est_vide(fa)); + return fa.data[fa.debut]; +} + +queue queue_creer() { + queue fa; + fa.capacite = INCR; + fa.debut = -1; + fa.data = malloc(INCR*sizeof(int)); + return fa; +} + +void queue_resize(queue* fa,int max) { + assert(queue_est_valide(*fa)); + if (max > fa->capacite) { + fa->capacite = max; + fa->data = realloc(fa->data,max*sizeof(int)); + } +} + +void queue_detruire(queue* fa) { + // à compléter +} + +void queue_inserer(queue* fa,int val) { + if (queue_est_pleine(*fa)) { + queue_resize(fa,fa->capacite+INCR); + } + fa->debut++; + fa->data[fa->debut] = val; +} + +int queue_extraire(queue* fa) { + int val = queue_tete(*fa); + // à compléter + return val; +} + diff --git a/source_codes/queues/queue_ptr_int.c b/source_codes/queues/queue_ptr_int.c new file mode 100644 index 0000000000000000000000000000000000000000..4da190888455e39e362c64988ef7c09d80b40f1e --- /dev/null +++ b/source_codes/queues/queue_ptr_int.c @@ -0,0 +1,112 @@ +#include <stdlib.h> +#include <stdio.h> +#include <stdbool.h> +#include <assert.h> +#include "queue_ptr_int.h" + + +//Creer une nouvelle queue vide +queue queue_creer() { + queue fa; + fa.tete = fa.debut = NULL; + return fa; +} + +//Inserer un élement en début de queue +void queue_inserer(queue* fa,int val) { + element* elmt = malloc(sizeof(element)); + elmt->data = val; + elmt->next = NULL; + if (queue_est_vide(*fa)) { + fa->tete = elmt; + } else { + fa->debut->next = elmt; + } + fa->debut = elmt; +} + +//Extraire un élément en tête de queue +int queue_extraire(queue* fa) { + int val = queue_tete(*fa); + element* elmt = fa->tete; + fa->tete = fa->tete->next; + free(elmt); + if (NULL == fa->tete) { + fa->debut = NULL; + } + return val; +} + +//Désallouer complètement la queue +void queue_detruire(queue* fa) { + while (!queue_est_vide(*fa)) { + int val = queue_extraire(fa); + } +} + +//Tester si la queue est vide +bool queue_est_vide(queue fa) { + return (NULL == fa.tete && NULL == fa.debut); +} + +//Consulter l'élément en tête de queue +int queue_tete(queue fa) { + assert(!queue_est_vide(fa)); + return fa.tete->data; +} + +//Consulter l'élément en début de queue +int queue_debut(queue fa) { + assert(!queue_est_vide(fa)); + return fa.debut->data; +} + +//Compter le nombre d'éléments de la queue: +int queue_count(queue fa) { + int cnt = 0; + while (NULL != fa.tete->next) { + fa.tete = fa.tete->next; + cnt++; + } + return cnt; +} + +///////////////////////////////////////////////////////// +/* +#include <stdlib.h> +#include <stdio.h> +#include <stdbool.h> +#include "fa.h" + +void print(void* a) { + int* b = (int*)a; + printf("%d ",*b); +} +int cmp(void* a,void* b) { + int* aa = (int*)a; + int* bb = (int*)b; + if (*aa == *bb) return 0; + else if (*aa < *bb) return -1; + else return 1; +} + +int main() { + + fa_Elmt* queue = fa_create(); + int a = 3; + queue = fa_push(queue,&a); + int b = 6; + queue = fa_push(queue,&b); + int c = 7; + queue = fa_push(queue,&c); + fa_process(queue,print); printf("\n"); + int d = 6; + fa_Elmt* elmt = fa_pop(queue,&d,cmp); + int* tutu = (int*)(elmt->data); + printf("%d\n",*tutu); + fa_process(queue,print); printf("\n"); + return 0; +}*/ + + + diff --git a/source_codes/queues/queue_ptr_int.h b/source_codes/queues/queue_ptr_int.h new file mode 100644 index 0000000000000000000000000000000000000000..4dd3a6cf62d3b1641a07edced7cf9333f1ada53f --- /dev/null +++ b/source_codes/queues/queue_ptr_int.h @@ -0,0 +1,37 @@ +/* pour éviter que le précompilateur inclue plusieurs fois le fichier .h */ +#ifndef QUEUE_PTR_INT_H +#define QUEUE_PTR_INT_H +#include <stdbool.h> + +/* Utilité du typedef : Element a; <=> struct Element a; */ +typedef struct _element { + int data; + struct _element* next; +} element; + +typedef struct _queue { + element* tete; + element* debut; +} queue; + +//Créer d'une nouvelle queue vide +queue queue_creer(); +//Désallouer complètement la queue +void queue_detruire(queue* fa); +//Insérer un élement en début de queue +void queue_inserer(queue* fa,int val); +//Extraire un élément de la queue +int queue_extraire(queue* fa); +//Consulter l'élément en tête de queue +int queue_tete(queue fa); +//Consulter l'élément en début de queue +int queue_debut(queue fa); +//Tester si la queue est vide +bool queue_est_vide(queue fa); +//Compter le nombre d'éléments de la queue: +int queue_count(queue fa); +#endif + + + + diff --git a/source_codes/queues/queue_ptr_int_partiel.c b/source_codes/queues/queue_ptr_int_partiel.c new file mode 100644 index 0000000000000000000000000000000000000000..41f2916747bc67b985138ea5dbfe9a85bba811e3 --- /dev/null +++ b/source_codes/queues/queue_ptr_int_partiel.c @@ -0,0 +1,68 @@ +#include <stdlib.h> +#include <stdio.h> +#include <stdbool.h> +#include <assert.h> +#include "queue_ptr_int.h" + +//Creer une nouvelle queue vide +queue queue_creer() { + queue fa; + fa.tete = fa.debut = NULL; + return fa; +} + +//Inserer un élement en début de queue +void queue_inserer(queue* fa,int val) { + element* elmt = malloc(sizeof(element)); + elmt->data = val; + elmt->next = NULL; + if (queue_est_vide(*fa)) { + fa->tete = elmt; + } else { + fa->debut->next = elmt; + } + fa->debut = elmt; +} + +//Extraire un élément en tête de queue +int queue_extraire(queue* fa) { + int val = queue_tete(*fa); + element* elmt = fa->tete; + fa->tete = fa->tete->next; + free(elmt); + if (NULL == fa->tete) { + fa->debut = NULL; + } + return val; +} + +//Désallouer complètement la queue +void queue_detruire(queue* fa) { + // à compléter +} + +//Tester si la queue est vide +bool queue_est_vide(queue fa) { + return (NULL == fa.tete && NULL == fa.debut); +} + +//Consulter l'élément en tête de queue +int queue_tete(queue fa) { + assert(!queue_est_vide(fa)); + return fa.tete->data; +} + +//Consulter l'élément en début de queue +int queue_debut(queue fa) { + assert(!queue_est_vide(fa)); + return fa.debut->data; +} + +//Compter le nombre d'éléments de la queue: +int queue_count(queue fa) { + int cnt = 0; + // à compléter + return cnt; +} + +