I21 Algorithmique et programmation II David Gross-Amblard, Joël Savelli IEM-uB 2008-2009 - GFDL 1.2 CM 8/8
Types de données et algorithmes Récursivité Algorithmes de tri Types de données 3.1 Définitions 3.2 Listes 3.3 Piles 3.4 Files i21 IEM-UB 2008-2009 GFDL 1.2
Motivation Structures de données classiques/fréquentes Structures linéaires Organisation sous forme de séquence d'éléments <e1,e2,e3...,en> ou séquence vide <> Opérations d'ajout et de suppression Selon la position d'ajout/suppression, différentes structures linéaires i21 IEM-UB 2008-2009 GFDL 1.2
Quelle structure linéaire : ajout/suppression ? N'importe quelle position : liste ex. liste d'Etudiants Ajout/suppression en tête : pile dernier arrivé-premier servi / LIFO : last in first out ex. Pile d'assiette, ferry, pile d'appel des fonctions, fonction undo Ajout en fin, suppression en tete : file premier arrivé-premier servi / FIFO : first in first out ex. file d'attente i21 IEM-UB 2008-2009 GFDL 1.2
Type de données abstrait Séparer la définition du type abstrait (les opérations disponibles) de l'implantation concrète (tableau ? etc. ) Généricité : s'applique à tout type indépendant du type des données stockées (entier, String, ...) Avant programmation orientée objet ~1972, Hoare i21 IEM-UB 2008-2009 GFDL 1.2
Type de données abstrait En programmation objet : Type abstrait : classe (abstraite) Opération : méthodes (abstraite) Implantation : classe dérivée, précisant concrètement comment sont réalisées les opérations Généricité : manipuler des Object (toute classe hérite de Object) i21 IEM-UB 2008-2009 GFDL 1.2
3.1 Les listes Opérations : ajouter un élement en position i supprimer un élément à la position i obtenir le ième élément connaître le nombre d'éléments de la liste Rq. Pas de limitation sur la taille i21 IEM-UB 2008-2009 GFDL 1.2
Type abstrait Liste (version incomplète) abstract class Liste { public abstract int getLongeur(); public abstract Object ieme(int i); public abstract void ajouter(int i,Object o); public abstract void supprimer(int i); } i21 IEM-UB 2008-2009 GFDL 1.2
Type abstrait Liste Et les erreurs ? ex. demande le ième élément, inexistant Utiliser les exceptions : class RangInvalideException extends Exception{} i21 IEM-UB 2008-2009 GFDL 1.2
Type abstrait Liste abstract class Liste { public abstract int getLongeur(); public abstract Object ieme(int i) throws RangInvalideException; public abstract void ajouter(int i,Object o) throws RangInvalideException; public abstract void supprimer(int i) throws RangInvalideException; } i21 IEM-UB 2008-2009 GFDL 1.2
Exemple d'utilisation Rq : pas de constructeur, car abstrait (sera défini à l'implantation) Exemple d'utilisation d'une liste L L.ajouter(0, ''toto''); // toto : String, hérite de Object L.ajouter(1,''tutu''); L.ajouter(2,''tata''); L.supprimer(1); L contient <''toto'',''tata''> Attention: transtypage explicite,typage dynamique String toto = (String)L.ieme(3); i21 IEM-UB 2008-2009 GFDL 1.2
Implantation des listes : tableau Première approche : utiliser un tableau d'objets, et un compteur nbElement Classe ListeTableau, hérite de Liste i21 IEM-UB 2008-2009 GFDL 1.2
Implantation des listes : tableau class ListeTableau extends Liste { private Object[] tab; private int nbElement; private final int TAILLEINITIALE=100; public ListeTableau(){ tab=new Object[TAILLEINITIALE]; nbElement=0; } ... i21 IEM-UB 2008-2009 GFDL 1.2
Implantation des listes : tableau Algorithme Ajouter en position i si en dernière position, facile si ailleurs, décaler le tableau vers la droite incrémenter le compteur nbElement (Code : sera détaillé en TD) i21 IEM-UB 2008-2009 GFDL 1.2
Implantation des listes : tableau Algorithme Supprimer en position i : si dernière position, facile si ailleurs, décaler le contenu vers la droite décrémenter le compteur nbElement Obtenir le ième élément : rendre le ième élément du tableau Indice invalide (<0 ou >nbElement) : signaler l'exception RangInvalideException i21 IEM-UB 2008-2009 GFDL 1.2
Implantation des listes : tableau Tableau plein ? Créer un nouveau tableau plus grand Y recopier le tableau existant Remplace le tableau existant Liste : structure dynamique (mieux qu'un tableau Java) ! i21 IEM-UB 2008-2009 GFDL 1.2
Implantation des listes : liste chaînée Structure également dynamique (taille variable) Formée de Noeuds liés entre eux Chaînage simple : lien d'un noeud vers le suivant Chaînage double : lien d'un noeud vers suivant et précédent Localisation de la tête (et éventuellement de la queue de liste) i21 IEM-UB 2008-2009 GFDL 1.2
Structures chaînées Structure simplement chaînée Structure doublement chaînée tête tête null 5 3 8 2 null liste vide queue tête queue tête null null null 5 5 5 null liste vide i21 IEM-UB 2008-2009 GFDL 1.2
Implantation d'un noeud / lien simple class Noeud { private Object valeur; private Noeud suivant; void setSuivant(Noeud n){suivant=n;} void setValeur(Object v){valeur=v;} Object getValeur(){return valeur;} Noeud(Object v){valeur=v;suivant=null;} Noeud(Object v,Noeud n){valeur=v;suivant=n;} Noeud suivant(){return suivant;} } i21 IEM-UB 2008-2009 GFDL 1.2
Remarque sur Noeud Type de données récursif ! Noeud contient une référence à un Noeud Fin de la chaîne des liens : lien à null i21 IEM-UB 2008-2009 GFDL 1.2
Ex. Instanciation d'une liste chaînée ''toto''->''tutu'' (String hérite de Object) Noeud n=new Noeud(''tutu''); Noeud debut=new Noeud(''toto'',n); Plus simplement : Noeud debut=new Noeud(''toto'',new Noeud(''tutu'')); i21 IEM-UB 2008-2009 GFDL 1.2
Implantation d'une liste par liste chaînée rappel : abstract class Liste { public abstract int getLongeur(); public abstract Object ieme(int i) throws RangInvalideException; public abstract void ajouter(int i,Object o) throws RangInvalideException; public abstract void supprimer(int i) throws RangInvalideException; } i21 IEM-UB 2008-2009 GFDL 1.2
Implantation d'une liste par liste chaînée Mémoriser : la tête de la liste la longueur de la liste Opération à réaliser : ième : parcourir la liste en suivant les liens ajouter : ajouter un noeud, coller les liens supprimer : couper des liens i21 IEM-UB 2008-2009 GFDL 1.2
Implantation d'une liste par liste chaînée class ListeChainée extends Liste { Noeud tete; int longueur; ListeChaînée(){ tete=null; longueur=0; } // puis code des opérations à préciser dans Liste i21 IEM-UB 2008-2009 GFDL 1.2
Implantation d'une liste par liste chaînée Algorithme ième(entier i) s'assurer que i est entre 0 et longueur-1 Noeud position, initialisée à la tête pour j allant de 0 à i-1 position=position.suivant(); // avancer dans la liste on se retrouve en ième position renvoyer position.getValeur(); i21 IEM-UB 2008-2009 GFDL 1.2
Implantation d'une liste par liste chaînée Algorithme supprimer(entier i) s'assurer que i est entre 0 et longueur-1 si i==0 (suppression en tête de liste) tete=tete.suivant(); sinon parcourir la liste, se positionner sur le ième Noeud soit courant, ième Noeud, précédent le Noeud précédent le suivant de précédent devient le suivant de courant précédent.setSuivant(courant.suivant()); décrémenter la longueur i21 IEM-UB 2008-2009 GFDL 1.2
Implantation d'une liste par liste chaînée Algorithme ajouter(entier i,Objet o) s'assurer que i est entre 0 et longueur (ajout en fin) si i==0, ajout en tête de liste tete=new Noeud(o,tete) sinon parcourir la liste, se positionner sur le ième Noeud soit courant, ième Noeud, précédent le Noeud précédent Noeud nouveau=new Noeud(o,courant); précédent.setSuivant(noeud); incrémenter la longueur i21 IEM-UB 2008-2009 GFDL 1.2
Complexité en temps ième(i): i opérations ajouter(i,o): i opérations supprimer(i,o) : i opérations O(n) pour liste de taille n dans le pire des cas Opération fréquente : ajout en fin, mauvaise performance Solution : mémoriser la tête et la queue de liste Parcours en sens inverse : O(n²) i21 IEM-UB 2008-2009 GFDL 1.2
Implantation des listes doublement chaînées Noeuds avec suivant et précédent Mémoriser la tête et la queue de liste Ajout en fin facilité Parcours en sens inverse facilité : O(n) i21 IEM-UB 2008-2009 GFDL 1.2
3.2 Les piles Opérations : obtenir une pile vide ajouter en sommet de pile lire l'objet en sommet de pile dépiler le sommet connaître le nombre d'objets dans la pile i21 IEM-UB 2008-2009 GFDL 1.2
Type abstrait Pile abstract class Pile { public abstract int getLongeur(); public abstract Object tete() throws PileVideException; public abstract void empiler(Object o); public abstract void depiler() throws PileVideException; } i21 IEM-UB 2008-2009 GFDL 1.2
Exemple d'utilisation Soit P une pile P.empiler(''toto''); P.empiler(''tutu''); P.empiler(''tata''); P.tete() renvoie ''tata'' P.depiler(); P.tete() renvoie ''tutu'' i21 IEM-UB 2008-2009 GFDL 1.2
Implantation des piles par listes Pile : utilise une Liste L Ajouter o en tête : L.ajouter(0,o) Obtenir la tête de pile : L.ième(0) Dépiler : L.supprimer(0); Choisir ListeTableau ou ListeChainée i21 IEM-UB 2008-2009 GFDL 1.2
Pile avec tableau ou liste chaînée class PileTableau extends Pile { ListeTableau L; // code des opérations, utilisant L } class PileChainée extends Pile { ListeChainee L; i21 IEM-UB 2008-2009 GFDL 1.2
Inconvénient Inconvénient : écrire 2 fois le code, alors qu'il est identique pour les deux implantations (toujours sur une Liste) Solution : classe abstraite PileAvecListe, hérite de Pile, utilise une Liste abstraite classe d'implantation : donne le type de la liste i21 IEM-UB 2008-2009 GFDL 1.2
Variante abstract class PileAvecListe extends Pile { Liste L; // code des opérations, en termes de Liste } class PileTableau extends PileAvecListe { PileTableau(){ L=new ListeTableau(); // utilisation du polymorphisme } // pas refaire le code : tout fonctionne car exprimé en terme de Liste i21 IEM-UB 2008-2009 GFDL 1.2
3.3 Les files Opérations : obtenir une file vide ajouter en queue de file connaître l'élément en tête de file supprimer en tête de file connaître le nombre d'objets dans la file i21 IEM-UB 2008-2009 GFDL 1.2
Type abstrait File abstract class File { public abstract int getLongeur(); public abstract Object tete() throws FileVideException; public abstract void ajouter(Object o); public abstract void supprimer() throws FileVideException; } i21 IEM-UB 2008-2009 GFDL 1.2
Exemple d'utilisation Soit F une file F.ajouter(''tutu''); F.ajouter(''toto''); F.ajouter(''tata''); F.tete() renvoie ''tutu'' F.supprimer(); F.tete() renvoie ''toto'' i21 IEM-UB 2008-2009 GFDL 1.2
Implantation des files par listes File : utilise une Liste L Ajouter o en queue : L.ajouter(L.longeur(),o) Obtenir la tête de file : L.ieme(0); Supprimer en tête : L.supprimer(0); Choisir ListeTableau ou ListeChainée i21 IEM-UB 2008-2009 GFDL 1.2
File avec tableau ou liste chaînée class FileTableau extends File { ListeTableau L; // code des opérations, utilisant L } class FileChainée extends File { ListeChainee L; i21 IEM-UB 2008-2009 GFDL 1.2
Inconvénient (déjà vu...) Inconvénient : écrire 2 fois le code, alors qu'il est identique (toujours sur une Liste) Solution : classe abstraite FileAvecListe, hérite de File classe d'implantation : donne le type de la liste i21 IEM-UB 2008-2009 GFDL 1.2
Solution abstract class FileAvecListe extends File { Liste L; // code des opérations } class FileTableau extends FileAvecListe { FileTableau(){ L=new ListeTableau(); // utilisation du polymorphisme } // pas refaire le code : tout fonctionne car exprimé en terme de Liste i21 IEM-UB 2008-2009 GFDL 1.2
Conclusion Structures fréquentes : listes, piles, files Présentation par types abstraits Programmation par classes abstraites, et raffinement jusqu'à implantation concrète De nombreuses autres structures pertinentes : files de priorité, dèques, arbres, forêts, graphes, tables de hachage, ... i21 IEM-UB 2008-2009 GFDL 1.2