File d'attente en C++

20 Nov 2021 20 Nov 2021 4807 vues ESSADDOUKI Mostafa 7 min de lecture
Introduction et syntaxe de base
1 Introduction au langage C++ 2 Entrée-sortie en C++ - cin et cout 3 Inférence de type avec le mot-clé auto en C++ 4 Classe std::string et les chaînes de caractères en C++ 5 Les structures conditionnelles (if et switch) en C++ (C++17 et C++20) 6 Les boucles en C++ (C++17 et C++20) 7 La gestion des fichiers en C++
Pointeurs et fonctions
8 Introduction aux pointeurs en C++ - Déclaration et interêts 9 Les références en C++ - déclaration et interêts 10 Les tableaux en C++ - Déclaration et interêts 11 Introduction aux fonctions en C++ 12 Passer des arguments à une fonction en C++ 13 Déclarer un paramètre const en C++ 14 Les fonctions Lambda en C++ 15 Fonctions utiles (Mathématiques et caractères) en C++
Programmation OO
16 Classes et objets en C++ 17 Spécificateurs d'accès en C++ 18 Constructeurs et destructeur d'une classe en C++ 19 Fonctions membres en C++ 20 Membres statiques d'une classe en C++ 21 Fonctions en ligne en C++ - inline 22 Fonctions et classes amies en C++ - friend 23 Surcharge des fonctions en C++ 24 Surcharge des opérateurs en C++ 25 Héritage en C++ 26 La gestion d'exceptions en C++ : déclaration, utilisation et personnalisation 27 fonctions et classes templates en C++ 28 Les nouveautés C++20 pour améliorer les templates en C++
Structures de données
29 Introduction aux structures de données 30 Les structures en C++ et la différence avec les structures en C 31 Les listes chaînées en C++ 32 Les piles en C++ 33 File d'attente en C++ 34 Arbre binaire de recherche : définition et mise en oeuvre en C++
La bibliothèque standard (STL)
35 Introduction à la bibliothèque de Template Standard STL 36 Les itérateurs en C++ - définition, déclaration et exemples 37 La classe array en C++ (bibliothèque STL) <array> 38 La classe vector de la bibliothèque STL <vector> 39 La classe deque en C++ ( Bibliothèque STL) 40 La classe list en C++ (bibliothèque STL) <list> 41 La classe stack (Pile) en C++ (bibliothèque STL) <stack> 42 La classe queue (File d'attente) en C++ (bibliothèque STL) <queue> 43 La file d'attente prioritaire (classe priority_queue) - Bibliothèque STL 44 Les ensembles en C++ (Classe set <set> - Bibliothèque STL) 45 Les dictionnaires en C++ : Classe map (Bibliothèque STL) 46 Introduction aux algorithmes de la bibliothèque STL (programmation compétitive) 47 Tri et méthodes associées en C++ - Bibliothèque STL 48 Recherche dichotomique et méthodes associées en C++ - Bibliothèque STL 49 Appliquer un prédicat ou une fonction aux éléments d'une séquence en C++ - Bibliothèque STL 50 Recherche dans une séquence et méthodes associées en C++ - Bibliothèque STL

La structure File d'attente (Queue)

Une file d'attente est une structure de données abstraite qui implémente le mécanisme FIFO (First In, First Out — premier entré, premier sorti) : l'élément inséré en premier est également supprimé en premier.

Principe FIFO Les éléments entrent par l'arrière de la file et en sortent par l'avant. Exemples courants : une file de personnes attendant le bus, une liste d'appels en attente chez un opérateur téléphonique, ou une liste de travaux en attente de traitement par un ordinateur.

File d'attente de personnes

File d'attente d'éléments

Comme la pile, une file peut être implémentée par un tableau (taille fixe) ou par une liste chaînée (taille dynamique). La figure ci-dessous illustre la structure interne d'une file chaînée avec ses deux pointeurs entete et queue.

File implémentée en liste chaînée

Opérations de base

OpérationDescription
enfiler(valeur)Ajoute un nouvel élément à la fin de la file
defiler()Retire l'élément en tête de file et libère sa mémoire
premier()Retourne la valeur de l'élément en tête sans le supprimer
taille()Retourne le nombre d'éléments dans la file
estVide()Retourne true si la file est vide, false sinon

Implémentation directe

Enfiler un élément

L'insertion se fait toujours à la fin. Sans pointeur queue, il faudrait parcourir toute la liste — complexité O(n). En maintenant un pointeur queue vers le dernier nœud, l'opération devient O(1).

Enfiler — insertion en queue

  Version naïve — O(n)

template <typename T>
void File<T>::enfiler(const T& valeur) {
    Noeud<T>* nouveau = CreerNoeud(valeur);
    if (compteur == 0) {
        entete = nouveau;
    } else {
        Noeud<T>* courant = entete;
        for (int i = 1; i < compteur; i++)
            courant = courant->suivant;
        courant->suivant = nouveau;
    }
    compteur++;
}

  Version optimisée avec pointeur queue — O(1)

template <typename T>
void File<T>::enfiler(const T& valeur) {
    Noeud<T>* nouveau = CreerNoeud(valeur);
    if (compteur == 0) {
        entete = queue = nouveau;   // 1er élément : tête et queue identiques
    } else {
        queue->suivant = nouveau;   // attacher après le dernier nœud
        queue = nouveau;            // avancer le pointeur queue
    }
    compteur++;
}
Optimisation clé Le pointeur queue évite de parcourir toute la liste à chaque insertion. C'est pourquoi la classe File maintient deux pointeurs : entete (pour défiler) et queue (pour enfiler).

Défiler l'élément en tête

La suppression se fait en tête — même principe que pour la pile.

Défiler — suppression en tête

template <typename T>
void File<T>::defiler() {
    if (compteur == 0) {
        cout << "Erreur! La file est vide." << endl;
        return;
    }
    Noeud<T>* del = entete;
    entete = entete->suivant;
    delete del;
    compteur--;
}

Fichiers complets — implémentation directe

#ifndef FILE_H
#define FILE_H

#include <iostream>
#include <cassert>
using namespace std;

template <typename T>
struct Noeud {
    T donnees;
    Noeud<T>* suivant;
};

template <typename T>
class File {
private:
    Noeud<T>* entete;
    Noeud<T>* queue;       // pointeur vers le dernier nœud
    int compteur;
    Noeud<T>* CreerNoeud(const T& valeur);

public:
    File();
    ~File();
    void enfiler(const T& valeur);
    void defiler();
    T& premier() const;
    int taille() const;
    bool estVide() const;
    void afficher() const;
};
#endif
#ifndef FILE_CPP
#define FILE_CPP

#include "file.h"

template <typename T>
File<T>::File() : entete(NULL), compteur(0) {}

template <typename T>
File<T>::~File() {
    Noeud<T>* del = entete;
    while (entete) {
        entete = entete->suivant;
        delete del;
        del = entete;
    }
}

template <typename T>
Noeud<T>* File<T>::CreerNoeud(const T& valeur) {
    Noeud<T>* temp = new Noeud<T>;
    temp->donnees = valeur;
    temp->suivant = NULL;
    return temp;
}

template <typename T>
void File<T>::enfiler(const T& valeur) {
    Noeud<T>* nouveau = CreerNoeud(valeur);
    if (compteur == 0) {
        entete = queue = nouveau;
    } else {
        queue->suivant = nouveau;
        queue = nouveau;
    }
    compteur++;
}

template <typename T>
void File<T>::defiler() {
    if (compteur == 0) { cout << "Erreur! La file est vide." << endl; return; }
    Noeud<T>* del = entete;
    entete = entete->suivant;
    delete del;
    compteur--;
}

template <typename T>
T& File<T>::premier() const {
    if (compteur == 0) { cout << "Erreur! La file est vide"; assert(false); }
    return entete->donnees;
}

template <typename T>
bool File<T>::estVide() const { return (compteur == 0); }

template <typename T>
int File<T>::taille() const { return compteur; }

template <typename T>
void File<T>::afficher() const {
    if (compteur == 0) { cout << "La file est vide!" << endl; return; }
    Noeud<T>* courant = entete;
    while (courant != 0) {
        cout << courant->donnees << endl;
        courant = courant->suivant;
    }
}
#endif

Implémentation par composition (réutilisation de la classe Liste)

Comme pour la pile, on peut réutiliser la classe Liste par composition : la file contient une liste et délègue ses opérations en mappant insertion en queue (inserer(taille(), valeur)) et suppression en tête (supprimer(0)).

#ifndef FILE_H
#define FILE_H
#include "liste.cpp"
using namespace std;

template <typename T>
class File {
private:
    Liste<T> liste;   // composition : la file contient une liste

public:
    void enfiler(const T& valeur);
    void defiler();
    T& premier() const;
    int taille() const;
    bool estVide() const;
    void afficher() const;
};
#endif
#ifndef FILE_CPP
#define FILE_CPP

#include "file.h"

template <typename T>
void File<T>::enfiler(const T& valeur) {
    liste.inserer(liste.taille(), valeur);  // insertion en dernière position
}

template <typename T>
void File<T>::defiler() {
    liste.supprimer(0);                     // suppression en tête
}

template <typename T>
T& File<T>::premier() const {
    return liste.getNoeud(0);
}

template <typename T>
bool File<T>::estVide() const {
    return (liste.taille() == 0);
}

template <typename T>
int File<T>::taille() const {
    return liste.taille();
}

template <typename T>
void File<T>::afficher() const {
    liste.afficher();
}
#endif

Programme principal

#include "file.cpp"
#include <string>

int main() {
    File<string> file;

    file.enfiler("Mostafa");
    file.enfiler("Omar");
    file.enfiler("Sara");
    file.enfiler("Mohamed");
    file.enfiler("Moneim");
    file.enfiler("Dounia");
    file.enfiler("Abdelmalek");

    cout << "Afficher la file" << endl;
    file.afficher();
    cout << '\n';

    cout << "Afficher la tete de la file" << endl;
    cout << file.premier() << endl;
    cout << '\n';

    cout << "Supprimer quelques noeuds et afficher la file" << endl;
    file.defiler();
    file.defiler();
    file.afficher();
    cout << '\n';

    cout << "Afficher la tete de la file" << endl;
    cout << file.premier() << endl;
    cout << '\n';

    cout << "Nombre de noeuds dans la file : " << file.taille();
    return 0;
}
Sortie
Afficher la file
Mostafa
Omar
Sara
Mohamed
Moneim
Dounia
Abdelmalek

Afficher la tete de la file
Mostafa

Supprimer quelques noeuds et afficher la file
Sara
Mohamed
Moneim
Dounia
Abdelmalek

Afficher la tete de la file
Sara

Nombre de noeuds dans la file : 5
CritèrePile (Stack)File (Queue)
PrincipeLIFO — dernier entré, premier sortiFIFO — premier entré, premier sorti
InsertionEn tête uniquementEn queue uniquement
SuppressionEn tête uniquementEn tête uniquement
Pointeurs nécessairesenteteentete + queue
Complexité enfiler/empilerO(1)O(1) avec pointeur queue

Discussion (0)

Soyez le premier à laisser un commentaire !

Laisser un commentaire

Votre commentaire sera visible après modération.