Collections Séquence Conteneurs de données avec différents protocoles d’accès • Collection d’objets placés selon un ordre. • Chaque objet possède une position. • On place et enlève les éléments selon leur position. Séquences Listes binaires Ensembles et multi-ensembles / itérateurs Séquences et chaines (de caractères) ? • même structure : <a 1 , a2, …, an > , {1 → a1 , 2 → a2 , …, n → a n} Fonctions / associations Piles / récursivité • opérations différentes Files / simulation, coopération – chaines : recherche de sous-chaines, comparaison lexicale. – séquences : recherche d’un élément • Vue externe (opérations, définition abstraite) • Techniques d’implémentations (performances) G. Falquet, CUI, Université de Genève 1 de 26 G. Falquet, CUI, Université de Genève 2. Spécification algébrique - opérations 2 de 26 Axiomes Constructeurs vide crée une séquence vide longueur(vide) == 0 inserer(e, i, s) insère un élément e à la position i dans s supprimer(i, s) supprime l’élément à la position i longueur(inserer(e, i, s) == longueur(s)+1 remplacer(e, i, s) remplace l’élément à la position i par e longueur(supprimer(i, s) == longueur(s)–1; element(i, s) l’élément à la position i dans s supprimer(i, inserer(e, i, s) == s; indice(f, s) position du premier élément égal à f indice-apres(f, d, s) position du premier élément égal à f après la position d longueur(s) nombre d’éléments dans s Sélecteurs G. Falquet, CUI, Université de Genève 3 de 26 G. Falquet, CUI, Université de Genève 4 de 26 Axiomes - insertion/suppression/élément Opération indice j < i ⇒ element(j, inserer(e, i, s) == element(j, s) indice(e, vide) == –1 i = j ⇒ element(j, inserer(e, i, s) == e element(0, s) = e ⇒ indice(e, s) == 0 j > i ⇒ element(j, inserer(e, i, s) == element(j–1, s) element(0, s) ≠ e ⇒ indice(e, s) == indice(e, supprimer(0, s))+1 j < i ⇒ element(j, supprimer(i, s)) == element(j, s) j ≥ i ⇒ element(j, supprimer(i, s)) == element(j+1, s) G. Falquet, CUI, Université de Genève 5 de 26 G. Falquet, CUI, Université de Genève Utilisation des séquences 6 de 26 Implémentation Données de taille variable (≠ Tableaux) • Tableaux extensibles (c.f. chaînes de caractères) • Listes liées • Itérateurs Données dont l’ordre est signifiant • texte = séquence de mots • historique = séquence d’évènements • … ** Eviter d’utiliser les séquences quand il n’y a pas d’ordre sous-jacent (utiliser Ensemble et Multi-ensemble) ** Les implémentations ont des performances très variées pour les diverses opérations G. Falquet, CUI, Université de Genève 7 de 26 G. Falquet, CUI, Université de Genève 8 de 26 Implémentation par tableaux extensibles Performances type ListeTableau = (longueur : Entier, elements : Tableau) procedure extension (L : ListeTableau) nt := nouveau Tableau[2 * longueur] nt[0 .. longueur–1] := L.elements[0 .. longueur–1] L.elements := nt; vide O(1) inserer(e, i, s) O(n – i) , (décaler n–i éléments) environ O(1) si on insère à la fin supprimer(i, s) O(n – i) , (décaler n–i éléments) environ O(1) si on suppr ime à la fin remplacer(e, i, s) O(1) On devra étendre le tableau t fois, element(i, s) indice(f, s) O(1) O(n) nombre d’éléments à copier lors des extensions : 1, 2, 4, …, 2t = (2t+1 -1). indice-apres(f, d, s) O(n – d) longueur(s) O(1) 2t opérations insérer(). nombre moyen de recopies par opération : (2t+1 -1)/2t = 2 – 1/2 t. quasiment constant = 2. G. Falquet, CUI, Université de Genève 9 de 26 G. Falquet, CUI, Université de Genève Listes liées Opérations • ensemble de noeuds, • contiennent chacun un élément et sont liés les uns aux autres pour former une liste. • un noeud ne peut appartenir qu’à une seule liste. insererDebut (L, e) nn ← nouveau Noeud() nn.contenu ← e nn.suivant ← premier L.premier ← nn L.longueur ← L.longueur+1} type Noeud = (element : T, suivant : référence Noeud) type ListeLiee = (debut : Noeud, longueur : Entier) ListeLiée suivant suivant Noeud Noeud suivant G. Falquet, CUI, Université de Genève element (L, i) { n ← L . premier; pour j de 1 à i–1 { n retourner n . contenu suivant suivant Noeud e +1 supprimerDebut (L) { précondition: L.premier ≠ nul L.premier ← L.premier.suivant L.longueur ← L.longueur–1 } contenu debut longueur : 4 10 de 26 Noeud Noeud 11 de 26 G. Falquet, CUI, Université de Genève ← n . suivant } 12 de 26 Complexités vide O(1) inserer(e, i, s) O(i) supprimer(i, s) O(i) remplacer(e, i, s) O(i) element(i, s) O(i) indice(f, s) O(n) indice-apres(f, d, s) O(n – d) longueur(s) O(1) Itérateurs • curseur se déplaçant sur la liste. • mémoriser une position • effectuer des opérations d’insertion ou de suppression. Implémentation d’un itérateur sur une liste liée type Itérateu = (liste : ListeLiee, position : Noeud) début pour i de 1 à n s.inserer(e, i) ListeLiéée liste position Complexité quadratique ! Origine de la complexité : aller jusqu’au noeud i Itérateur G. Falquet, CUI, Université de Genève 13 de 26 G. Falquet, CUI, Université de Genève Opérations du type Itérateur Opérations (suite) insererApres (I, e ) PRE: I.position ≠ nul nn ← nouveau Noeud() nn.contenu ← e nn.suivant ← I.position.suivant I.position.suivant ← nn initialiser (I, L) I.position ← L.premier I.liste ← L avancer (I) PRE: I.position ≠ nul I.position ← position.suivant supprimerApres (I) PRE: I.position ≠ nul et I.position.suivant ≠ nul I.position.suivant ← I.position.suivant.suivant courant (I) PRE: I.position ≠ nul retourner I.position.contenu remplacer (I, e) I.position.contenu G. Falquet, CUI, Université de Genève 14 de 26 ←e 15 de 26 G. Falquet, CUI, Université de Genève 16 de 26 Exemple Listes “binaires” Une liste s de nombres entiers, on veut multiplier par 12 chaque élément de la liste. Définition récursive (polylithique) Méthode directe (quadratique) une liste est • soit vide • soit composée d’un élément (tête) et d’une liste (reste) pour i de 1 à s.longeur() { x := s.element(i); s.remplacer(12*x, i) } t r Avec un itérateur (linéaire) iter := nouveau Itérateur; iter.initialiser(s); pour i de 1 à s.longueur() { iter.remplacer(12*iter.courant()); iter.avancer() } G. Falquet, CUI, Université de Genève 17 de 26 G. Falquet, CUI, Université de Genève Représentation d’une séquence 18 de 26 Une séquence imbriquée Un élément est soit un atome (valeur simple), soit une liste <a, c, d, g, k> = <a, <c, d>, g> = a a c d g c g d k G. Falquet, CUI, Université de Genève () () () 19 de 26 G. Falquet, CUI, Université de Genève 20 de 26 Une spécification algébrique AXIOMES vide : → liste; cons : elem, liste → liste; [1] tete(cons(E, L)) == E; [2] reste(cons(E, L)) == L; cons [3] est-vide(vide) == vrai; elem [4] est-vide(cons(E, L)) == faux; elem tete : liste → elem; reste : liste → liste; est-vide : liste → bool; element : elem, liste → bool; position : elem, liste → nat; G. Falquet, CUI, Université de Genève 21 de 26 Traitements récursifs procédure AJOUTE_FIN(Liste u, Element e) si est-vide(u) retourne cons(e, vide) sinon retourne cons(tete(u), AJOUTE_FIN (reste(u), e) SOMME (reste(u)) procédure APPLIQUE_F(Liste u) si est-vide(u) retourne vide sinon retourne cons(F(tete(u), 22 de 26 Algorithmes pour les séquences Ce type de liste est bien adapté aux traitements récursifs procédure SOMME(Liste u) si est-vide(u) retourne 0 sinon retourne tete(u) + G. Falquet, CUI, Université de Genève procédure INSERTION(Liste u, Element e, Entier i) si i = 0 retourne cons(e, u) sinon retourne cons(tete(u), INSERTION (reste(u), e, i-1) APPLIQUE_F (reste(u))) procédure CONCATENATION(u, v) si est-vide(v) retourne u sinon retourne CONCATENATION (AJOUTE_FIN(u, tete(v)), reste(v)) procédure INVERSION(Liste u) retourne Liste v si est-vide(u) retourne vide sinon retourne AJOUTE_FIN( INVERSION (reste(u), tete(u))) G. Falquet, CUI, Université de Genève 23 de 26 G. Falquet, CUI, Université de Genève 24 de 26 Listes et LISP (Meta)Lisp En LISP la liste sert à représenter • les données Les expressions sont des données et • les expressions d’une programme => écrire facilement des programmes qui construisent des programmes (métaprogrammes). => traiter les programmes comme des données. (opérateur argument-1 argument-2 …) (define a (define x (eval a) ---> (cdr a) ---> (define b (eval b) ---> Exemples: calculer 6+3: calculer 8 * (12 - x); si (a = 5) calculer b+3 sinon x-1 (+ 6 4) (* 8 (– 12 x)) (cond ((eq a 5) (+ 3 b)) (else (- x 1)) '(+ 3 x))) 12) [[ a = (+ 3 x) ]] [[ x = 12 ]] 15 // cdr == reste (3 x) (cons '* (cdr a))) [[ b = (* 3 x) ]] 36 ) G. Falquet, CUI, Université de Genève 25 de 26 G. Falquet, CUI, Université de Genève 26 de 26