INF 321
Types produit, somme, et r´ ecursifs
Eric Goubault
Cours 3
27 mai 2013
R´ esum´ e
A l’´episode pr´ec´edent...
Les fonctions et les passages d’argument Les r´ef´erences (pointeurs)
Les types produits et le GC Dans ce cours
Les types produits - retour sur les tableaux tableaux 1D, 2D etc.
rappel: enregistrements; ´egalit´e physique et structurelle;
hachage Les types somme Les types r´ecursifs
listes - retour au hachage probl`emes departage
2
Les tableaux
En quelque sorte: type produit, dont le nom des champs est un entier.
Un peu l’ancˆetre des types produits: surtout utilis´e pour coder les vecteurs et matrices...
Possibilit´e ´egalement de faire des tableaux 2D (matrices), 3D etc. (tenseurs)
D´ eclaration (1D)
Java (rappel) double[ ] x ;
C
d o u b l e ∗x ;
Un tableau=pointeur sur son premier ´el´ement Caml
Pas de d´eclaration
4
Allocation (1D)
Java (rappel)
x = new double[ 1 0 0 ] ;
d´emarre en 0, dernier indice valide en 99 C
x = (d o u b l e ∗) m a l l o c ( 1 0 0∗s i z e o f(d o u b l e) ) ;
D´ebut d’allocation dynamique!
o`u alors plus simplement, `a la d´eclaration:
d o u b l e x [ 1 0 0 ] ;
d´emarre aussi en 0, dernier indice valide en 99 Caml
l e t x = A r r a y . make 100 0 ; ;
Acc` es (projections, construction)
Java, C
d o u b l e y = x [ 5 0 ] ; x [ 5 0 ] = 1 . 0 ;
Caml
l e t y=x . ( 5 0 ) ; ; x . ( 5 0 )<−1 . 0 ; ;
6
Exemple: produit scalaire
c l a s s v e c t n { double[ ] comp ; v e c t n (i n t n ) {
t h i s. comp = new double[ n ] ; } }
c l a s s E s s a i {
s t a t i c double s c p r o d u c t ( v e c t n p , v e c t n q ) { double r e s = 0 ;
f o r (i n t i =0; i<p . comp . l e n g t h ; i ++) r e s = r e s+p . comp [ i ]∗q . comp [ i ] r e t u r n r e s ; }
. . . }
Et siq.dim est diff´erent dep.dim? (plus tard: les exceptions) Remarque: lethis (non n´ecessaire ici) d´enote l’objet courant...
Dans d’autres langages
C
d o u b l e u [ 1 0 0 ] , v [ 1 0 0 ] ; . . .
d o u b l e s c p r o d u c t (d o u b l e p [ 1 0 0 ] , d o u b l e q [ 1 0 0 ] ) { d o u b l e r e s = 0 ;
f o r (i n t i =0; i<100; i ++) r e s = r e s+p [ i ]∗q [ i ] r e t u r n r e s ; } . . . s = s c p r o d u c t ( u , v ) ;
Ou (taille de tableau param`etre):
d o u b l e ∗u , ∗v ; i n t d ; . . .
u = (d o u b l e ∗) m a l l o c ( d∗s i z e o f(d o u b l e) ) ; v = (d o u b l e ∗) m a l l o c ( d∗s i z e o f(d o u b l e) ) ; . . .
d o u b l e s c p r o d u c t (d o u b l e ∗p , d o u b l e ∗q , i n t dim ) { d o u b l e r e s = 0 ;
f o r (i n t i =0; i<dim ; i ++) r e s = r e s+p [ i ]∗q [ i ] r e t u r n r e s ; }
. . . s = s c p r o d u c t ( u , v , d ) ;
8
Et finalement, en Caml
Caml
l e t s c p r o d u c t u v n = l e t r e s= r e f 0 .
and n=A r r a y . l e n g t h u i n f o r i =0 t o n do
r e s := ! r e s +. u . ( i ) ∗. v . ( i ) ; done;
! r e s ; ;
Donne une fonction:
v a l s c p r o d u c t : f l o a t a r r a y−> f l o a t a r r a y−> f l o a t =<f u n>
Tableaux 2D
On consid`ere une matrice deRN×M, avecM = 3 colonnes de N= 4 lignes:
En Java
double M = new double[ 4 ] [ 3 ] ; M[ 0 ] [ 0 ] = 8 ;
M[ 0 ] [ 1 ] = 1 ; . . .
8 1 6
3 5 7
4 9 2
10 12 11
10
Tableaux 2D
Ou de fa¸con plus compacte
double[ ] [ ] M={ {8 , 1 , 6}, {3 , 5 , 7}, {4 , 9 , 2}, {1 0 , 1 2 , 1 1} };
8 1 6
3 5 7
4 9 2
10 12 11
Tableaux 2D en C
Organisation en un bloc contigu en m´emoire
Une matriceN∗M est donn´e par un ensemble deN×M r´eels Allocation: float *x = (float *)
malloc(N*M*sizeof(float));
on r´ecup`ere xi,j par x[i*M+j]
8 1 6 3 5 7 4 9 2 10 12 11
12
Tableaux 2D en C (et en fait en Java!)
Organisation en vecteur de vecteurs
Une matrice N∗M est un ´el´ement deRN×M, c’est aussi un vecteur `aM composantes chacune dans RN
Allocation: float **x = (float **) malloc(M*sizeof(float *)); puis:
f o r ( i =0; i<M; i ++)
x [ i ] = (f l o a t ∗) m a l l o c (N∗s i z e o f(f l o a t) ) ;
Le tableau est ainsi impl´e- ment´e comme M pointeurs sur N vecteurs de taille N (chacun un bloc contigu de m´emoire)
8 1 6
3 5 7
4 9 2
10 12 11
Se g´en´eralise en dimension sup´erieure...
En Caml
Plus simple...
l e t x = A r r a y . m a k e m a t r i x n m 0 ; ; x . ( 1 ) . ( 2 )<−9 . 0 ; ;
14
Enregistrements - rappel
Revenons aux enregistrements g´en´eraux (hors tableaux) Java
c l a s s P o i n t {
i n t x ; i n t y ; i n t z ;
P o i n t (i n t a , i n t b , i n t c ) { x = a ; // ou t h i s . x = a ; y = b ; // ou t h i s . y = b ; z = c ; // ou t h i s . z = c ; } }
Utilisation du constructeur
P o i n t x =new P o i n t ( 1 , 2 , 3 ) ;
Alloue, et fait l’affectation
Egalit´ e physique et ´ egalit´ e structurelle
Apr`es cela, faisons:
i n t x x = p . x ; i n t y y = p . y ; i n t z z = p . z ;
P o i n t q = new P o i n t ( xx , yy , z z ) ;
petqd´enotent les mˆemes points (mˆeme coordonn´ees, i.e. les champs ont mˆeme valeur), mais ne sont pas ´egaux (en tant qu’objets, c.-a.d. de pointeurs, ou de locations m´emoire).
p q
x: 1|y: 2|z: 3 x: 1|y: 2|z: 3 [assez similaire `a ´egalit´e, et ´egalit´e `a isomorphisme pr`es...]
16
Egalit´ e physique
p == q ?
Cela est faux (deux r´ef´erences distinctes), aussi bien en Java, C qu’en Caml.
p q
x: 1|y: 2|z: 3 x: 1|y: 2|z: 3 De mˆeme pour les tableaux
Egalit´ e structurelle
Java
s t a t i c boolean e q u a l ( P o i n t p , P o i n t q ) { r e t u r n ( p . x==q . x )&&(p . y==q . y )&&(p . z==q . z ) ; }
(Impl´ement´e parfois par la fonctionequals - ex. String) C
i n t e q u a l (s t r u c t P o i n t p , s t r u c t P o i n t q ) {
r e t u r n ( p . x == q . x ) && ( p . y == q . y ) && ( p . z == q . z ) ; }
Caml
l e t e q u a l p q = ( p . x==q . x ) && ( p . y==q . y ) && ( p . z==q . z ) ; ;
(impl´ement´e par p=q)
18
Partage et hash-consing
L’´egalit´e structurelle est coˆuteuse, on peut parfois, par construction, l’obtenir par l’´egalit´e physique...
Id´ee pour les Point: on remplace le newpar une fonction de cr´eation:
qui teste si un point de mˆemes coordonn´ees existe d´ej`a ne l’alloue pas de nouveau si c’est le cas
Pour ce faire: il faut un test d’´egalit´e structurelle...on
l’approche par un moyen peu coˆuteux, lehachage et les tables de hachage
Hachage
Principe
Permettre `a moindre coˆut, de distinguer `a coup sˆur deux objets
Traditionnellement, par une fonction de hachage,h :O →N qui associe `a tout objet que l’on veut consid´erer, un entier, de telle fa¸con que h(x)6=h(y) =⇒ x 6=y
G´en´eralement,h a pour valeur 0, . . . ,n (pour un certain n ∈N)
On peut ainsi ranger les objets deO dans unetable de collision: tableau qui `a i ∈0, . . . ,n associe uneliste de collision: tous les x tels queh(x) =i
On simplifie le probl`eme pour l’instant - on utilise et on red´efinit les listes `a la fin de ce cours!
20
Exemple pour Point
Fonction de hachage modulaire simple c l a s s P o i n t {
. . . }
c l a s s Hachage {
f i n a l i n t n = . . . ; // nombre f i x e f i n a l i n t m = . . . ; // t a i l l e f i x e e
s t a t i c i n t h a c h e ( P o i n t p ) { r e t u r n ( p . x+p . y+p . z)%n ; }
}
Gestion d’ensembles de m points
Probl`eme
Se constituer une base de donn´ees de m(fix´e - mˆeme que transparent pr´ec´edent) points distincts au maximum Mais le remplissage de la base de donn´ees peut demander plusieurs fois d’inclure un point avec les mˆemes coordonn´ees qu’un existant dans la base
On veut d´ecider de l’´egalit´e structurelle rapidement (par l’´egalit´e physique)
Structure de donn´ees Java
Tableau 2D -tab[i][j]est le ji`emePoint de code de hachage
´egal `ai
c l a s s T a b l e n a i v e { s t a t i c P o i n t [ ] [ ] t a b ; s t a t i c i n t[ ] f r e e i n d e x ; . . .
p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ) { t a b = new P o i n t [ n ] [ m ] ;
f r e e i n d e x =new i n t[ n ] ; // t o u t a z e r o . . . } }
22
Utilisation du hachage
Code de cr´eation non-redondante c l a s s T a b l e n a i v e {
. . .
s t a t i c v o i d a d d P o i n t (i n t x , i n t y , i n t z ) { P o i n t p = new P o i n t ( x , y , z ) ;
i n t k = Hachage . h a c h e ( p ) ; boolean f o u n d = f a l s e;
f o r (i n t i =0; i<f r e e i n d e x [ k ] ; i = i +1) i f ( e q u a l ( t a b [ k ] [ i ] , p ) ) {
i =f r e e i n d e x [ k ] ; f o u n d=t r u e; } i f ( ! f o u n d ) {
t a b [ k ] [ f r e e i n d e x [ k ] ] = p ;
f r e e i n d e x [ k ]= f r e e i n d e x [ k ] + 1 ; } }
. . .
(On pourrait retourner ´egalement found)
Exemple
Point (0,0,0) (hachage=0)
f i n a l i n t n =3;
f i n a l i n t m=4;
. . .
a d d P o i n t ( 0 , 0 , 0 ) ;
(0,0,0) null null null null null null null null null null null
24
Exemple
Point (1,2,4) (hachage=1)
a d d P o i n t ( 1 , 2 , 4 ) ;
(0,0,0) null null null (1,2,4) null null null null null null null
Exemple
Point (1,2,3) (hachage=0)
a d d P o i n t ( 1 , 2 , 3 ) ;
(0,0,0) (1,2,3) null null (1,2,4) null null null null null null null
26
Exemple
Point (2,3,6) (hachage=2)
a d d P o i n t ( 2 , 3 , 6 ) ;
(0,0,0) (1,2,3) null null (1,2,4) null null null (2,3,6) null null null
Exemple
De nouveau le point (1,2,3) (hachage=0)
a d d P o i n t ( 1 , 2 , 3 ) ;
(0,0,0) (1,2,3) null null (1,2,4) null null null (2,3,6) null null null
28
Critique
Points positifs
Pas de nouvelle cr´eation de point dans la table pour (1,2,3) En deux comparaisons avec un autre point (au lieu de potentiellement 4)
Points n´egatifs
Coˆut m´emoire incompressible avec le tableau 2D...m×n
´
el´ements allou´es pour seulement m points possibles!
→ structures de donn´eesdynamiques(listes) au prochain cours
Recherche dans la table des collisions peu optimis´ee. On pourrait au moins ordonner les points, pour une recherche dichotomique; demande la aussi des listes...
Types somme, qu’est-ce?
Un cas “primitif”
Supposons que l’on veuille repr´esenter un nombre fini de valeurs, par exemple, les couleurs d’une carte `a jouer (ici en Caml):
> t y p e c o u l e u r = PIQUE | COEUR | CARREAU | TREFLE ; ;
> l e t x = PIQUE ; ; v a l x : c o u l e u r = PIQUE
(exemple du Leroy/Weis)
Ceci est un cas simple de type somme/disjonctif!
30
Et dans d’autres languages (C, Java)
Java
enum c o u l e u r { PIQUE , COEUR, CARREAU, TREFLE };
c o u l e u r c = c o u l e u r . PIQUE ; S y s t e m . o u t . p r i n t l n ( c ) ;
(donnePIQUE) C
enum c o u l e u r { PIQUE , COEUR, CARREAU, TREFLE };
enum c o u l e u r c = PIQUE ;
Union (coproduit)
X
X` Y
Y
Z inX
∀f
inY
∀g
∃!h
Propri´et´e universelle: ∀f,g,∃!h, tel que h◦inX = f
h◦inY = g
Dans les ensembles X`
Y ={(0,x)|x ∈ X} ∪ {(1,y)|y∈Y}(union disjointe)
inX(x) = (0,x), inY(y) = (1,y) h(z) =
f(x) if z = (0,x) g(y) if z = (1,y)
32
En fait...
En Java (et en Caml)
couleur.PIQUE(resp. PIQUE) est l’injection canonique de
l’ensemble `a un ´el´ement (PIQUE) vers le typeenum couleur(resp.
couleur)
En C
Ce n’est qu’une fa¸con de nommer symboliquement des constantes scalaires:
enum c o u l e u r { PIQUE=0 , COEUR=1 , CARREAU=2 , TREFLE=3 };
enum c o u l e u r c = PIQUE ; // v a u t 0 ( i n t )
Passons au jeu de cartes...
En Caml
> t y p e c a r t e = As o f c o u l e u r
| R o i o f c o u l e u r
| Dame o f c o u l e u r
| V a l e t o f c o u l e u r
| P e t i t e c a r t e o f i n t∗c o u l e u r ; ;
> l e t x = As ( PIQUE ) ; ; v a l x : c a r t e = As PIQUE
> l e t y = P e t i t e c a r t e ( 8 , TREFLE ) ; ; v a l y : c a r t e = P e t i t e c a r t e ( 8 , TREFLE )
Asrepr´esente l’injection canonique d’une copie decouleur (“tagg´e” par As) vers le typecarte.
Lepattern-matchingpermet de programmer ´el´egamment...
Moins ´el´egant...(?)
Mais th´eoriquement isomorphe (le syst`eme ne le voit pas...):
> t y p e v a l e u r = As | R o i | Dame | V a l e t | P e t i t e c a r t e o f i n t ; ; t y p e v a l e u r = As | R o i | Dame | V a l e t | P e t i t e c a r t e o f i n t
> t y p e c a r t e b i s = v a l e u r∗c o u l e u r ; ; t y p e c a r t e b i s = v a l e u r ∗ c o u l e u r
> l e t z = ( As , PIQUE ) ; ;
v a l z : v a l e u r ∗ c o u l e u r = ( As , PIQUE )
(valeur×couleur∼carte∼cartebis...)34
Dans d’autres languages?
En Java
c l a s s C a r t e {
enum v a l e u r { As , Roi , Dame , V a l e t , P e t i t e C a r t e };
enum c o u l e u r { PIQUE , COEUR, CARREAU, TREFLE };
v a l e u r v a l ; i n t v a l p e t i t e ; c o u l e u r c ; }
Moche! (somme→ produit cart´esien; luxueux...) on reconnaˆıt les enregistrements pour le produit valeur×couleur
maisvalpetite n’est utile que quandvalvautPetiteCarte Mˆeme probl`eme en C!
enum c o u l e u r { P i q u e , Coeur , C a r r e a u , T r e f l e };
enum v a l e u r { As , Roi , Dame , V a l e t , P e t i t e C a r t e };
s t r u c t c a r t e {
enum v a l e u r v a l ; i n t v a l p e t i t e ; enum c o u l e u r c ; };
Encore qu’en C...
Type somme primitif...
enum c o u l e u r { P i q u e , Coeur , C a r r e a u , T r e f l e };
u n i o n v a l b i s {
enum v a l e u r b i s { As , Roi , Dame , V a l e t } v a l u e ; i n t v a l p e t i t e b i s ; };
s t r u c t c a r t e { u n i o n v a l b i s v a l ; enum c o u l e u r c ; };
Probl`eme: les espaces m´emoires allou´es aux diff´erents champs d’une union sont les mˆemes!:
x.val.value et x.val.valpetitebissont les mˆemes mots m´emoire...
Cause d’erreurs, ou de codage abscons...
36
Pattern-matching (filtrage)?
En Caml
Enum´eration de cas, pratique sur les types disjonctifs...
l e t f x = f u n c t i o n
| As −> . . .
| R o i −> . . . . . .
| P e t i t e c a r t e ( x , c )−> . . .
| −> . . . ; ;
Exactement la fonctionh de la propri´et´e universelle!
En Java
Forme “primitive”:
s t a t i c f ( C a r t e x ) { s w i t c h ( x . v a l ) {
c a s e As : . . . ; b r e a k; c a s e R o i : . . . ; b r e a k;
. . .
d e f a u l t : . . . } . . . }
Moralit´ e
Mˆeme sur ce cas simple...
Le codage des types sommes n’est pas id´eal en C et en Java...
En g´en´eral
Pour des types sommes plus complexes (non finis, donc pas d’´enum´eration):
on utilise l’injection X`
Y ,→X ×Y,
c.a.d. que l’on remplace les types sommes par des types enregistrements
plus coˆuteux...
Possibilit´e en Java d’utiliser des classes abstraites...(cf. cours 4) Maintenant...application aux types de donn´eesdynamiques...
38
Des types de donn´ ees dynamiques, pour quoi faire?
Matrices dont la taille est inconnue au moment de l’´ecriture du code (mais bien sˆur connue au moment de l’ex´ecution) On veut mˆeme des types dont la taille ´evolue au cours du temps: les tableaux ne sont plus pertinents...Exemple de ce cours: tableau 2D -tab[i][j] est leji`emePointde code de hachage ´egal `ai
c l a s s T a b l e n a i v e { s t a t i c P o i n t [ ] [ ] t a b ; s t a t i c i n t[ ] f r e e i n d e x ;
p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ) { t a b = new P o i n t [ n ] [ m ] ;
f r e e i n d e x =new P o i n t [ n ] ; // t o u t a z e r o }
}
Listes
Rappel (type produit):
Un ´el´ement deN3 est en mˆeme temps, par associativit´e du produit:
N×N×N: un triplet d’entiers
N×(N×N): un couple dont le premier ´el´ement est un entier, et le deuxi`eme est un couple (d’entiers)
On peut jouer `a ce jeu r´ecursivement:
Une listel (de intpar exemple) est une structure de donn´ees telle que:
son premier ´el´ement (car de LISP) est unint
son deuxi`eme ´el´ement (cdr de LISP) est une liste d’entiers l car: . . .|cdr . . .|. . .
40
Listes
On a envie d’´ecrire (´equation aux domaines):
ListN=N×ListN
d’o`u programmation par r´ecurrence structurelle (plus tard)
Listes
On a envie d’´ecrire (´equation aux domaines):
ListN={()} ∪N×ListN car il ne faut pas oublier la liste vide!
d’o`u programmation par r´ecurrence structurelle (plus tard)
42
Impl´ ementation
Java
c l a s s L i s t { i n t hd ; L i s t t l ; }
C
t y p e d e f s t r u c t s t L i s t { i n t hd ;
s t r u c t s t L i s t ∗t l ; } ∗L i s t ;
O` u est pass´ ee la liste vide?
Une liste non vide est allou´ee quelque part en m´emoire (pour conserver la valeur dehd et de tl), donc est unpointeur valide, diff´erent denull
On identifie la liste vide avecnull
44
Un peu de p´ edantique
Les listes sont construites `a partir d’un type disjonctif, ou type somme: une liste est:
soit vide
soit non vide (et donc un ´el´ement deN×ListN, lui mˆeme type produit)
Types disjonctifs en Caml
Listes
t y p e l i s t e = N i l | Cons o f i n t∗l i s t e
Nilest l’injection canonique de unitvers liste
Cons est l’autre injection canonique deint*listeversliste On peut ´ecrire directement:
> Cons ( 1 , N i l ) ; ;
−: l i s t e = Cons ( 1 , N i l )
46
Remarque en passant (en C)
(Rappel) il y a une forme primitive de type disjonctif en C, les types union.
On n’en a pas besoin ici carnull est une valeur possible de tout pointeur, et on n’a pas besoin de coder explicitement le type disjonctif.
On aurait pu ´ecrire sinon:
t y p e d e f u n i o n u n L i s t { i n t v i d e ;
s t r u c t c o n s { i n t hd ;
u n i o n u n L i s t ∗t l ; }
} ∗L i s t ;
Constructeur par d´ efaut (Java)
L i s t l ;
l = new L i s t ( ) ; l . hd = 4 ;
l . t l = new L i s t ( ) ; l . t l . hd = 5 ;
l . t l . t l = n u l l;
48
Construction de la liste
Code L i s t l ;
l
Construction de la liste
Code
l = new L i s t ( ) ;
l ?|?
50
Construction de la liste
Code l . hd = 4 ;
l 4|?
Construction de la liste
Code
l . t l = new L i s t ( ) ;
l 4|. ?|?
52
Construction de la liste
Code
l . t l . hd = 5 ;
l 4|. 5|?
Construction de la liste
Code
l . t l . t l = n u l l;
l 4|. 5|null
54
Constructeurs (II)
Java
Il s’agit de d´efinir l’injection canonique de N×List versList:
c l a s s L i s t { . . .
L i s t (i n t c a r , L i s t c d r ) { hd = c a r ;
t l = c d r ; }
Du coup, on aurait pu ´ecrire (exemple pr´ec´edent)List l = new List(4, new List(5, null));
C
L i s t c o n s (i n t c a r , L i s t c d r ) {
L i s t r e s = ( L i s t ) m a l l o c (s i z e o f(s t r u c t s t L i s t ) ) ; r e s−>hd = c a r ; r e s−>t l = c d r ; r e t u r n r e s ; }
Remarquez leres->hd, abbr´eviation de(*res).hd
Les listes lin´ eaires
Restriction:
Listes construites uniquement sanscycle
Dans ce cas, les listes ont une notion de longueur: il suffit de d´efinirlength dans l’un des deux cas liste vide, liste non vide (donc ´egale `a un cons(hd,l)) d’apr`es l’´equation de domaines ListN={()} ∪N×ListN:
length(()) = 0,
length(cons(hd,l)) =length(l) + 1
Cela nous interdit bien sˆur des listes circulaires comme l =cons(0,l), qui “repr´esente” en quelque sorte la liste infinie constitu´ee uniquement de z´eros.
l 0|.
56
En fait, tout cela est d´ ej` a d´ efini...
Les listes d’objets de type’a: (type ’a list):
Caml
> [ ] ; ;
−: ’ a l i s t = [ ]
> [ 1 ; 2 ; 3 ] ; ;
> 1 : : 2 : : 3 : : [ ] ; ;
−: i n t l i s t = [ 1 ; 2 ; 3 ]
> [ 1 ; 2 ] @ [ 3 ; 4 ; 5 ] ; ;
−: i n t l i s t = [ 1 ; 2 ; 3 ; 4 ; 5 ]
> L i s t . l e n g t h [ ” h e l l o ” ; ”w o r l d ” ; ” ! ” ] ; ;
−: i n t = 3
> L i s t . hd [ 1 ; 2 ; 3 ] ; ;
−: i n t = 1
> L i s t . t l [ 1 ; 2 ; 3 ] ; ;
−: i n t l i s t = [ 2 ; 3 ]
Java
LesArrayList...(signature plus complexe)
Revenons aux tables de hachage...
Am´elioration du code
A chaquei entre 0 etn, on va repr´esenter une liste de collisions possibles (au lieu d’un tableau bidimensionnel, fig´e):
c l a s s P o i n t l i s t { P o i n t p ;
P o i n t l i s t t l ;
P o i n t l i s t ( P o i n t q , P o i n t l i s t r ) { p = q ; t l = r ; }
}
c l a s s T a b l e {
s t a t i c P o i n t l i s t [ ] t a b ;
p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ) { t a b = new P o i n t l i s t [ n ] ;
. . . } }
58
Cr´ eation d’un ´ eventuel nouveau Point
s t a t i c P o i n t l i s t a d d P o i n t L i s t ( P o i n t l i s t l , P o i n t q ) { i f ( l == n u l l)
r e t u r n new P o i n t l i s t ( q , n u l l) ; i f ( e q u a l ( l . p , q ) )
r e t u r n l ; e l s e
r e t u r n new P o i n t l i s t ( l . p , a d d P o i n t L i s t ( l . t l , q ) ) ; }
s t a t i c v o i d a d d P o i n t (i n t x , i n t y , i n t z ) { P o i n t p = new P o i n t ( x , y , z ) ;
i n t k = Hachage . h a c h e ( p ) ;
t a b [ k ] = a d d P o i n t L i s t ( t a b [ k ] , p ) ; }
Exemple
Point (0,0,0) (hachage=0)
a d d P o i n t ( 0 , 0 , 0 ) ;
tab[0] (0,0,0)|null
tab[1]
tab[2]
60
Exemple
Point (1,2,4) (hachage=1)
a d d P o i n t ( 1 , 2 , 4 ) ;
tab[0] (0,0,0)|null
tab[1] (1,2,4)|null
tab[2]
Exemple
Point (1,2,3) (hachage=0) a d d P o i n t ( 1 , 2 , 3 ) ;
(0,0,0)|null GC!
tab[0] (0,0,0)|. (1,2,3)|null
tab[1] (1,2,4)|null
tab[2]
62
Exemple
Point (2,3,6) (hachage=2) a d d P o i n t ( 2 , 3 , 6 ) ;
tab[0] (0,0,0)|. (1,2,3)|null
tab[1] (1,2,4)|null
tab[2] (2,3,6)|null
En fait cela existe en Java!
List, AbstractList, Vector etc.
En fait, compliqu´e... il faut parler desinterfaces, des classes, packagesetc. (cours 4)
HashTable
De mˆeme... (en en Caml: Hashtbl)!
Utile de savoir comment cela marche...voire de savoir refaire...
64
C’est bien beau mais...j’ai trich´ e!
Les listes en pratique, font du partage:
Pour des questions d’efficacit´e (cf. hash-consing) Pour repr´esenter des structures de donn´ees “infinies”
Listes infinies (rationnelles)
Exemple:
on veut repr´esenter toutes les listes infinies, ultimement p´eriodiques, par exemple une liste
l = (0,(1,(2,(3,(2,(3, ....
(que des pattern2 puis 3 r´ep´et´es):
L i s t l 3 = new L i s t ( ) ; l 3 . hd = 2 ;
l 3 . t l = new L i s t ( 3 , l 3 ) ; L i s t l 2 = new L i s t ( 1 , l 3 ) ; L i s t l 1 = new L i s t ( 0 , l 2 ) ;
Remarque: c’est la construction correcte de l3que l’on ´ecrit par “abus de notation”l3 =cons(2,cons(3,l3))
Possibilit´e de manipuler algorithmiquement les listes infinies.
Evaluation paresseuse...(voir cours 9) 66
Partage or not partage?
Java
Si partage sans cycle,
On ´economise juste en m´emoire, et cela peut permettre de faire du hash-consing sur les listes...
Ex. fonction append: on veut concat´ener une listel2 au bout de la listel1:
s t a t i c L i s t append ( L i s t x , L i s t y ) { i f ( x == n u l l) r e t u r n y ;
L i s t p = x ;
w h i l e ( p . t l != n u l l) p = p . t l ; p . t l = y ;
r e t u r n x ; }
Versions d´ er´ ecursiv´ ees (Java)
s t a t i c L i s t append ( L i s t x , L i s t y ) { i f ( x == n u l l) r e t u r n y ;
L i s t p = x ;
w h i l e ( p . t l != n u l l) p = p . t l ;
p . t l = y ; r e t u r n x ; }
Plus tard
On fera des versions r´ecursives...
68
Ex´ ecution
append ( l 1 , l 3 ) ;
Avec:
l1 4|. 5|null
l3 2|. 3|null
Ex´ ecution
x
l1 4|. 5|cnl1
p
l3 2|. 3|null
y
70
Ex´ ecution
x
l1 4|. 5|cnl1
p
l3 2|. 3|null
y
Ex´ ecution
x
l1 4|. 5|cnl1
p
l3 2|. 3|null
y
72
Versions d´ er´ ecursiv´ ees (II)
s t a t i c L i s t append ( L i s t x , L i s t y ) { i f ( x == n u l l) r e t u r n y ;
e l s e {
L i s t p = x ;
L i s t q = new L i s t ( x . hd , n u l l) ; L i s t r = q ;
w h i l e ( p . t l != n u l l) {
q . t l = new L i s t ( p . t l . hd ,n u l l) ; q = q . t l ;
p = p . t l ; } q . t l = y ; r e t u r n r ; }
Version sans partage (pour l’argument gauche), et it´erative!
Partage or not partage?
Partage possible de l’argument gauche, de l’argument droit, des deux, ou d’aucun des deux...
Int´erˆet/inconv´enient: si on modifieen place les listesl1,l2 oul3,append(l1,l3); et append(l2,l3);ne sont pas modifi´ees.
Tout d´epend de ce que l’on veut faire, y r´efl´echir avant de taper un code!
74
Conclusion sur append
La premi`ere:
ne modifie pas ses arguments
permet `a ses arguments de partager des cellules alloue
La seconde fonction append:
modifie ses arguments
demande que ses arguments ne partagent pas de cellules n’alloue pas
Arbres binaires
Vous imaginez bien que vous pouvez aller plus loin... Remplacer la liste par un couple de deux arbres: le sous-arbre gauche (oufils gauche) et le sous-arbre droit (ou fils droit):
Java
c l a s s A r b r e B i n {
O b j e c t noeud ; A r b r e B i n f i l s g ; A r b r e B i n f i l s d ; A r b r e B i n ( O b j e c t n , A r b r e B i n f g , A r b r e B i n f d ) {
noeud = n ; f i l s g = f g ; f i l s d = f d ; } }
(remarque: ici arbre d’objets quelconques Java) Caml
t y p e ’ a A r b r e B i n = N i l | A r b r e o f ’ a∗A r b r e B i n∗A r b r e B i n
(remarque: ici arbre de type quelconque) 76
La prochaine fois
Classes, objets, exceptions Interfaces, packages etc.
Bon TD!
La prochaine fois
Classes, objets, exceptions Interfaces, packages etc.
Bon TD!
78