Collections Séquence 2. Spécification algébrique - (CUI)

publicité
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
Téléchargement