INF121: Algorithmique et Programmation Fonctionnelle Cours 7 : Listes (suite et fin) Année 2013 - 2014 Brefs rappels sur les listes Une liste c’est : I une suite finie de valeurs de même type I contenant un nombre arbitraire d’éléments I fournis selon un ordre donné ([5, 8, 4] 6= [8, 5, 4]) Le type liste_de_t peut être défini par un type (union) récursif : I la constante Nil représente la liste vide I le constructeur Cons(e,l) représente l’ajout en tête de e à l Cons (expr1, Cons (expr2, ...Cons (exprn, Nil) ...)) → Un élément du type list_de_t est une valeur (comme une autre !) → On peut définir des listes d’entiers, booléens, réels, fonctions, etc. 1 / 10 Le type prédéfini pour les listes en Ocaml OCaml fournit un constructeur de type list prédéfini I Nil est noté I Cons est exprimé par un opérateur infixé [] :: Exemple : Listes en notation OCaml I Cons (2, Nil) correspond à 2::[ ] I Cons (4,Cons (9, Nil)) correspond à 4::(9::[ ]) Quelques raccourcis de notation : I v1::(v2::...::(vn::[ ])) peut être noté v1::v2:: ...vn::[ ] I v1::v2::... vn::[ ] peut être noté [v1;v2;...;vn] le type list_of_t devient t list DEMO : les listes en notation Ocaml 2 / 10 Retour sur le pattern-matching Rien ne bouge . . . ⇒ Même règles, même expressivité, mais une nouvelle syntaxe ensembles de valeurs attendues liste vide liste non vide liste à un seul élément liste non vide dont le premier élément est 1 (dans le cas d’une liste d’entiers) ... filtre [] _::_, _::l, e::l, e::_ e::[], _::[], [_], [e] 1::_ ... 3 / 10 Retour sur les exercices du cours précédent Avec ces nouvelles notations Pour des listes d’entiers : I somme : renvoie la somme des éléments d’une liste I appartient : indique si un élément appartient à une liste I dernier : renvoie le dernier élément d’une liste I minimum : renvoie le minimum d’une liste d’entiers I pairs : renvoie les entiers pairs d’une liste I supprime : supprime une/toutes les occurrences d’un élément I concatene : concaténation de deux listes I partition : partitionne une “liste de paires” en une “paire de listes” I est_croissante : indique si une liste est croissante DEMO : Implémentation de certaines de ces fonctions 4 / 10 D’autres exemples de fonctions sur les listes Une liste est-elle une sous-liste d’une autre ? Exemples : I [ e2 ; e4 ; e5 ] est une sous-liste de [e1 ; e2 ; e3 ; e4 ; e5 ; e6] I [ e2 ; e4 ; e5 ; e7 ] n’est pas une sous-liste de [e2 ; e3 ; e4 ; e5 ; e6] I [ e4 ; e2 ; e5 ] n’est pas une sous-liste de [e1 ; e2 ; e3 ; e4 ; e5 ; e6] Analyse : I ce predicat prend deux listes l1 et l2 en paramètre I l2 doit être obtenue en “supprimant” certains éléments de l1 Fermeture-Eclair zip: prend en paramètre un couple de liste (de même taille) et renvoie la liste des couples correspondants Exemples : I zip [1; 3; 8] [2; 9; 8] est la liste [(1,2); (3,9); (8,8)] I zip [1; 3; 8] [2] n’est pas défini . . . 5 / 10 Quelques opérateurs prédéfinis sur le type list let l1 = [3; 8; 7; 1] Description nième élément longueur tête fin inverse concaténation Opérateur List.nth List.length List.hd List.tl List.rev @ Exemple List.nth l1 2 = 7 List.length l1 = 4 List.hd l1 = 4 List.tl l1 = [8;7;1] List.rev l1 = [1;7;8;3] l1 @ [2;3] = [3; 8; 7; 1; 2; 3] Plus de détails sur caml.inria.fr/pub/docs/manual-ocaml/libref/List.html 6 / 10 Tris de listes Motivations Trier ≈ ranger les éléments d’une liste selon un ordre donné (ex., < pour int): tri liste quelconque −→ liste triée Exemple tri [2;1;9;4] −→ [1;2;4;9] I type person = Toto | Titi | Tata I [Titi;Tata;Toto] −→ [Toto;Titi;Tata] tri Motivations ? I représentation canonique du (multi-ensemble) des elts d’une liste I certains traitements seront plus efficaces I une étape nécessaire dans de nombreux algorithmes plus généraux ⇒ ∃ nombreux algorithmes de tri, qui diffèrent par : I leur efficacité (en temps d’exécution, en mémoire) I leur difficulté à programmer, à prouver 7 / 10 Tris de listes Quelques fonctions préliminaires Recherche d’un élément dans une liste triée → on peut interrompre la recherche dès que l’on “dépasse” l’élément cherché let rec appartient (e:int) (l:int list):bool= (* l est croissante *) match l with | [] → false | x::lp → e=x || (e > x) && (appartient e lp) Insérer un élément dans une liste triée (en produisant une nouvelle liste triée) let rec inserer (e:int) (l:int list):int list= (* l est croissante, le resultat est une liste croissante *) match l with | [] → [e] | x::lp → if e<x then e::l else x::(inserer e lp) 8 / 10 Deux exemples d’algorithmes de tri Tri par insertion “isoler un élément de l (la tête), trier (récursivement !) les autres éléments, et insérer l’élément isolé à sa place dans la liste résultat” Tri par sélection “construire la liste résultat par ajouts successifs (en tête) des éléments de la liste initiale l sélectionnés par ordre croissant” Indication : deux fonction auxilliaires utiles I min_list: élément minimal d’une liste I supprime: supprime la 1ère occurence d’un élément dans une liste 9 / 10 Conclusion Les listes : un type de données incontournable I Peuvent être définies explicitementt par un type union (récursif) : I constructeurs Cons et Nil I I I I En pratique : on utilise plutôt le type list de OCaml ::, [], [v1;v2;...;vn], @, . . . fonctions récursives sur les listes : I I I “first-class citizens” toutes les règles de typage s’appliquent, pattern-matching, etc. identifier et définir le(s) cas de base identifier et définir le(s) cas de récurrence 2 algorithmes de tri : tri par insertion et tri par sélection Important I Vérifiez que vous savez écrire les fonctions vues dans ce cours I Jetez un coup d’oeil aux opérateurs prédéfinis du type List . . . 10 / 10