Structures de données IFT-2000 Abder Alikacem Les listes ordonnées Programmation générique en C++ Semaine 3, suite et fin Édition Septembre 2009 Département d’informatique et de génie logiciel
Deuxième partie Retour au type abstrait liste ordonnée, implantation par: des tableaux dynamiques (lab#3) des listes simplement chaînées des listes doublement chaînées des listes circulaires (anneaux)
Les listes ordonnées Implantation dans une liste chaînée // fichier Noeud.h // déclaration de la classe Noeud #ifndef NOEUD_H #define NOEUD_H class Noeud; typedef Noeud * elem; template <typename T> class Noeud{ //Un noeud typique de la liste public: T el; //L'élément de base de la liste elem suivant; //Un pointeur vers le noeud suivant Noeud (const T& data_item, elem next_ptr = 0) : el(data_item), suivant(next_ptr) {} ~Nœud(){}; }; #endif el suivant
Les listes ordonnées Implantation dans une liste chaînée #ifndef LISTE_H #define LISTE_H #include "Noeud.h" #pragma warning( disable : 4290 ) template <typename T> class Liste { public: Liste(){debut = 0;} // constructeur ~Liste(); // destructeur Liste(const Liste&) throw(bad_alloc); // constructeur de copie void ajouter(T x, int pos) throw(range_error, bad_alloc); int taille() const; bool appartient(constT& x,) const; //Surcharge d'opérateurs Liste<T>& operator = (const Liste<T>&) throw (bad_alloc); friend ostream& operator << (ostream&, const Liste& ); private: elem debut; // Pointeur vers le dernier noeud de la liste } ; #endif Implantation dans une liste chaînée
Implantation dans une liste chaînée Une meilleure version: utilisation d’une classe interne //… template <typename T> class Liste { public: //Constructeurs Liste(){debut = 0;} // constructeur Liste(const Liste&) throw(bad_alloc); // constructeur de copie ~Liste(); // destructeur //Surcharge d'opérateurs Liste<T>& operator = (const Liste<T>&) throw (bad_alloc); private: class Noeud{ //Un noeud typique de la liste T el; //L'élément de base de la liste Noeud * suivant; //Un pointeur vers le noeud suivant Noeud (const T& data_item, Noeud * next_ptr = 0) : el(data_item), suivant(next_ptr) {} }; typedef Noeud * elem; elem debut; //Pointeur vers le premier noeud de la liste } ;
Implantation dans une liste chaînée ~Liste() // destructeur Destructeur template <typename T> Liste<T>:: ~Liste() { elem courant = debut; while(courant!=0) debut=debut->suivant; delete courant; courant=debut; }
Implantation dans une liste chaînée ajouter() // l’ajout d’élément template <typename T> void Liste<T>:: ajouter(T x, int pos) throw(range_error, bad_alloc) { elem courant; //pointeur de service pour se promener dans la liste elem nouveau; //pour l'adresse de la nouvelle structure pour entreposer x int cpt=1; //compteur de boucle //Vérification des hypothèses (préconditions) //La position if(pos<1 || pos > taille() +1) throw range_error( ..:Position d'ajout erronée"); //La mémoire nouveau = new Noeud(x); //on appelle le constructeur de la classe Noeud //suite prochaine diapositive
Implantation dans une liste chaînée ajouter() // l’ajout d’élément //Cas où l'ajout se fait en première position if(pos==1) { nouveau->suivant=debut; debut = nouveau; return ; } //Ajout dans une autre quelconque position courant = debut; //on se positionne au début de la liste chaînée while (cpt< pos - 1) courant=courant->suivant; //on passe à la structure suivante.. cpt++; //...et on compte //A: courant pointe la structure d'avant le nouvel ajout nouveau->suivant = courant->suivant; //on chaîne la nouvelle structure … courant->suivant = nouveau;//on chaîne la structure qui doit précéder …
Implantation dans une liste chaînée enleverEl() // enlever la première occurrence d’un élément template <typename T> void Liste<T>:: enleverEl(const T& x) throw(logic_error) { elem trouve = debut; elem pred; //on prend pour acquis que l'opérateur != s'applique sur x, le mieux est … while (trouve != 0 && trouve->el != x ) pred = trouve; // pour marquer le noeud prédécesseur à celui qui contient x trouve = trouve->suivant; } if (trouve== 0) throw logic_error("EnleverEl: x n'est pas dans la liste"); else { //suite prochaine diapositive
Implantation dans une liste chaînée enleverEl() // enlever la première occurrence d’un élément else { if (debut == trouve) { / x est au début de la liste debut = debut->suivant; } { // ..il est ailleur pred->suivant = trouve->suivant; // on "coupe" la structure supprimée de la liste trouve->suivant = 0; //libération de la mémoire associée à la structure supprimée delete trouve;
Implantation dans une liste chaînée Operator = () // surcharge de l’op. d’affectation template <typename T> Liste<T>& Liste<T>::operator = (const Liste<T>& source)throw(bad_alloc) { //nettoyage ... if (debut!=0) { elem temp= debut; while (debut !=0) debut = temp->suivant; delete temp; temp = debut; } //suite prochaine diapositive
Implantation dans une liste chaînée Operator = () // surcharge de l’op. d’affectation if (source.debut== 0) debut = 0; // la liste originale est vide else { //la copie try{ //copie le permier noeud debut = new Noeud(source.debut->el); // copie le reste de la liste elem nouveau = debut; for(elem temp = source.debut->suivant; temp != 0;temp = temp->suivant) { nouveau->suivant = new Noeud(temp->el); nouveau = nouveau->suivant; } }catch(exception&){ //suite dans la prochaine diapositive
Implantation dans une liste chaînée Operator = () // surcharge de l’op. d’affectation catch(exception&){ //Si on arrive ici c'est qu'il y a une erreur d'allocation //On doit donc libérer la mémoire déjà allouée elem temp= debut; while (temp!=0) { debut = temp->suivant; delete temp; temp = debut; } //On relance alors l'exception pour indiquer qu'une erreur est survenue throw; }//else return (*this);
Implantation dans une liste chaînée Operator << () // surcharge de l’op. << template <typename T> class Liste { public: //.. friend ostream& operator << (ostream& f, const Liste& l){ elem courant=l.debut; while(courant!=0) { f << courant->el << " "; courant=courant->suivant; } return f; private: } ;
Implantation dans une liste circulaire (anneau) Les listes chaînées circulaires permettent de rendre l’écriture de certains algorithmes d’une manière plus efficace. sommet . . . Cependant, il est plus intéressant d’avoir un pointeur dernier au lieu d’un pointeur sommet dernier . . .
Listes circulaires (les anneaux) template <typename T> class Liste { public: //... friend ostream& operator << (ostream& f, const Liste& l){ if(l.dernier == 0) return f; elem courant = l.dernier->suivant; while(courant!=l.dernier){ f << courant->el << " "; courant=courant->suivant; } f << l.dernier->el; return f; } private: class Noeud{ public: T el; Noeud * suivant; Noeud (const T& data_item, Noeud * next_ptr = 0) : el(data_item), suivant(next_ptr) {} }; typedef Noeud * elem; elem dernier; /*Pointeur vers le dernier noeud de la liste*/ } ;
Implantation dans une liste doublement chaînée Dans les situations où il est souvent nécessaire d’atteindre des éléments d'une chaîne qui se trouvent quelques positions avant un élément donné, on peut alors adjoindre, à chaque élément, un pointeur supplémentaire vers son prédécesseur. SommetG SommetD … Nœud typique d’une liste chaînée : Nœud typique d’une liste doublement chaînée : Info Lien PtrG Info PtrD
Implantation dans une liste doublement chaînée template <typename T> class Liste { public: //.. private: class Noeud{ //Un noeud typique de la liste T el; //L'élément de base de la liste Noeud * suivant; //Un pointeur vers le noeud suivant Noeud * precedent; //Un pointeur vers le noeud précédent Noeud (const T& data_item, Noeud * next_ptr = 0, Noeud * pred_ptr =0) : el(data_item), suivant(next_ptr), precedent(pred_ptr){} }; typedef Noeud * elem; elem sommetG; //Pointeur vers le sommet à gauche elem sommetD; //...vers le sommet droit int cpt; //cardinalité de la liste } ;
Liste doublement chaînée Ajouter un élément Ajouter N avant P : P … … N
Liste doublement chaînée Ajouter un élément Ajouter N avant P : Pprecedentsuivant = N Nprecedent = Pprecedent Nsuivant = P Pprecedent = N P … … N
Liste doublement chaînée Ajouter un élément Ajouter N avant P : Pprecedentsuivant = N Nprecedent = Pprecedent Nsuivant = P Pprecedent = N P … … N
Liste doublement chaînée Ajouter un élément Ajouter N avant P : Pprecedentsuivant = N Nprecedent = Pprecedent Nsuivant = P Pprecedent = N P … … N
Liste doublement chaînée Ajouter un élément Ajouter N avant P : Pprecedentsuivant = N Nprecedent = Pprecedent Nsuivant = P Pprecedent = N P … … N
Liste doublement chaînée Ajouter un élément Ajouter N avant P : Pprecedentsuivant = N Nprecedent = Pprecedent Nsuivant = P Pprecedent = N P … … N
Liste doublement chaînée Ajouter un élément Ajouter N avant P : Pprecedentsuivant = N Nprecedent = Pprecedent Nsuivant = P Pprecedent = N P … … N
Liste doublement chaînée Ajouter un élément Ajouter N après le sommet droit : N template <typename T> class Liste { public: //.. private: … elem sommetG; elem sommetD; int cpt; } ; P … …
Liste doublement chaînée Ajouter un élément Ajouter N après le sommet droit : sommetDsuivant = N Nprecedent = sommetD sommetD = N Nsuivant = 0 N P … …
Liste doublement chaînée Ajouter un élément Ajouter N après le sommet droit : sommetDsuivant = N Nprecedent = sommetD sommetD = N Nsuivant = 0 N P … …
Liste doublement chaînée Ajouter un élément Ajouter N après le sommet droit : sommetDsuivant = N Nprecedent = sommetD sommetD = N Nsuivant = 0 N P … …
Liste doublement chaînée Ajouter un élément Ajouter N après le sommet droit : sommetDsuivant = N Nprecedent = sommetD sommetD = N Nsuivant = 0 N P … …
Liste doublement chaînée Ajouter un élément Ajouter N après le sommet droit : sommetDsuivant = N Nprecedent = sommetD sommetD = N Nsuivant = 0 N P … …
Liste doublement chaînée Supprimer un élément Supprimer le nœud avant P … … P
Liste doublement chaînée Supprimer un élément Supprimer le nœud avant P N = Pprecedent Pprecedent = Pprecedentprecedent Pprecedentsuivant = P Nsuivant = 0 Nprecedent = 0 delete N N = 0 … … P N
Liste doublement chaînée Supprimer un élément Supprimer le nœud avant P N = Pprecedent Pprecedent = Pprecedentprecedent Pprecedentsuivant = P Nsuivant = 0 Nprecedent = 0 delete N N = 0 … … P N
Liste doublement chaînée Supprimer un élément Supprimer le nœud avant P N = Pprecedent Pprecedent = Pprecedentprecedent Pprecedentsuivant = P Nsuivant = 0 Nprecedent = 0 delete N N = 0 … … P N
Liste doublement chaînée Supprimer un élément Supprimer le nœud avant P N = Pprecedent Pprecedent = Pprecedentprecedent Pprecedentsuivant = P Nsuivant = 0 Nprecedent = 0 delete N N = 0 … … P N
Liste doublement chaînée Supprimer un élément Supprimer le nœud avant P N = Pprecedent Pprecedent = Pprecedentprecedent Pprecedentsuivant = P Nsuivant = 0 Nprecedent = 0 delete N N = 0 … … P N
Liste doublement chaînée Supprimer un élément Supprimer le nœud avant P N = Pprecedent Pprecedent = Pprecedentprecedent Pprecedentsuivant = P Nsuivant = 0 Nprecedent = 0 delete N N = 0 … … P N
Liste doublement chaînée Supprimer un élément Supprimer le nœud P … … P
Liste doublement chaînée Supprimer un élément Supprimer le nœud P Pprecedentsuivant = Psuivant Psuivantprecedent = Pprecedent Pprecedent = 0 Psuivant = 0 delete P … … P
Liste doublement chaînée Supprimer un élément Supprimer le nœud P Pprecedentsuivant = Psuivant Psuivantprecedent = Pprecedent Pprecedent = 0 Psuivant = 0 delete P … … P
Liste doublement chaînée Supprimer un élément Supprimer le nœud P Pprecedentsuivant = Psuivant Psuivantprecedent = Pprecedent Pprecedent = 0 Psuivant = 0 delete P … … P
Liste doublement chaînée Supprimer un élément Supprimer le nœud P Pprecedentsuivant = Psuivant Psuivantprecedent = Pprecedent Pprecedent = 0 Psuivant = 0 delete P … … P
Liste doublement chaînée Supprimer un élément Supprimer le nœud P Pprecedentsuivant = Psuivant Psuivantprecedent = Pprecedent Pprecedent = 0 Psuivant = 0 delete P … … P
Liste doublement chaînée template <typename T> class Liste { public: //.. private: … elem sommetG; elem sommetD; int cpt; } ; Supprimer un élément Supprimer le sommet gauche … … N
Liste doublement chaînée Supprimer un élément Supprimer le sommet gauche N = sommetG sommetG = sommetGsuivant sommetGprecedent = 0 Nsuivant = 0 delete N N = 0 … … N
Liste doublement chaînée Supprimer un élément Supprimer le sommet gauche N = sommetG sommetG = sommetGsuivant sommetGprecedent = 0 Nsuivant = 0 delete N N = 0 … … N
Liste doublement chaînée Supprimer un élément Supprimer le sommet gauche N = sommetG sommetG = sommetGsuivant sommetGprecedent = 0 Nsuivant = 0 delete N N = 0 … … N
Liste doublement chaînée Supprimer un élément Supprimer le sommet gauche N = sommetG sommetG = sommetGsuivant sommetGprecedent = 0 Nsuivant = 0 delete N N = 0 … … N
Liste doublement chaînée Supprimer un élément Supprimer le sommet gauche N = sommetG sommetG = sommetGsuivant sommetGprecedent = 0 Nsuivant = 0 delete N N = 0 … … N
Comparaison des implantations de la liste Liste avec tableau: 1. Insertion et suppression sont en O(n). 2. Accès direct est en O(1). 3. Tout l’espace est alloué à l’avance. 4. Pas d’espace autre que les valeurs. Liste dans une liste chaînée: 1. Insertion et suppression sont en O(1). 2. Accès direct est en O(n). 3. L’espace augmente avec la liste. 4. Chaque élément requiert de l’espace pour les pointeurs
Éléments du C++ à consulter Semaine 1 Du C au C++ Les entrées/sorties (important pour cette semaine) Semaine 2 Concepts orientés objet Classe et objet L'espace de nommage Les types vector et string Semaine 3 Programmation générique (template) La gestion des exceptions
Éléments du C++ à maîtriser Les éléments syntaxiques nouveaux par rapport au langage C déclaration et initialisation de variables le type bool, l’attribut const surcharge de fonctions et arguments par défaut transtypage, espace de nommage et opérateur de résolution de portée Notion de classe, constructeurs, destructeur les attributs de masquage Constructeur de copie et surcharge de l'op. = (minimum exigé dans une classe) Les attributs et méthodes d'une classe: friend, static, const La généricité (template)
Le point sur les normes de programmation Commentaires d’interface Commentaires d’implémentation Découpage logique d’un programme La gestion des exceptions Style de programmation Voir sur le site Web du cours, section Documentations/Normes de programmation: NormesProgrammation.pdf Resume.h (à propos des commentaires Doxygen)
Gestion des exceptions #include <stdexcept> Nom de la classe Catégorie Description domain_error logique Lancée s'il se produit une erreur de domaine mathématique. invalid_argument logique Lancée si un des arguments d'une fonction est invalide. length_error logique Lancée si un objet aura une taille invalide. out_of_range logique Lancée si il y a une erreur avec un indice. logic_error logique Lancée lors de n'importe quel autre problème de logique du programme.
Résumé des balises de Doxygen En-tête de fichiers /** * \file Liste.cpp * \brief Le code des opérateurs de la liste. * \author Abder * \version 0.1 * \date septembre 2009 * * Implémentation de la classe générique Liste. */ L'interface ... /** * \brief * * \pre * \post * \exception */ Implémentation ... /** * \fn * * \param[in] * \param[out] * \return Section Documentations/Normes de programmation: Resume.h (à propos des commentaires Doxygen)
Spécifications « C++ » (version Doxygen) template <typename T> class Liste{ public://L'interface ... /** * \brief Ajouter un nouvel élément dans la liste * * \pre il y a assez de mémoire pour ajouter l'élément x * \pre la position d'ajout, pos, est comprise entre 1 et |L|+1 * \post la liste comprend un élément de plus * \post la liste est inchangée sinon * \exception range_error si la position est erronée * \exception length_error si pas assez de mémoire */ void ajouter(T x, int pos) throw(range_error, length_error); private: ...//Modèle d'implantation }; Fichier Liste.h
Commentaires d’implémentation (version Doxygen) /** * \fn void Liste<T>:: ajouter (T x, int pos) * * \param[in] x Élément à ajouter * \param[in] pos Position où insérer l'élément */ template <typename T> void Liste<T>::ajouter (T x, int pos) throw(out_of_range, length_error) {
Structures de données IFT-2000 Abder Alikacem Les structures de piles et de files Semaine 4 Édition Septembre 2009 Département d’informatique et de génie logiciel
Première partie: les piles Introduction et exemples d’application Description en terme de type abstrait Implantation Piles : LIFO : last in, first out DAPS : dernier arrivé, premier sorti in out pile
Piles Les primitives de manipulation ajouter un nouvel élément sur la pile (empiler, push) enlever un élément de la pile (dépiler, pop) regarder le premier élément de la pile (sommet, top) indiquer si la pile est vide regarder si un élément est sur la pile (examiner, peep) remplacer un élément sur la pile (changer, change) Préoccupation de la programmation par objet initialiser une pile (constructeurs); détruire une pile de ses éléments (destructeur); Constructeur de copie; Surcharge de l’opérateur = pile
La classe Pile template <typename T> class Pile { public: // constructeurs et destructeurs Pile(); //constructeur Pile(const Pile&) throw(bad_alloc); //constructeur copie ~Pile(); //destructeur // Modificateurs void empiler(T) throw (bad_alloc); T depiler() throw(logic_error); //Sélecteurs bool estVide(); int taille(); T& sommet() throw (logic_error); // élément au sommet //surcharge d'opérateurs Pile<T>& operator = (const Pile<T>&) throw (bad_alloc); friend ostream& operator << (ostream& , const Pile& ); private: … //Modèle d’implantation };
Piles : implantation dans un tableau Implantation dans un tableau dynamique template <typename T, int MAX = 100 > class Pile { public: Pile(const int max = MAX) throw (bad_alloc); // constructeur ... ~Pile (); // destructeur private : T* tab; int sommet; int tailleMax; };
Piles : implantation dans un tableau Constructeur template <Typename T> Pile<T> :: Pile (int max) throw (bad_alloc){ tab = new T [max]; sommet = -1; tailleMax =max; } Destructeur template <class T> Pile<T> :: ~Pile (void) { if (tab!=0) delete [ ] tab; }
Piles : implantation dans un tableau dépiler template <typename T> T Pile<T> :: depiler(void) throw (logic_error){ if (!estVide()) return tab[sommet--]; else throw logic_error("Depiler: la pile est vide!"); } Sélecteur : vide template <typename T> bool Pile<T> :: estVide (void){ return (sommet == -1); }
Piles : implantation dans un tableau template <typename T> void Pile<T> :: empiler(const T& e) throw (length_error){ if (sommet+1 < tailleMax) { sommet ++; tab[sommet] = e; } else throw length_error("Empiler:la pile est pleine\n"); } empiler Remarque : on suppose que l ’opérateur d ’affectation existe ou est surchargé dans la classe qui correspond au paramètre T. => intérêt de la surcharge des opérateurs
Piles : implantation dans un tableau Surcharge de l’op. = template <typename T> Pile<T>& Pile<T> :: operator = (const Pile<T>& p) { if (tab!=0) delete [ ] tab; //on nettoie this tab=new T [p. tailleMax]; tailleMax =p.tailleMax; for (int i=0; i< tailleMax;i++) tab[i]=p.tab[i]; sommet=p.sommet; return (*this); //retourner : une référence sur l ’objet courant }
Piles : implantation dans un tableau Constructeur de copie template <typename T> Pile<T> :: Pile (const Pile<T>& p) { tab=new X [p. tailleMax]; tailleMax =p. tailleMax; for (int i=0; i< tailleMax;i+=1) tab[i]=p.tab[i]; sommet=p.sommet; }
Piles : implantation dans une liste chaînée Version 1 template <typename T> class Noeud{ public: Noeud (const T& data_item, Noeud * next_ptr = 0) : el(data_item), suivant(next_ptr) {}//constructeur ~Noeud () {}; //destructeur qui ne fait rien }; friend class Pile <T>; private : T el; Noeud<T> * suivant;
Piles : implantation dans une liste chaînée template <typename T> class Pile { public: Pile (); // Constructeur Pile (const pile<X>&) throw (bad_alloc); // Constructeur par copie ~Pile (); // Destructeur Pile<T>& operator=(const Pile<T>& P); // P1 = P void empiler (const T& a) throw (bad_alloc); T depiler () throw (logic_error); T& sommet (void) throw (logic_error); // sélecteur : valeur //placée au sommet bool vide(); //sélecteur : est vide? }; Version 1 private : Noeud<T>* sommet; // pointeur sur le sommet de la pile int cpt; // Nombre d'élements de la pile void detruire (); //Méthode privée utile pour le destructeur // et l’op. =
Piles : implantation dans une liste chaînée template <typename T> class Pile { public: Pile (); Pile (const Pile<T>&) throw (bad_alloc); ~Pile (); Pile<T>& operator=(const Pile<T>& P); //.. private: class Noeud{ public: T el; Noeud * suivant; Noeud (const T& data_item, Noeud * next_ptr = 0) : el(data_item), suivant(next_ptr) {} }; Noeud * sommet; //sommet de la pile int cpt; void detruire (); Version 2 Class Nœud interne
Piles : implantation dans une liste chaînée destructeur constructeur template <class X> Pile<X>:: ~Pile() { if (sommet != 0) detruire( );} template <typename T> Pile<T>::Pile () { sommet =0; cpt = 0; } template <typename T> void Pile<T>::detruire () { Noeud<T>* p; while (sommet != 0){ p=sommet->suivant; delete sommet; sommet=p; }
Les piles Comparaison des 2 implantations Toutes les implantations des opérations d’une pile utilisant un tableau ou une liste chaînée prennent un temps constant i.e. en O(1). Par conséquent, d’un point de vue d’efficacité, aucune des deux implantations n’est mieux que l’autre. D’un point de vue de complexité spatiale, le tableau doit déclarer une taille fixe initialement. Une partie de cet espace est perdue quand la pile n’est pas bien remplie. La liste peut augmenter ou rapetisser au besoin mais demande un extra espace pour mémoriser les adresses des pointeurs.
Deuxième partie: les files Introduction et exemples d’application Description en terme de type abstrait Implantation Files : FIFO : first in, first out PAPS : premier arrivé, premier sorti out in file
Files Primitives de manipulation: ajouter un nouvel élément dans la file (enfiler); ôter l'élément le plus ancien de la file (défiler); indiquer si la file d'attente est vide; retourner le premier et dernier élément; Préoccupation de la programmation par objet initialiser une file (constructeurs); détruire une file de ses éléments (destructeur); Constructeur de copie; Surcharge de l’opérateur = in file
La classe File template<typename T> class File { public: // constructeurs et destructeurs: File() throw(bad_alloc); //constructeur File(const File &) throw(bad_alloc); //constructeur copie ~File(); // modificateurs void enfiler(T) throw (length_error); T defiler() throw(logic_error); // sélecteurs int taille() { return cpt;} bool estVide() { return cpt==0; } bool estPleine() { return cpt==TailleMax; } T& premier() throw (logic_error); // élément en tête de la file T& dernier() throw (logic_error); // élément en queue de la file // surcharges d'opérateurs File<T>& operator = (const File<T>&) throw (bad_alloc); friend ostream& operator << (ostream& f, const File& q); private: // ...Modèle d'implantation };
Implantation par tableau circulaire V i d e T ê t e Q u e u e P a u l I n s é r e r ' P a u l ' T Q P a u l R e n é I n s é r e r ' R e n é ' T Q P a u l R e n é M a r c I n s é r e r ' M a r c ' T Q R e n é M a r c E x t r a i r e ' P a u l ' T Q M a r c E x t r a i r e ' R e n é ' T Q M a r c J e a n I n s é r e r ' J e a n ' T Q M a r c J e a n A n n e I n s é r e r ' A n n e ' T Q M a r c J e a n A n n e I n s é r e r ' R o b e r t ' T Q D é b o r d e m e n t
Implantation: liste circulaire q = (q + 1) modulo MAXELT
Files: implantation dans un tableau Implantation dans un tableau dynamique template <typename T, int MAX = 100 > class File { public: File(const int max = MAX) throw (bad_alloc); // constructeur ... ~File (); // destructeur private : T* tab; int tete; int queue; int tailleMax; int cpt; }; Tableau tab réservé dans le tas Constructeur avec un paramètre : taille maximum
Files: implantation dans un tableau Constructeur template <Typename T> File<T> :: File (int max) throw (bad_alloc){ tab = new T [max]; tete = 0; queue = 0; cpt = 0; tailleMax =max; } Destructeur template <class X> File<X> :: ~File (void) { if (tab!=0) delete [ ] tab; }
Files: implantation dans un tableau défiler template <typename T> T File<T> :: defiler() throw (logic_error){ if (cpt!=0) { T elementaDefiler = tab[tete]; tete = (tete+1)% tailleMax; cpt--; return elementaDefiler; } else throw logic_error("Defiler: la file est vide!");
Files: implantation dans un tableau enfiler template <typename T> T File<T> :: enfiler(const T& e) throw (length_error){ if(cpt<tailleMax) { tab[queue]= e; queue = (queue+1)%tailleMax; cpt++; } else throw length_error(« Enfiler: la file est pleine!");
Files: implantation par listes template <typename T> class File { public: File (); File (const File<T>&) throw (bad_alloc); ~File (); File<T>& operator=(const File<T>& P); //.. private: class Noeud{ public: T el; Noeud * suivant; Noeud (const T& data_item, Noeud * next_ptr = 0) : el(data_item), suivant(next_ptr) {} }; typedef Noeud * elem; elem tete; // pointeur sur la tête de la file eleme queue; // Pointeur en queue de file int cpt; // cardinalité de la file Implantation dans une liste chaînée
Files: implantation par listes destructeur constructeur template <class X> File<X>:: ~File() { if (tete != 0) Noeud<T>* p; while (tete != 0){ p=tete->suivant; delete tete; tete=p; } template <typename T> Pile<T>::Pile () { tete =0; queue = 0; cpt = 0; }
Files prioritaires 1 4 4 8 1 1 1 4 4 8 file file Gestion d’une seule file insertion se fait selon la priorité éléments toujours triés selon leur priorité 1 4 4 8 1 1 1 4 4 8 in in file file
Laboratoire #4 (suite du lab#3) Implantation d’une liste ordonnée Nous vous fournissons 3 packetages, un par projet/implantation que vous devez faire: tableau dynamique (Lab#3) liste doublement chaînée liste circulaire Dans chacun d'eux, vous devez compléter le fichier .inl étant donné le modèle d'implantation décrit dans la partie privée de la classe Liste. Bien entendu, les 3 implantations demandées doivent être génériques. Ces 2 main() fournis sont pour tester les 3 packetages (séparément), un main() pour instancier une liste ordonnée d'entiers et un autre pour déclarer une liste d'objets définis dans la classe ClasseTests.h que nous vous fournissons également.