Listes et listes chaînées
Listes : interface¶
Une liste est une structure de donnée permettant de regrouper un nombre fini de données de manière séquentielle.
Par exemple \((0, 1, \pi, 1, -6, 1, \textrm{\texttt{"Bonjour"}} )\) est une liste. De manière générale on préfère que tous les éléments d'une liste soient du même type. Par exemple tous les éléments de la liste \((3, 5, 9)\) sont des entiers.
Interface¶
On donne ci-dessous la liste des opérations que doit supporter un objet de type liste :
Fonction | Description |
---|---|
creer_vide() |
Renvoie une liste vide. |
est_vide(l) |
Teste si la liste l est vide. |
ajoute(l, e) |
Ajoute au début de la liste l l'élément e . |
tete(l) |
Renvoie le premier élément de la liste l . |
queue(l) |
Renvoie la liste constituée de tous les éléments de l sauf le premier. |
Implémentation via des listes chaînées¶
Définition et exemple d'utilisation¶
Dans cette implémentation du type liste, les éléments sont chaînés entre
eux : chaque élément de la liste est stocké dans un objet Maillon
, où
il y est accompagné de l'adresse mémoire de l'élément suivant dans la
liste.
On décide de représenter un maillon vide par l'élément None
.
1 2 3 4 5 6 |
|
Schéma¶
Avec cette implémentation, chaque élément de la liste est chaîné au suivant.
1 |
|
Cela correspond à la liste \((-4, 123)\).
Une liste est représentée par son maillon de tête. On peut alors implémenter les fonctions suivantes de l'interface.
1 2 3 4 5 |
|
Parcours récursif¶
Pour écrire une fonction f
qui prend en argument une liste l
et
résout le problème \(\mathcal{P}\) :
-
On traite le cas de base selon le contexte du problème : cela correspond souvent au cas où la liste est vide ou constituée d'un seul élément (singleton).
-
Dans le cas général :
-
On obtient récursivement une solution partielle en appliquant la fonction
f
résolvant le problème à la queue de la liste. -
On utilise la solution partielle et la tête de la liste pour répondre au problème général.
-
Décrire un algorithme récursif qui prend en argument une liste d'entiers
l
et qui renvoie une liste composée des éléments de l
rangés dans le
sens inverse.
On supposera écrite la fonction concatene
qui prend en argument deux
listes l1
et l2
et qui renvoie la liste constituée des éléments de
l1
et de l2
mis bout à bout dans cet ordre.
-
Dans le cas où la liste
l
est vide : sil = ()
alorsrenverse(l)
renvoie()
. -
Dans le cas général : par exemple si
l = (5, 7, 1, 4, 2)
.Si on note
avant = renverse(queue(l)) = (2, 4, 1, 7)
. Il suffit de concaténeravant
avec la liste singleton(5)
.Alors
reponse = concatene(avant, singleton(tete(l)))
On renvoie
renverse(l)
renvoiereponse = (2, 4, 1, 7, 5)
.
1 2 3 4 5 6 7 8 9 |
|
Parcours itératif¶
Pour écrire une fonction f
qui prend en argument une liste l
et
résout le problème \(\mathcal{P}\). On parcourt les éléments de la liste
les uns après les autres :
-
On initialise une variable
maillon_courant
qui permet d'accéder à un maillon dans la chaîne. -
Lors de chaque itération, on remplace
maillon_courant
par le prochain maillon de la chaine :maillon_courant = maillon_courant.suivant
Lors de ce parcours, on utilise les structures de données et les algorithmes adéquats pour répondre au problème posé.
Écrire une fonction renverse
qui prend en argument une liste d'entiers l
et
qui renvoie une liste composée des éléments de l
rangés dans le sens
inverse.
1 2 3 4 5 6 7 8 9 10 11 |
|
Objet mutable¶
-
Le constructeur
Maillon
construit un nouveau maillon, indépendant des autres maillons déjà créés. -
Lorsque
m
est un maillon, on accède à ses attributs viam.valeur
etm.suivant
. Si l'on affecte une nouvelle valeur à ces attributs, on modifie en place le maillonm
.
1 2 3 |
|
1 2 3 |
|
Pour le moment l'interface donnée ne permet pas de modifier un objet de
type Maillon
. On peut l'enrichir de deux nouvelles fonctions qui
permettent respectivement de modifier l'attribut valeur
et l'attribut
suivant
d'un objet de type Maillon
:
1 2 |
|
Écrire une fonction ajoute_fin
qui étant donné une liste l
et un
entier e
et qui renvoie la liste composée des éléments de l
à
laquelle on a ajouté l'élément e
.
La liste initiale ne sera pas modifiée.
1 2 3 4 5 6 7 8 9 |
|
Écrire une fonction ajoute_fin
qui prend en argument un maillon m
et un
entier e
et qui renvoie ajoute à la fin de la liste chaînée dont le premier
maillon est m
un maillon de valeur e
.
On pourra modifier des objets existant.
1 2 3 4 5 6 7 8 9 10 11 12 |
|
Encapsulation dans un objet¶
La classe Liste
ci-dessous implémente le type abstrait de données "listes non mutables", définit
par l’interface de la section 1.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
|
Il est possible d'importer toutes les fonctionnalitées de l'interface avec l'instruction :
1 |
|
Puis, on peut utiliser les objets de type Liste
via les méthodes de l'interface.
1 2 3 4 5 |
|
2 - 3 - 42 - x