class Maillon: """Un maillon est donné par son élément et son maillon suivant à droite, éventuellement None.""" def __init__(self, élément, droite): self.élément = élément self.droite = droite def __str__(self): return str(self.élément) class Liste: "Une liste est donnée par son maillon de gauche" def __init__(self): self.maillon_gauche = None def est_vide(self): return self.maillon_gauche is None def ajout_gauche(self, élément): self.maillon_gauche = Maillon(élément, self.maillon_gauche) def extrait_gauche(self): if self.est_vide(): raise ValueError("Liste vide") élément = self.maillon_gauche.élément self.maillon_gauche = self.maillon_gauche.droite return élément def __str__(self): affichage = "Contenu : " maillon = self.maillon_gauche while maillon is not None: affichage += str(maillon) + "::" maillon = maillon.droite affichage += " fin." return affichage def ajout_droite(self, élément): if self.est_vide(): self.maillon_gauche = Maillon(élément, None) else: maillon = self.maillon_gauche while maillon.droite is not None: maillon = maillon.droite maillon.droite = Maillon(élément, None) def extrait_droite(self): if self.est_vide(): raise ValueError("Liste vide") maillon = self.maillon_gauche if maillon.droite is None: élément = maillon.élément self.maillon_gauche = None return élément précédent = maillon maillon = maillon.droite while maillon.droite is not None: précédent = maillon maillon = maillon.droite élément = maillon.élément précédent.droite = None return élément
On pose la longueur de la chaîne. La complexité des méthodes est la suivante :
ajout_gauche
: ; il suffit de modifier un maillon, et d'en ajouter un. Coût constant.extrait_gauche
: ; il suffit de modifier un maillon. Coût constant.ajout_droite
: ; il suffit de modifier un maillon, et d'en ajouter un ; mais avant cela, il faut parcourir la liste entièrement.extrait_droite
: .Si on a besoin uniquement d'une structure de pile, alors la liste chaînée est parfaitement adaptée. De plus il n'y pas de limite fixée à l'avance pour la taille de la pile. Cela fournit donc une implémentation légèrement plus lente mais bien plus flexible qu'avec un tableau. C'est aussi un peu plus technique à écrire...
Pour bénéficier d'une structure de file (ou de deque, c'est presque le même coût intellectuel), on va utiliser des listes qui mémorisent le maillon gauche et droite, (et/ou des maillons qui pointent à droite et à gauche).
On peut avoir une file en conservant correctement le maillon gauche et le maillon droite de la liste.
class Maillon: """Un maillon est donné par son élément et son maillon suivant à droite, éventuellement None.""" def __init__(self, élément, droite): self.élément = élément self.droite = droite def __str__(self): return str(self.élément) class Liste: "Une liste est donnée par son maillon de gauche, et son maillon droite" def __init__(self): self.maillon_gauche = None self.maillon_droite = None def est_vide(self): return (self.maillon_gauche is None) and (self.maillon_droite is None) def ajout_droite(self, élément): maillon = Maillon(élément, None) if self.est_vide(): self.maillon_gauche = maillon self.maillon_droite = maillon else: self.maillon_droite.droite = maillon self.maillon_droite = maillon def extrait_gauche(self): if self.est_vide(): raise ValueError("Liste vide") élément = self.maillon_gauche.élément self.maillon_gauche = self.maillon_gauche.droite if self.maillon_gauche is None: self.maillon_droite = None return élément def __str__(self): affichage = "Contenu : " maillon = self.maillon_gauche while maillon is not None: affichage += str(maillon) + "::" maillon = maillon.droite affichage += " fin." return affichage
On pose la longueur de la chaîne. La complexité des méthodes est la suivante :
ajout_gauche
: ; il suffit de modifier un maillon, et d'en ajouter un. Coût constant.extrait_droite
: ; il suffit de modifier un maillon. Coût constant.Si on a besoin de construire une classe file cette liste doublement chaînée est idéale.
On utilise des maillons qui pointent dans les deux sens.
class Maillon: """Un maillon est donné par son élément et ses maillons à gauche et à droite, éventuellement None.""" def __init__(self, gauche, élément, droite): self.gauche = gauche self.élément = élément self.droite = droite def __str__(self): return str(self.élément) class Liste: """Une liste est donnée par ses maillons de gauche et de droite.""" def __init__(self): self.maillon_gauche = None self.maillon_droite = None def est_vide(self): return (self.maillon_gauche is None) or \ (self.maillon_droite is None) def ajout_gauche(self, élément): if self.est_vide(): self.maillon_gauche = self.maillon_droite = Maillon(None, élément, None) else: self.maillon_gauche = Maillon(None, élément, self.maillon_gauche) self.maillon_gauche.droite.gauche = self.maillon_gauche def ajout_droite(self, élément): if self.est_vide(): self.maillon_gauche = self.maillon_droite = Maillon(None, élément, None) else: self.maillon_droite = Maillon(self.maillon_droite, élément, None) self.maillon_droite.gauche.droite = self.maillon_droite def extrait_droite(self): if self.est_vide(): raise ValueError("Liste vide") élément = self.maillon_droite.élément self.maillon_droite = self.maillon_droite.gauche if self.maillon_droite is not None: self.maillon_droite.droite = None return élément def extrait_gauche(self): if self.est_vide(): raise ValueError("Liste vide") élément = self.maillon_gauche.élément self.maillon_gauche = self.maillon_gauche.droite if self.maillon_gauche is not None: self.maillon_gauche.gauche = None return élément def __str__(self): affichage = "Contenu : " maillon = self.maillon_gauche while maillon is not None: affichage += str(maillon) + "::" maillon = maillon.droite affichage += " fin." return affichage
ajout_gauche
Si la liste est vide, on crée un maillon qui sera le maillon gauche et aussi droite de la liste, il ne pointe nulle part, ni à droite, ni à gauche.
Exemple où on ajoute un premier maillon avec l'élément .
Si la liste est non vide, alors :
Exemple où le maillon gauche possède l'attribut élément à . On ajoute à gauche un maillon avec .
extrait_gauche
On ne peut pas extraire, on lève une exception.
Dans ce cas, le maillon de gauche existe mais il pointe à sa droite sur le vide. En supprimant un maillon, la liste devient vide.
Dans ce cas, le maillon de gauche existe et il pointe à sa droite sur un autre maillon ; ce maillon sera le nouveau maillon gauche.
Exemple où le maillon gauche possède l'attribut élément à , et pointe vers un maillon avec .
On pose la longueur de la chaîne. La complexité des méthodes est la suivante :
ajout_gauche
: ; il suffit de modifier un maillon, et d'en ajouter un. Coût constant.extrait_gauche
: ; il suffit de modifier un maillon. Coût constant.ajout_droite
: ; il suffit de modifier un maillon, et d'en ajouter un. Coût constant.extrait_droite
: ; il suffit de modifier un maillon. Coût constant.Si on a besoin de construire une classe file ou une deque, la liste doublement chaînée est idéale. On rappelle que cette construction est utile pour les langages qui ne fournissent pas ces structures naturellement. Cette construction est aussi pédagogique.
Avec Python, en dehors de l'aspect pédagogique, on utilisera la deque fournie dans
collections
.
Donnons maintenant une motivation à vouloir créer de nouvelles structures de données toujours plus efficaces.
On aimerait une structure de donnée, où :
Les arbres binaires de recherches (ABR) seront une réponse à cette question.