Application des arbres binaires. Plan • Compter les arbres binaires

Transcription

Application des arbres binaires. Plan • Compter les arbres binaires
Application des arbres binaires. Plan
•
•
•
•
•
•
Compter les arbres binaires
Tétrarbres (quad trees)
Problème des n corps
Recherche dans un intervalle
Recherche dans un nuage de points
Recherche dans un arbre d’intervalles
Amphi 8
1
Compter les arbres binaires (1)
Rappel : un arbre binaire est soit vide, soit union
disjointe d'une racine, d'un sous-arbre gauche et d'un
sous-arbre droit.
Si bn est le nombre d'arbres binaires distincts à n
nœuds, on a donc :
n-1
b0 = 1
bn = Σ bibn-i-1
i=0
La série B(x) =
n
b
x
Σ n
n≥0
vérifie l'identité xB2(x) - B(x) + 1 = 0
Amphi 8
2
Compter les arbres binaires (2)
La résolution de l'équation xB2(x) - B(x) + 1 = 0
donne
bn =
1
n+1
( )=
2n
n
(2n)!
n!(n+1)!
d'où bn ~ π-1/24nn-3/2 + O(4nn-5/2)
(1) Dans un arbre,
nombre de nœuds = 1 + nombre d'arcs
(2) Dans un arbre binaire complet (tout nœud est d'arité
0 ou 2),
nombre de feuilles = 1 + nombre de nœuds internes
Amphi 8
3
Application des arbres binaires. Plan
•
•
•
•
•
•
Compter les arbres binaires
Tétrarbres (quad trees)
Problème des n corps
Recherche dans un intervalle
Recherche dans un nuage de points
Recherche dans un arbre d’intervalles
Amphi 8
4
Une vision hiérarchique des images
Une image est :
• soit de couleur uniforme
• soit formée de quatre images
Amphi 8
NO
NE
SO
SE
SO NO NE SE
5
Tétrarbres (quad trees)
Une image 2n x 2n est subdivisée itérativement en
quadrants jusqu'au niveau du pixel.
Amphi 8
NO
NE
SO
SE
6
Tétrarbre associé à une image
Amphi 8
7
Une échelle de 32 couleurs
Amphi 8
8
Tétrarbre associé à une image
Amphi 8
Merci à Luc Maranget...
9
Tétrabres en Java (1)
class Tetrarbre {
boolean couleur; // version noir et blanc
boolean estFeuille;
Tetrarbre so, no, ne, se;
// Constructeur des feuilles
Tetrarbre(boolean couleur)
{
this.estFeuille = true;
this.couleur = couleur;
}
...
Amphi 8
10
Tétrarbres en Java (2)
...
// Constructeur des nœuds internes
Tetrarbre(Tetrarbre so, Tetrarbre no,
Tetrarbre ne, Tetrarbre se)
{
this.estFeuille = false;
this.so = so; this.no = no;
this.ne = ne; this.se = se;
}
}
static boolean[][] image; // pixels
Amphi 8
11
Tétrarbres en Java (3)
static boolean estMonochrome(
Tetrarbre so, Tetrarbre no,
Tetrarbre ne, Tetrarbre se)
{
return (so.estFeuille && no.estFeuille
&& ne.estFeuille && se.estFeuille &&
so.couleur == no.couleur &&
so.couleur == ne.couleur &&
so.couleur == se.couleur);
}
Amphi 8
12
t = taille/2
pixel (i, j)
j
j+t
i
NO
NE
SO
SE
i+t
Amphi 8
13
Tétrarbres en Java (4)
static Tetrarbre faireArbre(int taille, int
i, int j) {
if (taille == 1)
return new Tetrarbre(image[i][j]);
int t = taille/2;
Tetrarbre so = faireArbre(t, i+t, j);
Tetrarbre no = faireArbre(t, i, j);
Tetrarbre ne = faireArbre(t, i, j+t);
Tetrarbre se = faireArbre(t, i+t, j+t);
if (estMonochrome(so, no, ne, se))
return new Tetrarbre(so.couleur);
return new Tetrarbre(so, no, ne, se);
}
Amphi 8
14
Codage
On code l'arbre par un
parcours préfixe. Les nœuds
internes sont codés 0 et les
feuilles 1. Après chaque 1,
on code la couleur de la
feuille (0 pour blanc, 1 pour
bleu).
Equivaut au code :
0
11
10
00
On pourrait améliorer le code : 01
1
0110101110110011101110100111010111101010010111001011101111
Amphi 8
15
Tétrabres en Java (5)
static void parcours(Tetrarbre a) {
if (a != null) {
if (a.estFeuille)
System.out.print("1" +
((a.couleur) ? "1" : "0"));
else // nœud interne
System.out.print("0");
parcours(a.so);
parcours(a.no);
parcours(a.ne);
parcours(a.se);
}
}
Amphi 8
16
Autre avantage des tétrarbres
• On peut changer facilement la couleur d'une image.
• Faire une rotation d'un quart de tour.
NO
NE
NE
SE
SO
SE
NO
SO
SO NO NE SE
Amphi 8
NO NE SE SO
17
Application des arbres binaires. Plan
•
•
•
•
•
•
Compter les arbres binaires
Tétrarbres (quad trees)
Problème des n corps
Recherche dans un intervalle
Recherche dans un nuage de points
Recherche dans un arbre d’intervalles
Amphi 8
18
Problème des n corps
• Objectif : simuler le comportement de n particules
(force de gravité ou électrostatique).
• Solution directe, itérer les calculs suivants :
– les n(n-1) forces F(p, q) entre 2 particules p et q,
– la résultante des forces pour chaque particule,
– le mouvement résultant pour une unité de temps.
• Trop lent pour n grand.
• Calcul hiérarchique
– calculs exacts pour des particules proches;
– on assimile les particules distantes à leur barycentre.
Amphi 8
19
Algorithme de Barnes-Hut
• Octabres: c'est la version 3D des tétrarbres : un cube
est divisé récursivement en 8 cubes.
• Calcul de la force F(p, C), sur la particule p, issue du
cube C de coté c et de barycentre b.
– Si C ne contient qu'une particule q, F(p, C) = F(p, q)
– Si la distance de p à b est > α.c (par ex. α = 2 ou 3),
F(p, C) = F(p, b)
– Sinon
F(p, C) = résultante (F(p, C1), ..., F(p, C8))
où C1, ..., C8 sont les 8 sous-cubes de C.
A Hierarchical O(n log n) force calculation algorithm, J. Barnes and P. Hut, Nature, v. 324, Décembre 1986
Amphi 8
20
2
Tétrarbre associé
6
3
7
5
8
4
9
10
1
11
1
12
1
2
2
2
4
4
3
1
3
4
3
3
4
8
12
1
3 1
4
2
4
5 6
7
9
4
2
4
10
11
Réalisation
• Données : pour chaque cube, la masse totale et le
barycentre. Ce calcul peut se faire récursivement.
• Gestion de l'octarbre
– L'arbre est reconstruit à chaque unité de temps.
– Cas le pire en O(n2).
– En pratique, arbre de hauteur O(log n).
• Pour une distribution uniforme en 3D, le nombre
d'interactions à calculer est
3
28πα
~
(n log2 n) soit ~ 263(n log2 n) pour α = 3
9
Amphi 8
22
Résultats expérimentaux
• Simulation d'un système de 5000 particules : 10 fois
plus rapide qu'avec l'algorithme direct.
• L'algorithme est facilement parallélisable.
• La simulation réaliste d'une galaxie nécessite des
millions d'étoiles.
• On connaît un algorithme en O(n). En 1994, on a
simulé 107 particules pour 103 pas de calcul (une
semaine de calcul sur 500 processeurs...)
Amphi 8
23
Application des arbres binaires. Plan
•
•
•
•
•
•
Compter les arbres binaires
Tétrarbres (quad trees)
Problème des n corps
Recherche dans un intervalle
Recherche dans un nuage de points
Recherche dans un arbre d’intervalles
Amphi 8
24
Recherche en une dimension
Problème : Compter les éléments d’un ensemble
d’entiers qui sont dans un intervalle donné [min,
max].
Exemple : E = {7, 9, 10, 12, 15, 20}
Entre 12 et 19, il y a 2 éléments.
L’ensemble est donné par un arbre binaire de
recherche. Le prétraitement se fait en O(n log n), la
recherche se fait en temps O(r + log n) où r est le
nombre d'éléments trouvés.
Amphi 8
25
Exemple
• Entre 8 et 19, il y a 4
éléments.
10
7
3
20
9
6
15
25
• On peut couper les
sous-arbres issus de 3
(à gauche de 7) et de
25 (à droite de 20).
12
5
Amphi 8
26
Exemple plus compliqué
Entre 25 et 75
50
90
7
40
80
30
60
70
55
79
65
72
Amphi 8
27
En Java
static int compter(Arbre a, int min,
int max) {
int total = 0;
if (a == null)
return total;
if (a.contenu >= min)
total += compter(a.filsG, min, max);
if (a.contenu >= min
&& a.contenu <= max) total++;
if (a.contenu <= max)
total += compter(a.filsD, min, max);
return total;
}
Amphi 8
28
Application des arbres binaires. Plan
•
•
•
•
•
•
Compter les arbres binaires
Tétrarbres (quad trees)
Problème des n corps
Recherche dans un intervalle
Recherche dans un nuage de points
Recherche dans un arbre d’intervalles
Amphi 8
29
Recherche en deux dimensions
Problème : Etant donné un ensemble de points dans
le plan, déterminer ceux qui sont dans une zone
donnée.
Exemples :
• Trouver les villes à moins de 100 km de Tours
• Trouver les personnes entre 25 et 29 ans qui
gagnent entre 1000 et 2000 euros par mois.
Amphi 8
30
Recherche en deux dimensions
E
J
G
A
K
H
D
C
B
F
I
Problème : Nombre
de points dans un
rectangle donné.
L
Solution en deux étapes
1. Prétraitement : un arbre pour le nuage de points
2. Réponse : une recherche dans l’arbre
Amphi 8
31
Arbres pour des points
class Point { // Conflit avec MacLib !
int x, y;
Point(int a, int b) {
x = a; y = b;
}
}
class Arbre {
Point p;
Arbre filsG, filsD;
Arbre(Arbre g, Point v, Arbre d) {
filsG = g; p = v; filsD = d;
}
}
Amphi 8
32
Arbre pour un nuage de points
Construire un arbre comme suit
• le premier point coupe le plan en
deux, horizontalement.
• les points coupent des secteurs
horizontalement aux niveaux
pairs, et verticalement aux
niveaux impairs.
Amphi 8
33
Exemple
E
J
G
A
A
K
H
D
C
B
F
Amphi 8
I
L
34
Exemple
E
J
G
A
A
K
H
B
D
C
B
F
I
L
B est fils gauche de A car B.y < A.y
Amphi 8
35
Exemple
E
J
G
A
A
K
H
D
C
B
F
B
I
C
L
C est fils gauche de A car C.x < B.x
Amphi 8
36
Exemple
E
J
G
A
A
K
H
D
C
B
F
B
I
C
D
L
D est fils droit de B car D.x > B.x
Amphi 8
37
Exemple
E
J
G
A
A
K
H
D
C
B
F
B
I
C
E
D
L
E est fils droit de A car E.y > A.y
D est fils droit de B car D.x > B.x
Amphi 8
38
Insérer un point : au début
• A la racine, le niveau est impair
static Arbre ajouter(Point p, Arbre a)
{
return ajouter(p, a, false);
}
static Arbre ajouter(Point p, Arbre a,
boolean vertical)
{ ... }
Amphi 8
39
Insérer un point : une étape
static Arbre ajouter(Point p, Arbre a,
boolean vertical)
{
if (a == null)
return new Arbre(null, p, null);
boolean estAGauche = (vertical) ?
(p.x < a.p.x) : (p.y < a.p.y);
if (estAGauche) // insérer à gauche
return new Arbre(ajouter(p, a.filsG,
!vertical), a.p, a.filsD);
else // insérer à droite
return new Arbre(a.filsG, a.p,
ajouter(p, a.filsD, !vertical));
} Amphi 8
40
La classe Rectangle
class Rectangle
{
int g, d, b, h;
}
h
g : abcisse du côté gauche
d : abcisse du côté droit
d
g
b : ordonnée du côté bas
h : ordonnée du côté haut
b
Amphi 8
41
Le décompte (1)
static int compter(Rectangle r,
Arbre a, boolean vertical) {
if (a == null)
return 0;
int total = 0;
boolean aGauche = r.g <= a.p.x;
boolean aDroite = a.p.x < r.d;
boolean enBas = r.b <= a.p.y;
boolean enHaut = a.p.y < r.h;
boolean min, max;
min = (vertical) ? aGauche : enBas;
max = (vertical) ? aDroite : enHaut;
... // à suivre
}
Amphi 8
42
Le décompte (2)
static int compter(Rectangle r, Arbre a,
boolean vertical) { ... // suite
if (min)
total += compter(r, a.filsG,
!vertical);
if (aGauche && aDroite &&
enBas && enHaut)
total++;
if (max)
total += compter(r, a.filsD,
!vertical);
return total;
} Amphi 8
43
Application des arbres binaires. Plan
•
•
•
•
•
•
Compter les arbres binaires
Tétrarbres (quad trees)
Problème des n corps
Recherche dans un intervalle
Recherche dans un nuage de points
Recherche dans un arbre d’intervalles
Amphi 8
44
Recherche d'un intervalle coupant
Problème : Chercher, dans un ensemble
d’intervalles, un élément qui rencontre un
intervalle donné.
Exemple : Dans une base d’événements, chercher
un événement qui a eu lieu durant une période
donnée.
Amphi 8
45
Type abstrait de données
Données : Un ensemble d'intervalles fermés [g, d].
Opérations :
• ajouter un intervalle
• supprimer un intervalle
• chercher si l'ensemble contient un intervalle qui
rencontre un intervalle donné v.
Amphi 8
46
Structure de données
• Les intervalles sont stockés dans un arbre
binaire de recherche.
• La clé utilisée pour comparer les nœuds est
l'extrémité gauche des intervalles.
• Chaque noeud n contient une information
supplémentaire, dmax, qui est le maximum des
extrémités droites des intervalles du sous-arbre
issu de n.
Amphi 8
47
Exemple
dmax = max des
extrémités droites
du sous-arbre.
16:21
30
8:9
23
5:8
10
0:3
3
Amphi 8
6:10
10
[22,25] rencontre
[11,14] non
25:30
30
15:23
23
17:19
20
26:26
26
19:20
20
48
Utilisation de dmax (1)
dmax = max des
extrémités droites
du sous-arbre.
16:21
30
8:9
23
5:8
10
0:3
3
Amphi 8
6:10
10
Détermine dans
quel sous-arbre
chercher.
25:30
30
15:23
23
17:19
20
26:26
26
19:20
20
49
Intervalle [g, d]. Règle 1
Si filsG.dmax < g,
inutile de chercher dans
le sous-arbre gauche.
Intervalle [22, 25]
16:21
30
8:9
23
5:8
10
0:3
3
Amphi 8
6:10
10
25:30
30
15:23
23
dmax = 10 < 22
17:19
20
26:26
26
19:20
20
50
Règle 2 (justifiée plus loin)
Intervalle
[g, d]=[22, 25]
Si filsG.dmax ≥ g,
inutile de chercher dans
le sous-arbre droit.
16:21
30
8:9
23
5:8
10
0:3
3
Amphi 8
6:10
10
25:30
30
15:23
23
dmax = 23 > 22
dmax = 10 < 22
Intersection !
17:19
20
26:26
26
19:20
20
51
Utilisation de dmax
dmax = 23 > 11
dmax = 10 < 11
pas d'intersection !
Intervalle [11, 14]
16:21
30
8:9
23
5:8
10
0:3
3
Amphi 8
6:10
10
25:30
30
15:23
23
17:19
20
26:26
26
19:20
20
52
Justification
Soit v = [g, d]. Soit [g', d'] un intervalle du sous-arbre
gauche d'extrémité droite maximale. Par hypothèse, on
a d' ≥ g.
Supposons qu’aucun intervalle du sous-arbre gauche
ne rencontre [g, d]. Alors
[g, d] ∩ [g', d'] = ∅, d'où d < g'.
Soit [g", d"] un intervalle du sous-arbre droit. On a g <
d < g' < g" < d", donc [g, d] et [g", d"] sont disjoints.
Donc aucun intervalle ne rencontre v !
Amphi 8
53
Les classes
• Une classe d'intervalles
• Une classe d'arbres binaires de recherche avec
– un champ intervalle
– un champ dmax
• Il faut revoir le constructeur d'arbres pour le calcul
de dmax!
Amphi 8
54
Classe Intervalle
class Intervalle
{
int min, max;
Intervalle(int a, int b)
{
min = a;
max = b;
}
}
static boolean rencontre(
Intervalle u, Intervalle v)
{
return
u.min <= v.max && v.min <= u.max;
}
Amphi 8
55
Classe Arbre
class Arbre {
Intervalle u;
int dmax;
Arbre filsG, filsD;
Arbre(Intervalle v, Arbre g, Arbre d)
{
u = v;
filsG = g;
filsD = d;
dmax = calculDmax(v, g, d);
}
...
}
Amphi 8
56
Classe Arbre
class Arbre
{
...
static int calculDmax(Intervalle v,
Arbre g, Arbre d)
{
int m = v.max;
if (g != null && g.dmax > m)
m = g.dmax;
if (d != null && d.dmax > m)
m = d.dmax;
return m;
}
}
Amphi 8
57
Recherche
static Arbre chercher(Intervalle v, Arbre a)
{
if (a == null || rencontre(v, a.u))
return a;
if (a.filsG != null) &&
a.filsG.dmax >= v.min)
return chercher(v, a.filsG);//Règle 2
else
return chercher(v, a.filsD);//Règle 1
}
Amphi 8
58