:: Enseignements :: ESIPE :: E3INFO :: 2015-2016 :: Algorithmique ::
![[LOGO]](http://igm.univ-mlv.fr/ens/resources/mlv.png) | Listes chaînées |
Le but de ce TP est de manipuler les listes chaînées. Nous considérons
ici des listes chaînées d'entiers (appelées parfois tout simplement des
listes) et nous enrichissons l'ensemble des fonctions vues en TD.
Les définitions de type suivantes permettent de représenter une liste
chaînée d'entiers :
typedef struct _cell {
int value; /* donnee stockee : un entier. */
struct _cell *next; /* pointeur sur la cellule suivante. */
} cell;
typedef cell *list;
Exercice 1 - Outils classiques de manipulations de listes
Implémenter les fonctions suivantes et écrire un programme
permettant de les tester. Vous traiterez les échecs éventuels des fonctions
dans la fonction principale
int main(void).
-
cell *allocate_cell(int val) qui alloue l'espace mémoire
nécessaire pour une nouvelle cellule et retourne l'adresse de cette
nouvelle cellule après avoir affecté la valeur val au champ
value et NULL au champ next.
S'il n'y a plus de place disponible, la fonction renvoie la valeur
NULL ;
-
int insert_first(List *lst, int val) qui insère la valeur
val en tête de la liste *lst.
La fonction renvoie 0 si tout s'est bien passé et -1
en cas d'échec (si elle rencontre un problème lors de l'allocation par exemple);
-
int read_list(list *lst) qui crée une liste chaînée
d'entiers non nuls saisis au clavier en les insérant successivement
en tête de liste à partir de la liste *lst. La fonction s'arrête
d'ajouter des éléments à la liste lorsqu'un entier nul (0) est saisi;
elle renvoie -1 en cas de problème et 0 sinon ;
-
void print_list(list lst) qui affiche dans l'ordre du
chaînage, les éléments de la liste lst ;
-
cell *find(list lst, int val) qui renvoie l'adresse
de la cellule contenant l'entier val. La fonction renvoie
NULL si l'entier n'est pas présent dans la liste lst ;
-
void free_list(list *lst) qui libère tout l'espace mémoire
occupé par la liste *lst.
Exercice 2 - Complément
Écrire les fonctions
-
void print_reverse_list(list lst) qui affiche dans l'ordre
inverse du chaînage, les éléments de la liste lst ;
-
int insert_after(list *lst, int new_value, int given_value)
qui insère l'entier new_value après l'entier
given_value dans la liste *lst ou en fin de liste
si given_value n'est pas présent. La fonction renvoie 0
si tout s'est bien passé et -1 en cas d'échec;
-
cell *minimum(list lst) qui renvoie l'adresse d'une
cellule contenant la valeur minimale de la liste lst.
La fonction renvoie
NULL si la liste lst est vide ;
-
void concat_lists(list *lst1, list *lst2)}
qui concatène deux listes. La fonction reçoit deux listes et
transforme la première en la concaténation des deux listes.
Cette fonction ne doit pas créer de nouvelles cellules :
elle modifie directement les listes passées en paramètres ;
-
list extract_odds(list *lst) qui extrait
de la liste *lst toutes les cellules contenant des
valeurs impaires.
Les cellules contenant des valeurs impaires ne seront pas supprimées
physiquement mais elles formeront une autre liste que la fonction
renvoie.
Par exemple, appliquée à la liste
*lst = (5, 7, 2, 1, 9, 8), la
fonction doit construire et renvoyer la nouvelle liste (5, 7, 1, 9)
et elle doit transformer *lst en (2, 8).
Exercice 3 - Visualisation (facultatif)
-
Copier le code suivant dans un fichier list.dot.
digraph list {
rankdir=LR;
cell [shape=record];
edge [tailclip=false, arrowtail=dot, dir=both];
x1 [width=0.5, label="{ <next> }"];
x1:next:c -> x2:value;
x2 [width=1.0, label="{ <value> 3 | <next> }"];
x2:next:c -> x3:value;
x3 [width=1.0, label="{ <value> 1 | <next> }"];
x3:next:c -> x4:value;
x4 [width=1.0, label="{ <value> 4 | / }"];
}
-
Taper dans un terminal dot -Tps2 list.dot > list.ps pour
construire le graphique et gv list.ps ou evince list.ps
pour le visualiser.
-
À partir de cet exemple, écrire une fonction qui prend une liste
et qui génère le code pour la visualiser avec le programme dot.
Générer le code soit dans le terminal, soit
directement dans un fichier.
-
La documentation du langage DOT.
-
Conseil : Dans l'exemple, x1, x2, ... représentent
les quatre boîtes dans le diagramme. Vous pouvez changer ces noms. Cela simplifie
des choses si vous donnez les noms en utilisant les adresses des cellules.
Par exemple, pour une cellule cell *my_cell, vous pouvez utiliser printf("x%p", my_cell)
pour générer son nom.
© Université de Marne-la-Vallée