TD13. Listes doublement chaînées
Le sujet de ce TD est disponible au format pdf ici.
L'objectif de ce TD est de créer une liste doublement chaînée et de réfléchir à l'implémentation et à la complexité temporelle de différentes opérations sur ce type de listes chaînées.
Exercice 1 : listes doublement chaînées
On travaille donc aujourd'hui sur les listes doublement chaînées. Dans une liste doublement chaînée, chaque cellule contient deux références : une vers la cellule suivante et une vers la cellule précédente.
L'image ci dessous est la liste doublement chaînée 3 --> 2 --> 1
dessinée par le module traceur
à l'aide de l'option deeply=False
pour simplifier le dessin.
Cette option permet de ne pas dessiner les instances "primitives" (entiers, flottants, chaînes de caractères et None
) comme des objets à part entière mais de les imbriquer dans les instances les contenant.
Ceci n'est pas la réalité de ce qu'il se passe dans l'interpréteur.
Si vous n'êtes pas encore à l'aise avec les dessins conformes à la réalité que nous avons vus jusqu'à présent, il est déconseillé d'utiliser l'option deeply=False
.
Comme l'illustre l'image ci-dessus, le type ListeDoublementChainee
est le même que le type ListeSimplementChainee
manipulé jusque là, c'est à dire avec une référence vers la tête de liste et une autre vers la queue.
Le type Cellule
devient par contre le suivant :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
Question 1
Écrire les fonctions d'ajout d’éléments, de prototypes
ajoute_en_tete(liste_chainee, valeur)
et ajoute_en_queue(liste_chainee, valeur)
Dans ce TD, ces fonctions seront les deux seules créant des cellules. Quelle est la complexité temporelle de chacune de ces deux fonctions ?
Question 2
Programmer un générateur renvoyant un itérateur sur toutes les cellules de la liste de la tête à la queue. Il devra être résistant aux modifications sur la cellule courante.
Question 3
Programmer un générateur renvoyant un itérateur sur toutes les cellules de la liste de la queue à la tête. Il devra être résistant aux modifications sur la cellule courante. Serait-ce aussi simple avec une liste simplement chaînée ?
Question 4
En utilisant filter
, next
, et le générateur sur les cellules, programmer une fonction renvoyant la première cellule contenant la valeur donnée ou None
si la valeur n'est pas présente dans la liste.
Le prototype de cette fonction est recherche(liste_chainee, valeur)
.
La documentation de next
et de filter
est donnée ci-dessous.
1 2 3 4 5 6 7 |
|
Question 5
Programmer une fonction :
enleve_cellule(liste_chainee, cellule)
enlevant la cellule donnée, qui fait partie de la liste.
Quelle est sa complexité temporelle ?
Question 6
En supposant que notre liste soit de longueur ≥ 2 et contienne des entiers, proposer une fonction
renvoyant un des couples d'entiers les plus proches de la liste, de prototype : recupere_entiers_proches(liste_chainee)
Si le cœur nous en dit, on pourra utiliser itertools.combinations
dont la documentation est donnée ci-dessous.
Quelle est la complexité temporelle de la fonction recupere_entiers_proches
?
1 2 3 |
|
Question 7
Écrire une fonction supprime_doublons(liste_chainee)
, éliminant tous les doublons de la liste.
Exercice 2 : j'entrelace (pour aller plus loin)
Question 1
Écrire une fonction entrelace(liste_chainee_1, liste_chainee_2)
qui entrelace les deux listes chaînées dans liste_chainee_1
.
Par exemple, entrelace 0 --> 2 --> 4 --> 6 --> 8 --> 10 --> 12
et 1 --> 3 --> 5 --> 7 --> 9
donne 0 --> 1 --> 2 --> 3 --> 4 --> 5 --> 6 --> 7 --> 8 --> 9 --> 10 --> 12
.
On supposera qu’aucune liste n’est vide.
En sortie, liste_chainee_2
doit être vide.