890 likes | 1.19k Views
Structures linéaires Listes chaînées. Structures de Données. Listes. Définition Une liste est une séquence finie d’éléments Les éléments sont repérés selon leur rang Il existe une relation d’ordre sur le rang des éléments Le rang du premier élément est 1, le rang du second est 2, …
E N D
Structures linéaires Listes chaînées Structures de Données 2005/2006
Listes Définition Une liste est une séquence finie d’éléments Les éléments sont repérés selon leur rang Il existe une relation d’ordre sur le rang des éléments Le rang du premier élément est 1, le rang du second est 2, … L’ajout et la suppression d’un élément peut se faire à n’importe quel rang valide de la liste
Listes : Cellule La cellule est la composante principale d’une liste Une liste est un ensemble de cellules (éléments) chaînées entre elles à l’aide de liens Une Cellule est une structure qui comporte deux parties : Partie contenant les informations sur l’élément représenté par la cellule Un lien vers la cellule suivante
Listes : Cellule Le champ infos représente une ou plusieurs données de type quelconque Le champ suivant représente la référence de la cellule suivante Cellule infos suivant
Listes chaînée : schéma La liste vide est représentée par un trait en diagonal La dernière cellule pointe (a un lien) vers une liste vide tête infos suivant infos suivant infos suivant tête Liste vide cellule Liste chaînée
Listes Une liste est définie récursivement : Une liste est : Soit une liste vide Soit une liste avec une seule cellule liée à une liste tête contient la référence de la première cellule qui contient la référence de la cellule suivante, … En Java, null désigne la liste vide Définir une classe Cellule Définir une classe Liste
Listes : définition récursive Une liste est : Soit une liste vide Soit composée d’une cellule (la première) chaînée à une liste Cette définition est très importante, utilisée dans les opérations récursives sur les listes tête Liste vide tête infos suivant infos suivant infos suivant cellule Liste chaînée
Listes : structure d’uneCellule Données : Un champ (ou plusieurs) infos de type quelconque : primitif ou structure (objet) Un champ (suivant) référence d'une autre Cellule Opérations : setSuivant : modifie la référence suivant getSuivant : retourne la référence suivant getInfo : retourne le champ infos afficheInfo : affiche le champ Infos …
Listes : la classe Cellule classe Cellule Données: infos : typeElement suivant: Cellule Méthodes : procédure setSuivant (donnéec : Cellule) //pré-condition : //post- condition : le champ suivant est modifié //spécification : modifie le champ suivant en lui affectant le paramètre c finproc fonction getSuivant () retourneCellule //pré-condition : //post- condition : //spécification : retourne la référence du suivant finfonc
Listes : la classe Cellule fonction getInfo () retournetypeElement //pré-condition : //post- condition : //spécification : retourne la donnée infos finfonc procédure afficheInfo() //pré-condition : //post- condition : //spécification : affiche les données de la classe finproc classe Cellule Rajouter d’autres méthodes si nécessaire
Listes : structure d’une liste Données : Un champ tête de type Cellule Opérations : ajoutTete supprimeTete ListeVide : retourne vrai si la liste est vide afficheListe : affiche les éléments de la liste …
La classe Liste classe Liste Données: tete : Cellule Méthodes : //quelques opérations procédure ajoutTete(donnée c : Cellule) //pré-condition : //post- condition : une nouvelle cellule ajoutée, tête modifiée //spécification : ajoute la cellule c en tête de liste finproc procédure supprimeTete() //pré-condition : liste non vide //post- condition : une cellule supprimée, tête modifiée //spécification : supprime la cellule en tête de liste finproc
La classe Liste fonction listeVide() retournebooléen //pré-condition : //post- condition : //spécification : retourne vrai si la liste est vide, faux sinon finfonc procédure afficheListe() //pré-condition : //post- condition : //spécification : affiche les éléments de la liste finproc classe Liste Rajouter d’autres méthodes si nécessaire
Listes en Java : classe Cellule class Cellule { private typeElement infos; private Cellule suivant; public Cellule (typeElement e, Cellule c) // constructeur { infos = e; suivant = c; } public void setSuivant(Cellule c) { suivant = c; } public Cellule getSuivant() { return suivant; }
Listes en Java : classe Cellule public void setInfo(typeElement e) { infos = e; } public typeElement getInfo() { return infos; } public void afficheInfo() { System.out.println(infos); } }//class Cellule D'autres méthodes peuvent être rajoutées selon le besoin
Listes en Java : classe Cellule Accès aux champs d'une cellule : Seules les méthodes de la classe Cellule peuvent accéder aux données Cellule cel; cel infos suivant 4 cel = new Cellule(4, null); System.out.println(cel.infos); System.out.println(cel.getInfo()); cel.infos = 11; cel.setInfo(11);
La classe Liste en Java class Liste { private Cellule tete; public Liste() // constructeur { tete = null; //à sa création une liste est vide } public boolean listeVide() { return tete==null; } public void ajoutTete(typeElement e) { Cellule c = new Cellule(e, tete); tete = c; }
La classe Liste en Java public void supprimeTete() { assert (!listeVide()); tete = tete.getSuivant(); } public void afficheListe() { Cellule tmp = tete; System.out.println("affichage liste : "); while(tmp != null) { tmp.afficheInfo(); tmp = tmp.getSuivant(); } } }//class Liste D'autres méthodes peuvent être rajoutées selon le besoin
Classe Liste : ajout en tête Dans la suite : typeElement = int Ajout en tête : ajouter 3 li (tete) cel infos suivant 3 tete infos suivant 3 Liste li = new Liste(); ajoutTete(3); 2 étapes : 1) cel = new Cellule(3, tête); 2) tete = cel;
Classe Liste : ajout en tête Ajout en tête : ajouter 36 tête infos suivant 3 cel infos suivant 36 tete infos suivant infos suivant 36 3 cel = new Cellule(36, tete); tete = cel;
Classe Liste : supprime en tête supprimeTete(); tete infos suivant infos suivant 36 3 tete infos suivant infos suivant 36 3 tete = tete.getSuivant(); sera rendu au système par le ramasse-miettes
Classe Liste : supprime en tête supprimeTete(); tete infos suivant 3 tete infos suivant 3 sera rendu au système par le ramasse-miettes tete = tete.getSuivant();
Listes : manipulation Le constructeur sert à créer un objet Liste et à l’initialiser à vide (null) Les deux méthodes : ajout en tête supprime en tête sont très utiles dans beaucoup d’opérations sur les listes
Listes : exemple d'utilisation //TestListe.java, typeElement = int class TestListe { public static void main(String[]args) { Liste li = new Liste(); //création d'une liste vide System.out.println("--- test liste ---"); for(int i=1 ;i<=5; i++) li.ajoutTete(i); li.afficheListe(); li.supprimeTete(); li.afficheListe(); li.supprimeTete(); li.afficheListe(); } }//class TestListe
Listes : exemple d'utilisation Copier un tableau dans une liste chaînée : class CopieTableau { public static void main(String[]args) { int [] t = new int[10]; Liste li = new Liste(); //création d'une liste vide for(int i=0 ;i<10; i++) t[i] = i*2; for(int i=9 ;i>0; i--) li.ajoutTete(t[i]); li.afficheListe(); } }//class CopieTableau
Listes : application (Piles) Les piles peuvent être implantées à l'aide de listes chaînées Données tête (correspond à sommet) tête (sommet)
Listes : application (Piles) Méthodes : empiler : ajout en tête dépiler : supprime en tête sommet : première cellule estVide : teste si la liste est vide (pile vide) Avantage : Pas de pile pleine : pas de tailleMax à priori
Listes : application (Files d’attente) Les files peuvent être implantées à l'aide de listes chaînées Données tête : référence de la première cellule queue : référence de la dernière cellule queue tête
Listes : application (Files d’attente) Méthodes : enfiler : ajout en queue défiler : supprime en tête premier : première cellule estVide : teste si la liste est vide (file vide) Avantage : Pas de file pleine : pas de tailleMaxà priori
Listes : parcours récursif Premier parcours : dans l'ordre Traiter la cellule courante (première) Parcourir la sous-liste qui reste Ajouter 2 méthodes à la classe Liste parcoursRec(Cellule c) : méthode privée qui permet de passer d'une cellule à une autre grâce à la récursivité parcours() : qui appelle la méthode parcoursRec en lui passant la tête de la liste
Listes : parcours récursif Premier parcours : dans l'ordre private void parcoursRec(Cellule c) { if(c != null) { c.afficheInfo(); //traiter infos, ici c'est l'affichage parcoursRec(c.getSuivant()); } } public void parcours() { Cellule c = tete; parcoursRec(c); }
Listes : parcours récursif Second parcours : ordre inverse Parcourir la sous-liste (sans la première cellule) Traiter la cellule courante (première) Ajouter 2 méthodes à la classe Liste parcoursRecInv(Cellule c) : méthode privée qui permet de passer d'une cellule à une autre grâce à la récursivité parcours2() : qui appelle la méthode parcoursRecInv en lui passant la tête de la liste
Listes : parcours récursif Second parcours : ordre inverse private void parcoursRecInv(Cellule c) { if(c != null) { parcoursRecInv(c.getSuivant()); c.afficheInfo(); //traiter infos, ici c'est l'affichage } } public void parcours2() { Cellule c = tete; parcoursRecInv(c); }
Listes : parcours récursif Remarque Il est plus propre de définir les méthodes parcoursRec et parcoursRecInv comme privées en utilisant le mot-clé private. Cela veut dire que ces méthodes sont accessibles uniquement par les méthodes de la classe (notamment les méthodes parcours et parcours2) privatevoid parcourRec(Cellule c) privatevoid parcoursRecInv(Cellule c)
Listes : parcours itératif Parcours itératif : pas besoin de méthode privée Parcours dans l'ordre public void parcoursIter() { Cellule tmp = tete; while(tmp != null) { tmp.afficheInfo(); tmp = tmp.getSuivant(); } }
Listes : exercices Qu'affiche la procédure P1 P1 et P sont des méthodes dans la classe Liste On suppose que la liste contient dans l'ordre les éléments 1, 2 et 3 public void P1() { P(tete); } private void P(Cellule c){ if (c!=null) { c.afficheInfo(); P(c.getSuivant()); c.afficheInfo(); } } affichage : 1 2 3 3 2 1
Listes : exercices Qu'affiche la procédure P1 P1 et P sont des méthodes dans la classe Liste On suppose que la liste contient dans l'ordre les éléments 1, 2 et 3 public void P1() { P(tete); } private void P(Cellule c) { if (c!=null){ P(c.getSuivant()); c.afficheInfo(); P(c.getSuivant()); } } affichage : 3 2 313 2 3
Listes : quelques opérations Nombre d'occurrences d'un élément dans une liste On définit la méthode dans la classe Liste Version itérative public int nbOccurrences(int val) //typeElement = int { int nb =0; Cellule c =tete; while (c!=null){ if (val == c.getInfo()) nb++; c = c.getSuivant(); } return nb; }
Listes : quelques opérations Nombre d'occurrences d'un élément dans une liste Version récursive public int nbOccurrences(int val) //typeElement = int { return nbOcc(val, tete); } private int nbOcc (int val, Cellule c) { if (c==null) return 0; else if (val == c.getInfo()) return 1 + nbOcc(val, c.getSuivant()); else return nbOcc(val, c.getSuivant()); }
Listes : quelques opérations Accès par position : accès au kième position Données : un entier positif k et une liste Résultat : la référence de kième cellule Spécification : retourne la référence de la kièmecellule si elle existe, null sinon Exemple : k=3 adrK tête 5 d3 6 5
Listes : quelques opérations Accès par position : version itérative public Cellule adresseKieme(int k) { int i = 1; Cellule c = tete; while (c!=null && i<k) { i++; c = c.getSuivant(); } return c; }
Listes : quelques opérations Accès par position : version récursive public Cellule adresseKieme(int k) { Cellule c = tete; return adresseKiemeRec(k, c); } private Cellule adresseKiemeRec(int k, Cellule c) { if(c==null) return null; else if (k==1) return c; else return adresseKiemeRec(k-1,c.getSuivant()); }
Listes : quelques opérations Accès par valeur : accès à la cellule contenant une valeur donnée Données : une valeur val et une liste Résultat : la référence de la cellule contenant val Spécification : retourne la référence de lacellule contenant la première occurrence de val, si val n’est pas dans la liste elle retourne null Exemple : val=5 adrV tête 5 d3 6 5
Listes : quelques opérations Accès par valeur : version itérative public Cellule adresseValeur(int val) { int i = 1; Cellule c = tete; while (c != null) { if(val == c.getInfo()) return c; c = c.getSuivant(); } return null; }
Listes : quelques opérations Accès par valeur : version récursive public Cellule adresseValeur(int val) { Cellule c = tete; return adresseValeurRec(val, c); } private Cellule adresseValeurRec(int val, Cellule c) { if(c==null) return null; else if (val == c.getInfo()) return c; else return adresseValeurRec(val, c.getSuivant()); }
Listes : quelques opérations Insertion en fin de liste Données : une valeur val et une liste Résultat : une cellule contenant val insérée en fin de liste Spécification : insertion d’une valeur donnée val en fin de liste Exemple : val=11 p dernier tête 5 11 d3 6 5 p dernier tête 5 11 d3 6 5
Listes : quelques opérations Insertion en fin de liste : version itérative Calculer la référence du dernier ajouter après dernier public void ajoutFin(int val) { Cellule der = tete, p; if (der != null) while (der.getSuivant() != null) der = der.getSuivant(); if(der == null) ajoutTete(val); //cas liste vide else { p = new Cellule(val, null); der.setSuivant(p); } }
Listes : quelques opérations Insertion d’une valeur à la kième position Données : une valeur val, un entier positif valide k et une liste Résultat : une cellule contenant val insérée à la position k Spécification : insertion d’une valeur donnée val à la kième place Exemple : val=16, k=4 prec tête k-1 5 d3 6 5 p 16
Listes : quelques opérations Insertion d’une valeur à la kième position K doit être valide : 0 < k ≤ nombre d’éléments+1 version itérative Calculer la référence de la (k-1)ième cellule ajouter après la (k-1)ième cellule
Listes : quelques opérations Insertion d’une valeur à la kième position public void ajoutKieme(int val, int k) { Cellule prec, p, c; if (k==1) // cas particulier en première position ajoutTete(val); else { prec = adresseKieme(k-1); if(prec != null) { p = prec.getSuivant(); c = new Cellule(val, p); prec.setSuivant(c); } else System.out.println(" ajout impossible " ); } }