Arbres - Algorithmique 1 - 2019-2020 › ~gcolas › algo-licence › slides ›...
Transcript of Arbres - Algorithmique 1 - 2019-2020 › ~gcolas › algo-licence › slides ›...
ArbresAlgorithmique 1 - 2019-2020
Stéphane Grandcolas
Aix-Marseille Université
2019-2020
Arbres
I définitions, vocabulaire,I arbres binaires,I abres binaires de recherche,
Arbres
Arbre syntaxique représentant l’exp. arith.x
(x − 1)× (78+ y)
×
/ +
x − y78
x 1
Arbres
Un arbre généalogique descendant
GeorgesGinette
Paul LillyVictor
TomNaomie
Mattéo Lucie Théo Mélanie Léon
Arbres
Un arbre lexicographique, ou arbre en parties communes
t
r
oi
e
l e t c
n e
l s
e
m
a
e
i
p
i
main
port
pis
pile
pic
mite
mie
male
porte
Arbres : définition 1Un arbre est un ensemble organisé de noeuds :
I chaque noeud a un père et un seul,I excepté un noeud, la racine, qui n’a pas de père.
Les fils d’un noeud p sont les noeudsdont le père est p
Les feuilles d’un arbre sontles noeuds qui n’ont pas de fils
racine
feuilles
Arbres : définition 2 (récursive)
Un arbre est constituéI d’un noeud p, sa racine,I d’une suite de sous-arbres (a1, a2, . . . , ak).
Les racines des arbres a1, a2, . . . , ak sont les fils de p
....
p
a1 a2 ak
Arbres : définition 3 (graphes)
Un arbre est un graphe connexe et sans cycle.
Arbres : définition 3 (graphes)
Un graphe avec des cycles
Arbres : définition 3 (graphes)
Un graphe non connexe
Arbres : définition 3 (graphes)
Un graphe non connexe
Arbres : définition 3 (graphes)
Graphe connexe et sans cycle : nb arêtes = nb sommets−1
Arbres : vocabulaire
descendant
ancetre
hauteur=5
niveaux
profondeur=2
racine
frère
branche : chemin à la racine
Arbres binaires
Chaque noeud a au plus 2 fils : le fils gauche et le fils droit
(sa racine est )
fils droit
sous−arbre droitnoeud
fils gauche
sous−arbre gauche
Arbres binaires
16
8
4
2
1
racine
no
mb
re d
e n
oe
ud
s
Arbre binaire complet :
I à la profondeur p : 2p noeuds
I nombre total de noeuds :h−1∑i=0
2i = 2h − 1
Un arbre binaire de hauteur h contient au plus 2h − 1noeuds(hauteur = nombre de niveaux)
Arbres binaires : représentation
Arbre vide : �
Arbre non vide : p = 〈 x ,G ,D 〉I x : information, étiquette,I G = filsG (p) : sous-arbre gauche de p,I D = filsD(p) : sous-arbre droit de p,
×
78 +
6x〈×, 〈78,�,�〉, 〈+, 〈x ,�,�〉, 〈6,�,�〉〉〉
Arbres binaires : implémentation
public class Node <T> {T val;Node filsG;Node filsD;
// constructeurs, getters, setters...
}
On utilisera null pour indiquer qu’il n’y a aucun noeud
Arbres binaires : implémentation
public class Arbre <T> {private Node racine;
public Arbre() {this.racine = null;
}
boolean estVide() {return (this.racine == null);
}}
Encapsulation : Arbre connaît sa racine
Arbres binaires : implémentation
12
1 7
91
14
67 82
11
91
racine
67
1
1411
82
7
12
Arbres binaires : implémentation
12
1 7
91
14
67 82
11
12
racine.filsG
racine
67
1
1411
82
7
91
racine.filsD.filsD
Arbres binaires : parcours en profondeur
Principe : parcourir récursivement le fils gauche puis le filsdroit
static public void parcours(Node node) {if (node != null) {
// traitement avantparcours(node.filsG);// traitement entre les deux
parcoursparcours(node.filsD);// traitement apres
}}
Arbres binaires : parcours préfixe
static public void parcours(Nodenode) {
if (node != null) {node.printNode();parcours(node. filsG ) ;parcours(node. filsD ) ;
}}
1
2
3 4
5
6
7
12 1 91 67 7 82 61
1
67
12
7
82
61
91
Arbres binaires : hauteur minimale
Soit a un arbre de n noeuds : hauteur(a) ≥ log2 n
Preuve. Par récurrence en utilisant la propriété
h(a) = 1 + max(h(a1), h(a2))
Supposons n1 ≥ n2, et donc n1 ≥ n/2.
Hypothèse : h(a1) ≥ log2 n1
donc h(a1) ≥ log2 (n/2) = log2 n − 1donc h(a) ≥ 1 + h(a1) ≥ 1 + log2 n − 1,
Conclusion : h(a) ≥ log2 n
n1 noeuds
a
n2 noeuds
a2a1
C’est aussi vrai si on considère n le nombre de feuilles.
Arbres binaires : hauteur minimale
Soit a un arbre de n noeuds : hauteur(a) ≥ log2 n
Preuve. Par récurrence en utilisant la propriété
h(a) = 1 + max(h(a1), h(a2))
Supposons n1 ≥ n2, et donc n1 ≥ n/2.
Hypothèse : h(a1) ≥ log2 n1
donc h(a1) ≥ log2 (n/2) = log2 n − 1donc h(a) ≥ 1 + h(a1) ≥ 1 + log2 n − 1,
Conclusion : h(a) ≥ log2 n
n1 noeuds
a
n2 noeuds
a2a1
C’est aussi vrai si on considère n le nombre de feuilles.
Arbres binaires : hauteur minimale
Soit a un arbre de n noeuds : hauteur(a) ≥ log2 n
Preuve. Par récurrence en utilisant la propriété
h(a) = 1 + max(h(a1), h(a2))
Supposons n1 ≥ n2, et donc n1 ≥ n/2.
Hypothèse : h(a1) ≥ log2 n1
donc h(a1) ≥ log2 (n/2) = log2 n − 1donc h(a) ≥ 1 + h(a1) ≥ 1 + log2 n − 1,
Conclusion : h(a) ≥ log2 n
n1 noeuds
a
n2 noeuds
a2a1
C’est aussi vrai si on considère n le nombre de feuilles.
Arbres binaires : hauteur minimale
Soit a un arbre de n noeuds : hauteur(a) ≥ log2 n
Preuve. Par récurrence en utilisant la propriété
h(a) = 1 + max(h(a1), h(a2))
Supposons n1 ≥ n2, et donc n1 ≥ n/2.
Hypothèse : h(a1) ≥ log2 n1
donc h(a1) ≥ log2 (n/2) = log2 n − 1
donc h(a) ≥ 1 + h(a1) ≥ 1 + log2 n − 1,
Conclusion : h(a) ≥ log2 n
n1 noeuds
a
n2 noeuds
a2a1
C’est aussi vrai si on considère n le nombre de feuilles.
Arbres binaires : hauteur minimale
Soit a un arbre de n noeuds : hauteur(a) ≥ log2 n
Preuve. Par récurrence en utilisant la propriété
h(a) = 1 + max(h(a1), h(a2))
Supposons n1 ≥ n2, et donc n1 ≥ n/2.
Hypothèse : h(a1) ≥ log2 n1
donc h(a1) ≥ log2 (n/2) = log2 n − 1donc h(a) ≥ 1 + h(a1) ≥ 1 + log2 n − 1,
Conclusion : h(a) ≥ log2 n
n1 noeuds
a
n2 noeuds
a2a1
C’est aussi vrai si on considère n le nombre de feuilles.
Arbres binaires : hauteur minimale
Soit a un arbre de n noeuds : hauteur(a) ≥ log2 n
Preuve. Par récurrence en utilisant la propriété
h(a) = 1 + max(h(a1), h(a2))
Supposons n1 ≥ n2, et donc n1 ≥ n/2.
Hypothèse : h(a1) ≥ log2 n1
donc h(a1) ≥ log2 (n/2) = log2 n − 1donc h(a) ≥ 1 + h(a1) ≥ 1 + log2 n − 1,
Conclusion : h(a) ≥ log2 n
n1 noeuds
a
n2 noeuds
a2a1
C’est aussi vrai si on considère n le nombre de feuilles.
Arbres binaires : hauteur minimale
Soit a un arbre de n noeuds : hauteur(a) ≥ log2 n
Preuve. Par récurrence en utilisant la propriété
h(a) = 1 + max(h(a1), h(a2))
Supposons n1 ≥ n2, et donc n1 ≥ n/2.
Hypothèse : h(a1) ≥ log2 n1
donc h(a1) ≥ log2 (n/2) = log2 n − 1donc h(a) ≥ 1 + h(a1) ≥ 1 + log2 n − 1,
Conclusion : h(a) ≥ log2 n
n1 noeuds
a
n2 noeuds
a2a1
C’est aussi vrai si on considère n le nombre de feuilles.
Arbres binaires de recherche
Un dictionnaire est un ensemble dynamique d’objetscomparables qui supporte les opérations suivantes :
insérer : ajout d’une nouvelle valeurrechercher : recherche d’une valeursupprimer : suppression d’une valeur donnée
Exemples : liste, tableau, arbre binaire de recherche,. . .
Objectifs : être efficace, utiliser peu d’espace
Arbres binaires de recherche
Soit E un ensemble muni d’une relation d’ordre total
Un arbre binaire étiqueté avec des éléments de E est un arbrebinaire de recherche s’il satisfait l’ordre infixe,
i.e. pour tout noeud p = 〈x ,G ,D〉I pour tout noeud q ∈ G , val(q) < x ,I pour tout noeud q ∈ D, val(q) > x .
Les éléments figurant dans l’arbre sont donc tous différents
Arbres binaires de recherche
> 66 < 66
p
8 16
26
67 69 94
88
35
17
29
25
23 28
32
3021
50
66
70
36
37
68
52
51
34
55
7
9 978044
71
56 81
22
27
Arbres binaires de recherche : parcours infixé
Le parcours infixé de l’arbre produit la suite ordonnée deséléments
7 8 9 16 17 21 22 23 25 26 27 28 29 30 32 34 35 36 37 ...
8 16
26
27 67 69 94
88
1
2 4
16
7
5
3 6 8
9
13
15
14
12
10
1117
35
6855 978044
71
56 81
22
17
9
29
25
23 28
32
3021
50
66
70
51
7
52
36
37
34
ABR : Recherche d’un élémentSupposons v ∈ a :I si e < val(a) alors e ∈ filsG (a)
I si e > val(a) alors e ∈ filsD(a)
< 34
> 22
< 29
> 25
< 28
recherche de la valeur 27
8 16
26
27 67 72
28 3021
50
66
55
34
32
74
73
88
7
36
37
68
51
52 94
80 97
22
8156
44
17
9
29
25
23
35
ABR : Recherche d’un élément
public static <T extends Comparable<T>> booleancontains(Node<T> node, T element) {
if (node == null)return false ;
if (element.equals(node.getVal()))return true;
if (element.compareTo(node.getVal()) < 0)return contains(node. filsG , element);
return contains(node. filsD , element);}
ABR : ajout d’un élément (insertion)
Insertion de la valeur 31
8 16
26
27 67 94
88
72
22
9
29
25
23 28
32
3021
50
66
69
56 8117
7
73
74
52
51
34
55 97804436
35
37
ABR : ajout d’un élément (insertion)
Insertion de la valeur 31
8 16
26
27 67 94
88
35 72
17
29
25
23 28
32
3021
50
66
69
37
36
51
7
73
74
5231
34
55 978044
56 81
22
9
ABR : ajout d’un élément (insertion)
public static <T extends Comparable<T>> Node add(T e,Node<T> node) {
if (node == null)return new Node<T>(e, null, null);
if (node.val .compareTo(e) > 0) {node. filsG = add(e, node. filsG ) ;
}else {
node. filsD = add(e, node. filsD ) ;}return node;
}
Arbres binaires de recherche : successeur
66 a un fils droit :
528 16
26
27 67 69 94
8851
35
son sous−arbre gauche
dernier fils gauche de
son successeur est 67
23
32
3021
50
66
70
7
6836
31
37
34
55 978044
71
56 81
22
17
9
29
25
28
Arbres binaires de recherche : successeur
32 n’a pas de fils droit :
528 16
26
27 67 69 94
8851
35
tel que 32 figure dans son sous−arbre gauche
son successeur est 34, premier ascendant de 32
25
28
32
3021
50
66
70
7
6836
31
37
34
55 978044
71
56 81
22
17
9
29
23
Arbres binaires de recherche : suppression
Cas 1 : le noeud n’a pas de fils : décrochage
8 16
26
27 67 69 94
88
35
51
17
29
25
23 28
32
3021
50
66
70
36
37
31
68
7
9
34
55 978044
71
56 81
22
52
Arbres binaires de recherche : suppression
Cas 1 : le noeud n’a pas de fils : décrochage
51
8 16
26
27 69 94
88
35
22
9
29
25
23 28
32
3021
50
66
7037
31
68
7
17
36
34
55 978044
71
56 81
52
Arbres binaires de recherche : suppression
Cas 2 : le noeud a un seul fils : décrochage
8 16
26
27 69 94
88
56
22
17
9
29
25
23 28
32
3021
50
66
70
68
7 71
81
35
36
37
31
34
55 978044
51
52
Arbres binaires de recherche : suppression
Cas 2 : le noeud a un seul fils : décrochage
8 16
26
27 69 94
88
44
56 81
22
17
9
29
25
23 28
32
3021
50
66
70
68
7
80
71
36
37
3531
34
55 97
51
52
Arbres binaires de recherche : suppression
Cas 2 : le noeud a un seul fils : décrochage
8 16
26
27 94
88
69
68 9744
71
56 81
22
29
25
23 28
32
30
50
66
7037
55 80
3531
219
17
36
34
52
51
Arbres binaires de recherche : suppression
Cas 3 : le noeud a deux fils
des plus grands
plus petit
a supprimer
26
27 94
88
688
35
81
29
25
23 28
32
30
50
70
34
71
56
22 57
36
31
37
69
17
9 21
55 97804416
51
52
Arbres binaires de recherche : suppression
Cas 3 (deux fils) : copie du plus petit des plus grands
26
27 94
88
688
35
56
22
29
25
23 28
32
30
50
7021 37
44
71
81
57
31
36
69
17
9
34
55 978016
52
51
Arbres binaires de recherche : suppression
Cas 3 (deux fils) : copie du plus petit des plus grands
26
27 94
88
688
35
56
22
29
25
23 28
32
30
50
7021 37
44
71
81
68
31
36
69
17
9
34
55 978016
52
51
Arbres binaires de recherche : suppression
Cas 3 (deux fils) : décrochage
26
27 94
88
688
35
56
22
29
25
23 28
32
30
50
7021 37
44
71
81
68
31
36
69
17
9
34
55 978016
52
51
Arbres binaires de recherche : suppression
Cas 3 (deux fils) : décrochage
26
27 94
88
8
35
44
56 81
22
29
25
23 28
32
30
50
7037
9780
71
68
36
31
17
9 21
69
34
5516
51
52
Arbres binaires de recherche : suppression
public static <T extends Comparable<T>>Node remove(T e, Node<T> node) {
if (node.val.compareTo(e) > 0) // e est dans le filsGnode.filsG = remove(e, node.filsG) ;
else if (node.val.compareTo(e) < 0)node.filsD = remove(e, node.filsD) ;
else if (node.filsG == null)
else if (node.filsG == null)
return (node.filsD ;
return node.filsD ;
else if (node.filsD == null)
else if (node.filsD == null)
return (node.filsG ;
return node.filsG ;
else {node.val = node.filsD.getMin() ;node.filsD = removeLeftmostNode(node.filsD) ;
}return node ;
}
Arbres binaires de recherche : suppression
public static <T extends Comparable<T>>Node remove(T e, Node<T> node) {
if (node.val.compareTo(e) > 0)node.filsG = remove(e, node.filsG) ;
else if (node.val.compareTo(e) < 0) // e est dans le filsDnode.filsD = remove(e, node.filsD) ;
else if (node.filsG == null)
else if (node.filsG == null)
return (node.filsD ;
return node.filsD ;
else if (node.filsD == null)
else if (node.filsD == null)
return (node.filsG ;
return node.filsG ;
else {node.val = node.filsD.getMin() ;node.filsD = removeLeftmostNode(node.filsD) ;
}return node ;
}
Arbres binaires de recherche : suppression
public static <T extends Comparable<T>>Node remove(T e, Node<T> node) {
if (node.val.compareTo(e) > 0)node.filsG = remove(e, node.filsG) ;
else if (node.val.compareTo(e) < 0)node.filsD = remove(e, node.filsD) ;
else if (node.filsG == null) // node.val = e, pas de filsG
else if (node.filsG == null)
return node.filsD ;
return node.filsD ;
else if (node.filsD == null)
else if (node.filsD == null)
return (node.filsG ;
return node.filsG ;
else {node.val = node.filsD.getMin() ;node.filsD = removeLeftmostNode(node.filsD) ;
}return node ;
}
Arbres binaires de recherche : suppression
public static <T extends Comparable<T>>Node remove(T e, Node<T> node) {
if (node.val.compareTo(e) > 0)node.filsG = remove(e, node.filsG) ;
else if (node.val.compareTo(e) < 0)node.filsD = remove(e, node.filsD) ;
else if (node.filsG == null)return node.filsD ;
else if (node.filsD == null) // node.val = e, pas de filsD
else if (node.filsD == null)
return node.filsG ;
return node.filsG ;
else {node.val = node.filsD.getMin() ;node.filsD = removeLeftmostNode(node.filsD) ;
}return node ;
}
Arbres binaires de recherche : suppression
public static <T extends Comparable<T>>Node remove(T e, Node<T> node) {
if (node.val.compareTo(e) > 0)node.filsG = remove(e, node.filsG) ;
else if (node.val.compareTo(e) < 0)node.filsD = remove(e, node.filsD) ;
else if (node.filsG == null)return node.filsD ;
else if (node.filsD == null)return node.filsG ;
else { // node.val = e, deux filsnode.val = node.filsD.getMin() ;node.filsD = removeLeftmostNode(node.filsD) ;
}return node ;
}
Arbres binaires de recherche : suppression
public static Node removeLeftmostNode(Node root) {
Node pere = null;Node p = root;
while (p. filsG != null) {pere = p;p = p. filsG ;
}if (pere == null)
return root . filsD ;
pere. filsG = p.filsD ;return root ;
}
Arbres binaires de recherche : coûts
Structure insertion recherche suppression
tableau O(1) O(n) O(n)tableau trié O(n) O(log n) O(n)liste O(1) O(n) O(n)ABR O(h) O(h) O(h)
où h est la hauteur de l’arbre :log n dans le meilleur des cas, n dans le pire des cas