Cours num´ero 5 : Les listes Introduction aux listes Les listes

Transcription

Cours num´ero 5 : Les listes Introduction aux listes Les listes
Introduction aux listes
Liste : définition
Collection ordonnée d’éléments [x1 ; ....; xn ] (au moins) accessibles l’un après l’autre de x1 jusqu’à xn .
Cours numéro 5 : Les listes
LI213 – Types et Structures de données
Exemple : dans la liste [2 ;3 ;5 ;1 ;6], on peut accéder à
Christophe Gonzales – Pierre-Henri Wuillemin
«2». À partir de «2», on peut accéder à «3», et ainsi de suite.
Licence d’Informatique – Université Paris 6
Cette définition ne présuppose rien sur la représentation
en mémoire.
En principe, pas de contrainte sur le nombre d’éléments dans
la liste.
Christophe Gonzales – Pierre-Henri Wuillemin
Les listes simplement chaı̂nées
Intérêt des listes chaı̂nées (1/2)
Définition
Définition récursive : une liste est composée d’un élément
(la tête) suivi par la liste des éléments suivants (la queue).
Illustration graphique :
x1
x2
x3
.....
xn
Les seuls opérateurs :
Un opérateur pour accéder à la tête :
car en LISP/Scheme, hd en OC AML.
Un opérateur pour accéder à la queue :
cdr en LISP/Scheme, tl en OC AML.
toujours faire un dessin indiquant comment sont chaı̂nés
les éléments.
Vous pensez pouvoir vous en passer ? OK, vous aurez des
bugs, à vous de voir....
Christophe Gonzales – Pierre-Henri Wuillemin
Cours numéro 5 : Les listes
Cours numéro 5 : Les listes
x1
x2
.....
x3
xn
Les flèches sont des pointeurs
=⇒ en mémoire, les boites ne sont pas placées les unes
à côté des autres
Avantages des listes simplement chaı̂nées
Suppression d’un élément facile et rapide : parcourir la
liste jusqu’à l’élément à supprimer puis rechaı̂ner
x1
x2
x3
.....
xn
On peut rajouter autant d’éléments que l’on veut
Utilisation d’un espace mémoire proportionnel au nombre
d’éléments (=⇒ pas de perte de mémoire)
Christophe Gonzales – Pierre-Henri Wuillemin
Cours numéro 5 : Les listes
Inconvénients des listes chaı̂nées (2/2)
x1
x2
.....
x3
Les listes doublement chaı̂nées
Définition
Similaire à une liste simplement chaı̂née sauf qu’on peut
aussi accéder au prédécesseur.
xn
Illustration graphique :
Inconvénients des listes simplement chaı̂nées
Temps d’accès aux éléments : il faut en moyenne parcourir n/2
éléments avant de trouver un élément donné.
x1
x2
x3
.....
xn
Inconvénients du double chaı̂nage par rapport au simple chaı̂nage :
Conclusion : utilisation
C’est une structure à utiliser :
1
2
chaı̂nage plus complexe à gérer (2 pointeurs au lieu d’un)
utilise plus de mémoire
quand effectue souvent des ajouts/suppressions
d’éléments,
Avantages du double chaı̂nage par rapport au simple chaı̂nage :
quand on ne sait pas a priori combien on aura d’objets xi
Christophe Gonzales – Pierre-Henri Wuillemin
Christophe Gonzales – Pierre-Henri Wuillemin
Cours numéro 5 : Les listes
Les listes circulaires
Cours numéro 5 : Les listes
bilan : comparaison avec les tableaux
Définition
Listes telles que le «dernier» élément de la liste a pour
suivant le «premier»
Illustration graphique :
x2
suppression d’un élément plus rapide : rechaı̂ner autour de
l’élément à supprimer =⇒ parcours de liste inutile
x2
x3
x1
x3
x1
xn
liste circulaire
simplement chaı̂née
xn
liste circulaire
doublement chaı̂née
liste
nb d’éléments
arbitraire
accès aux éléments lent (parcours)
insertion au début rapide
insertion en fin
lente (parcours)
insertion au milieu lente (parcours)
suppression
rapide (rechaı̂nage)
tableau
borné
rapide
lente (décalages)
rapide
lente (décalages)
lente (décalages)
Règle : Utiliser plutôt des tableaux sauf si :
on doit faire beaucoup de suppressions
Utilisation : exécution de threads (fonctions s’exécutant en
concurrence (≈ en parallèle))
Christophe Gonzales – Pierre-Henri Wuillemin
Cours numéro 5 : Les listes
on ne connaı̂t pas le nombre d’éléments maximal a priori
Christophe Gonzales – Pierre-Henri Wuillemin
Cours numéro 5 : Les listes
Listes en OC AML
Parcours d’une liste (1/2)
type ’a list d’OC AML : listes simplement chaı̂nées
La Core Library
[] = la liste vide
[6 ; 7 ; 2] = liste de 3 entiers
:: concaténation d’un élément avec une liste :
1 :: [2 ;3 ;4] = [1 ;2 ;3 ;4]
@ concaténation de listes :
[1 ;2] @ [3 ;4] = [1 ;2 ;3 ;4]
Librairie standard : le module List
hd : ’a list -> ’a : renvoie la tête de la liste
tl : ’a list -> ’a list : renvoie la queue de la
liste
Christophe Gonzales – Pierre-Henri Wuillemin
Cours numéro 5 : Les listes
# open List ;;
let rec somme liste =
if liste = [] then 0
else hd liste + somme (tl liste) ;;
#trace somme ;;
somme [5 ; 6 ; 7];;
val somme
somme <-somme <-somme <-somme <-somme -->
somme -->
somme -->
somme -->
- : int =
: int list -> int = <fun>
[5 ; 6 ; 7]
[6 ; 7]
[7]
[]
tester la fin de la récursion
0
avant l’appel récursif
7
13
18
18
Christophe Gonzales – Pierre-Henri Wuillemin
Parcours d’une liste (2/2)
Cours numéro 5 : Les listes
Parcours d’une listes
Définition d’une liste en OC AML
type ’a list = [] | ’a :: ’a list
type somme - cf. cours 6
Règle 1 : Parcourez les listes en utilisant le matching
plutôt que hd et tl
=⇒ possibilité de matching :
match liste with [] ->
liste = liste vide
match liste with x :: reste ->
Règle 2 : Profitez au maximum de la puissance du matching !
x = tête de liste
reste = queue de liste
# let rec somme liste =
match liste with
| [] -> 0
| tete :: queue -> tete + somme queue ;;
Christophe Gonzales – Pierre-Henri Wuillemin
Cours numéro 5 : Les listes
Christophe Gonzales – Pierre-Henri Wuillemin
Cours numéro 5 : Les listes
Exemple de parcours
Parcours simultané de 2 listes
Recherche du dernier élément d’une liste :
# let rec dernier liste =
match liste with
| [ x ] -> x
| tete :: queue -> dernier queue
| [] -> failwith "liste vide";;
Recherche de l’avant-dernier élément :
# let rec avant dernier liste =
match liste with
| x :: y :: [] -> x
| tete :: queue -> avant dernier queue
-> failwith "pas assez d’éléments";;
|
# let liste1 = [1 ; 2 ; 3 ; 4] and liste2 = [5 ; 6] ;;
let rec ajoute l1 l2 =
match (l1,l2) with
| l1,[] -> l1
| [],l2 -> l2
| tete1 :: queue1, tete2 ::queue2 ->
(tete1 + tete2) :: ajoute queue1 queue2 ;;
ajoute liste1 liste2;;
- : int list = [6 ; 8 ; 3 ; 4]
ajoute [1 ; 2 ; 3 ; 4] [5 ; 6]
(1 + 5) :: (ajoute [2 ; 3 ; 4] [6])
(2 + 6) :: (ajoute [3 ; 4] [])
[3 ; 4]
[6 ;
[6 ;
[8 ;
[3 ;
8 ; 3 ; 4]
8 ; 3 ; 4]
3 ; 4]
4]
Le « » filtre n’importe quel motif !
Christophe Gonzales – Pierre-Henri Wuillemin
Cours numéro 5 : Les listes
Rappel : identifiants dans le matching
# let position liste elt =
let rec recherche liste nb =
match liste with
| elt :: reste -> nb
| tete :: reste -> recherche reste (nb+1)
| [] -> failwith "élément non trouvé"
in recherche liste 0 ;;
position [1 ; 2 ; 3 ; 4] 3;;
val position : ’a list -> ’b -> int = <fun>
- : int = 0
Christophe Gonzales – Pierre-Henri Wuillemin
Cours numéro 5 : Les listes
Insertion en début de liste
# let insere debut liste elt = elt : : liste ;;
let maliste = [2 ; 3 ; 4] ;;
insere debut maliste 1;;
val insere debut : ’a list -> ’a -> ’a list = <fun>
val maliste : int list = [2 ; 3 ; 4]
- : int list = [1 ; 2 ; 3 ; 4]
Remarques :
insertion rapide (pas de parcours de liste)
ne modifie pas la liste mais retourne une nouvelle liste
éléments partagés avec maliste
Retourne 0 au lieu de 2
Rappel :
maliste
les identifiants qui apparaissent dans les motifs sont
non liés. Le filtrage les lie localement à des parties
de la valeur filtrée.
Christophe Gonzales – Pierre-Henri Wuillemin
Cours numéro 5 : Les listes
liste retournée
2
3
1
Christophe Gonzales – Pierre-Henri Wuillemin
Cours numéro 5 : Les listes
4
Insertion en fin de liste
Insertion après un élément
# let rec insere fin liste elt = match liste with
| tete :: queue -> tete :: insere fin queue elt
| [] -> [elt] ;;
let maliste = [2 ; 3 ; 4] ;;
insere fin maliste 1;;
Remarques :
# let rec insere apres liste elt after =
match liste with
| tete :: queue ->
if tete = after then after :: elt :: queue
else tete :: insere apres queue elt after
| [] -> [] ;;
insere apres [2 ; 3 ; 5 ; 6] 4 3;;
- : int list = [2 ; 3 ; 4 ; 5 ; 6]
insertion lente : parcours de liste
Remarques :
retourne une nouvelle liste
insertion lente : parcours de liste
aucun élément partagé avec maliste
retourne une nouvelle liste
maliste
liste retournée
2
3
4
2
3
4
Christophe Gonzales – Pierre-Henri Wuillemin
fin de liste partagée avec maliste
maliste
1
Cours numéro 5 : Les listes
liste
retournée
2
2
3
3
4
Christophe Gonzales – Pierre-Henri Wuillemin
Suppression en début de liste
6
5
Cours numéro 5 : Les listes
Suppression en fin de liste
# let suppression debut liste = match liste with
| tete :: queue -> queue
| [] -> [] ;;
let maliste = [1 ; 2 ; 3 ; 4] ;;
suppression debut maliste;;
# let rec suppression fin liste = match liste with
| [
] -> []
| tete :: queue -> tete :: suppression fin queue
| [] -> [] ;;
suppression fin [1 ; 2 ; 3 ; 4];;
- : int list = [1 ; 2 ; 3]
- : int list = [2 ; 3 ; 4]
Remarques :
suppression lente : parcours de liste
Remarques :
suppression rapide (pas de parcours)
retourne une nouvelle liste
ne modifie pas la liste mais retourne une liste partagée
aucun élément partagé avec maliste
maliste
1
2
3
maliste
4
liste retournée
1
2
3
1
2
3
liste retournée
Christophe Gonzales – Pierre-Henri Wuillemin
Cours numéro 5 : Les listes
Christophe Gonzales – Pierre-Henri Wuillemin
Cours numéro 5 : Les listes
4
Suppression après un élément
Fonction iter
# let rec suppr apres liste after = match liste with
| un :: deux :: queue ->
if un = after then un :: queue
else un :: suppr apres (deux :: queue) after
|
-> liste ;;
suppr apres [2 ; 3 ; 4 ; 5 ; 6] 3;;
Définition
iter : (’a -> unit) -> ’a list -> unit
iter f [a1 ; ... ; an] applique la fonction f à tour de
rôle à a1, puis a2, etc.
équivalent à (f a1 ; f a2 ; ... ; f an ; ())
- : int list = [2 ; 3 ; 5 ; 6]
Exemple
# let f x = print string
("nombre : " ˆ string of int x ˆ "\n") ;;
List.iter f [1 ; 2 ; 3 ; 4];;
Remarques :
suppression lente : parcours de liste
retourne une nouvelle liste
fin de liste partagée avec maliste
maliste
2
3
liste
retournée
2
3
Christophe Gonzales – Pierre-Henri Wuillemin
4
5
6
nombre :
nombre :
nombre :
nombre :
- : unit
Cours numéro 5 : Les listes
Fonction map
1
2
3
4
= ()
Christophe Gonzales – Pierre-Henri Wuillemin
Cours numéro 5 : Les listes
Fonction fold left
Définition
map : (’a -> ’b) -> ’a list -> ’b list
Définition
fold left : (’a -> ’b -> ’a) -> ’a -> ’b
list -> ’a
fold left f a [b1 ; ... ; bn] retourne la valeur de
l’expression f (... (f (f a b1) b2) ...) bn
f [a1 ;... ;an] retourne la liste [f a1 ;... ;f an]
Exemples
Exemples
# List.map string of int [1 ; 2 ; 3 ; 4];;
- : string list = ["1" ; "2" ; "3" ; "4"]
# let f str nb = str ˆ " " ˆ (string of int nb) ;;
List.fold left f "nombre :" [1 ; 2 ; 3 ; 4];;
- : string = "nombre : 1 2 3 4"
# let f x = x * x ;;
List.map f [1 ; 2 ; 3 ; 4];;
- : int list = [1 ; 4 ; 9 ; 16]
# let somme nb1 nb2 = nb1 + nb2 ;;
List.fold left somme 0 [1 ; 2 ; 3 ; 4] ;;
List.fold left (+) 0 [1 ; 2 ; 3 ; 4];;
10
10
Christophe Gonzales – Pierre-Henri Wuillemin
Cours numéro 5 : Les listes
Christophe Gonzales – Pierre-Henri Wuillemin
Cours numéro 5 : Les listes
Fonction fold right
Définition
fold right : (’a -> ’b -> ’b) -> ’a list ->
’b -> ’b
fold right f [a1 ; ... ; an] b retourne la valeur
de l’expression f a1 (f a2 (... (f an b) ...))
Exemple
# let f nb str = str ˆ " " ˆ (string of int nb) ;;
List.fold right f [1 ; 2 ; 3 ; 4] "nombre :";;
- : string = "nombre : 4 3 2 1"
Christophe Gonzales – Pierre-Henri Wuillemin
Cours numéro 5 : Les listes