Arbres 234 Recherche dans un (sous)arbre-2.3.4 Recherche

Arbres 234
15
• Arbre de recherche dont les nœuds
contiennent 1, 2 ou 3 éléments triés et dont
toutes les feuilles sont à la même hauteur
• Un nœud contenant x1<…<xk-1 a k sousarbres tels que :
4 10 13
1 3
7 8
30 40
11 12
– les éléments du 1er sous-arbre sont ≤ x1,
– tous les éléments du ième sous-arbre sont > xi-1
et ≤ xi,
– tous les éléments du kième sous-arbre sont > xk-1
14
50 60
35
20 28
10 noeuds, 18 éléments
268
269
Recherche dans un
(sous)arbre-2.3.4
Recherche dans un
(sous)arbre-2.3.4
• Même principe que dans un (sous) arbre
binaire de recherche
• On compare x avec les éléments contenus
dans la racine de A
– si la recherche se termine sur une feuille qui
ne contient pas x, alors x n’appartient pas à A
– s’il existe j tel que x=xj, alors x est trouvé
– si x<x1 recherche dans le premier sous-arbre de A
– si xj<x<xj+1 recherche dans le (j+1) ième sousarbre de A
– si x>max(xi), recherche dans le dernier sous-arbre
• Recherche en O(lg n) puisque l’arbre est
équilibré par construction
270
271
Insertion dans un
(sous) arbre 234
Insertion dans un
(sous) arbre 234
• Pour insérer x
– On descend jusqu’à la feuille où x doit s’insérer
(même approche que pour la recherche)
– Si la feuille est pleine on commence par
l’éclater….
…
s1
s2
s3
…,e2, …
éclatement
e1,e2,e3
e1
s4
s1
• Lors d’un éclatement, l’élément du milieu
remonte dans le père
• Si le père est plein, on l’éclate à son tour…
…
e1,e2,e3
e3
s2
s3
s4 272
s1
s2
s3
…,e2, …
éclatement
e1
s4
s1
e3
s2
s3
s4 273
1
Exemple
Insertion dans
un (sous) arbre 234
Insertion avec éclatement en remontée
Insertion successive de 4, 35, 10, 13, 3, 30,15,12, 7, 40, 20,
11, 6, à partir de l’arbre vide
• 2 stratégies possibles
– Éclatement en remontée (seulement quand il
devient indispensable)
– Éclatement (préventif) à la descente des
nœuds pleins
4
10
35
4
4 35
4 10 35
A cette étape, A est équivalent à l’arbre binaire :
10
4
35
274
13
13
10
4
35
275
15
10
4
12
3
3 4
3 4
30
10
35
13
3 4
13 35
15
10 30
10 30
13 15
3 4
7
10 30
35
12 13 15
3 4 7
10 30
12 13 15
13 30 35
3 4
40
3 4 7
10 30
12 13 15
35 40
276
3 4 7
20
3 4 7
35
10
13 35
20
35
277
6
10 13 30
12
15
13
35 40
4 10
10 13 30
12
15 20
3
7
30
12
15 20
35 40
35 40
6
13
11
3 4 7
10 13 30
11 12
15 20
4 10
30
35 40
3
278
6 7
12
15 20
35 40
279
2
4
Insertion avec éclatement à la descente
Avec la méthode précédente, éclatements en cascade
possibles (éventuellement sur toute la hauteur de l’arbre si le
chemin suivi n’est formé que nœuds pleins)
4
13
Pour éviter ce phénomène, on travaille sur des arbres-2.3.4
ne contenant jamais deux nœuds pleins à la suite :
-> au plus un éclatement lors d’une insertion.
Réalisation de cette condition par éclatement à la descente :
pour insérer un élément, on parcourt un chemin dans l’arbre
à partir de la racine et on fait éclater les nœuds pleins au fur
et à mesure de leur rencontre.
10
35
4 35
3
10
15
10
13 35
10 30
35
13 15
3 4
13 30 35
3 4
10
3 4
13 35
4
30
4 10 35
280
12
3 4
7
10 30
12 13 15
35
3 4 7
281
11
10 30
12 13 15
13
10
35
3 4 7
40
3 4 7
15 20
11 12
35 40
10 30
12 13 15
35 40
6
13
4 10
20
10 13 30
3 4 7
30
12
15 20
3
6 7
30
11 12
35 40
15 20
35 40
282
Les transformations de rééquilibrage à la descente sont
purement locales : lorsqu’un nœud éclate, son père ne peut
être un nœud plein car sinon on l’aurait fait éclater avant ; il
n’y a donc que 2 cas possibles, suivant que le père contient 1
ou 2 éléments
Ces transformations n’augmentent pas la hauteur de l’arbre,
sauf si on éclate la racine ; dans ce cas la hauteur augmente
de 1
Analyse de la complexité
L’insertion est également en Θ(log n ) : dans le cas d’un
éclatement à la montée ou à la descente, on opère toujours sur
un chemin de la racine à une feuille de l’arbre
284
283
Représentation des arbres-2.3.4
Pour représenter les différents types de nœuds ; on peut
choisir une représentation « maximale » :
P0
e1
P1
e2
P2
e3
P3
On peut également opter pour une implantation équivalente
: les arbres binaires Rouge / Noir
285
3
Tas binaire (heap)
Exemple de tas-min :
• Structure de donnée pouvant être représentée par
un arbre binaire vérifiant deux contraintes
Exemple de tas-max :
35
1
– c'est un arbre binaire complet : tous les niveaux excepté le
dernier doivent être totalement remplis
– les valeurs des nœuds satisfont à une propriété de tas
2
5
• La propriété dépend du type de tas
– Dans un tas max, pour tout nœud interne x, la valeur de x est
supérieure aux valeurs de chacun des fils de x
– Dans un tas min, pour tout nœud interne x, la valeur de x est
inférieure aux valeurs de chacun des fils de x
20
17
4
8
7
15
5
13
12
6
9
6
3
2
7
• Dans un tas max (resp. min) la valeur maximale (resp.
minimale) est toujours à la racine
286
• Permet d’implémenter le type abstrait file de priorité
– insérer un élément
– lire puis supprimer l'élément ayant la plus grande/petite valeur
– tester si la file de priorité est vide ou pas
• On insère x à la prochaine position libre, c-à-d la position libre la plus
à gauche possible sur le dernier niveau (pour une implémentation en
tableau, il s’agit de la première case vide)
• On effectue si nécessaire une suite d’échanges pour rétablir la
propriété de tas : tant que x n'est pas la racine de l'arbre et que x est
strictement inférieur à son père on échange les positions entre x et
son père.
– L’élément racine est à l’indice 1
– Les fils gauche et droit de l’élément d’indice i sont situés aux
indices respectifs 2i et 2i+1
– Le père de l’élément d’indice i est situé à l’indice i/2
– Complexité :
• Lors de l'algorithme ci-dessus on effectue au plus h échanges, où h
est la hauteur de l’arbre. Dans un arbre binaire complet, h = log2n, où
n est le nombre d’éléments. Donc, le coût d’insertion est en O(log2n) .
…
2
4
5
8
15
…
6
20
7
1
2
3
4
5
6
7
8
9
• Insertion d’un élément x dans un tas-min
– Deux étapes :
• Un tas binaire étant un arbre complet, il peut être
représenté par un tableau dans lequel :
1
287
288
• Suppression de l’élément racine dans un tas-min
289
• Recherche de l’élément minimum dans un tas-min
– On souhaite retirer la racine de notre tas binaire (c'est-à-dire le
minimum de notre tas selon la relation d'ordre associée)
– Il est toujours situé à la racine
– L’accès se fait en temps constant : O(1)
– Deux étapes :
• On supprime la racine et on met à sa place le nœud qui était en
dernière position de l'arbre binaire (donc le nœud le plus à droite sur
le dernier niveau) que l'on notera x.
• On effectue une suite d’échanges pour rétablir la propriété de tas :
tant que x a des fils et que x est strictement supérieur à un de ses fils,
on échange les positions entre x et le plus petit de ses fils.
• Attention à ne pas confondre le tas binaire avec l’arbre binaire
de recherche !
– Dans un tas-min, l’élément minimum est à la racine
– Dans un arbre binaire de recherche, l’élément minimum est la feuille la
plus à gauche (rappel : accès en O(log2 n) )
– Complexité :
• Comme pour l’insertion, on effectue au plus h échanges, où h est la
hauteur de l’arbre. Donc, le coût de suppression de la racine est en
O(log2n) .
290
291
4
Graphe
Définitions
• Un graphe non orienté est un couple <S, A>
où
• Idée générale
– Notion plus générale que la notion d’arbre
– Arbre = cas particulier d’un graphe
• S est un ensemble fini de sommets
• A est un ensemble fini de paires de sommets,
appelées arêtes
• Graphe
– Modélisation de relations binaires entre des
éléments
2
1
4
3
292
S = { 1, 2, 3, 4 }
A = { {1, 2}, {1, 3}, {1, 4}, {2, 4} }
Définitions
Définitions
• Un graphe orienté est un couple <S, A>
où
• Il arrive qu’une information de coût soit
associée aux arcs (ou arêtes), voire aux
nœuds (resp. sommets)
• Un graphe valué est un triplet <S, A, C> où
– S est un ensemble fini de nœuds
– A un ensemble fini de paires ordonnées de
nœuds, appelées arcs
2
4
3
5
293
– S est un ensemble fini de nœuds (ou
sommets),
– A un ensemble fini d’arcs (ou d’arêtes)
– C une fonction de A dans R appelée fonction
de coût
1
S = { 1, 2, 3, 4, 5 }
A = { (1, 2), (1, 3), (2, 3), (3, 2), (3, 2), (4, 4), (4, 5) }
294
295
Exemples
Exemples
• GPS : Localités reliées par des voies de
communication (routes, voies ferrées, lignes
aériennes, …), la fonction de coût pouvant
correspondre à une distance, ou un temps de
parcours, le prix du trajet...
→ Recherche de plus courts chemins
• Représentation de localités reliées par des
canalisations (eau, gaz, électricité) caractérisées
par leur débit et leur capacité. Certains nœuds
pouvant correspondre à des stations de
distribution ou de pompage
→ Problème de flux maximal
Lille
Réseau
Paris
Brest
2
Nantes
Lyon
2
Nice
3
2
3 3
6
Toulouse
4
Pipelines
8
296
297
5
Algorithmes
Exemples
• Explorations
• Représentation
– des configurations possibles d’un jeu tactique par des
nœuds,
– des coups légaux par des arcs permettant de passer
d’une configuration à une autre
→Recherche position gagnante, séquences
de coups forcés, etc.
– Parcours en profondeur, en largeur
– Tri topologique
– Composantes fortement connexes, ...
• Recherche de chemins
– Clôture transitive
– Chemin de coût minimal
– Circuits eulériens et hamiltoniens, ...
• Arbres couvrants
– Algorithmes de Kruskal et Prim
298
299
Terminologie
Algorithmes
• Etant donné un arc (x, y)
– x est l’extrémité initiale de l’arc,
– y l’extrémité terminale
• Réseaux de transport
– Flot maximal
• Divers
• On dit que
– Coloration d'un graphe
– Test de planéarité, ...
2
4
1
3
– x et y sont adjacents
– y est un successeur de x
– x est un prédécesseur de y
• Les arcs qui partent d’un nœud lui sont
incidents extérieurement, ceux qui y
arrivent lui sont incidents intérieurement
300
Terminologie
Terminologie
• Dans un graphe orienté (resp. non orienté) G,
on appelle degré d’un nœud (resp. sommet) x et
on note d°(x) le nombre d’arcs (resp. d’arêtes)
dont x est une extrémité
• Demi-degré extérieur d’un nœud : nombre
d’arcs incidents extérieurement
• Demi-degré intérieur d’un nœud : nombre
d’arcs incidents intérieurement
2
4
1
3
301
302
• Dans un graphe orienté (resp. non orienté) G,
on appelle chemin (resp. chaîne) de longueur l
une suite de l+1 nœuds (resp. sommets) (s0, …,
sl) tels que
∀i,0 ≤ i ≤ l − 1, s i → s i +1 est un arc (resp. arête) de G
• Un chemin (resp. une chaîne) est dit
élémentaire s’il ne contient pas plusieurs fois le
même nœud (resp. sommet)
• Un circuit (resp. un cycle) est un chemin (resp.
une chaîne) tel (resp. telle) que les 2 sommets
aux extrémités coïncident
303
6
Terminologie
• Un graphe orienté est dit fortement connexe si
pour toute paire de noeuds distincts (u,v) il existe
un chemin de u vers v et un chemin de v vers u.
• Un graphe non orienté est dit connexe si pour
toute paire de sommets distincts (u,v) il existe une
chaîne entre u et v
2
4
1
3
Terminologie
• Un arbre est un graphe non orienté, connexe et
sans cycle
• Etant donné un graphe orienté G = <S,A>, on
appelle racine de G un nœud r de S tel que tout
autre nœud puisse être atteint par un chemin
d’origine r
• On appelle arborescence un graphe orienté
admettant une racine et tel que le graphe non
orienté associé soit un arbre
304
Type Abstrait Graphe
305
Représentations possibles
• Prévoir des procédures
– d’initialisation, de testament, d’affectation
– d’ajout / de retrait d’un nœud ou d’un arc
• Prévoir des fonctions
– testant l’existence d’un nœud ou d’un arc
• Prévoir des routines
– Permettant d’itérer
• Matrices d’adjacence
– Ensemble des arcs représenté par un tableau
de booléens de dimension n*n, où n est le
nombre de nœuds
1
1
2
1
3
4
3 4
3
4
F F F F
2
• sur l’ensemble des arcs issus d’un nœud
(ième arc)
• Sur l’ensemble des successeurs d’un nœud
(ième successeur)
2
F V V F
V F F V
F V F F
– De connaître l’origine (resp. l’extrémité) d’un 306
arc
– Si le graphe est valué on remplace les
booléen par le coût associé à l’arc
(en réservant une valeur spécifique pour
signifier l’absence d’arc)
– Types
307
– Quelle propriété est vérifiée par la matrice
d’adjacence d’un graphe non orienté?
– Quel est la complexité du parcours des
successeurs d’un nœud?
• Graphe = tableau [1…N x 1…N] de valeurs
– Utilisable si pas plus d’un arc entre 2 nœuds
308
309
7
Représentations possibles
• Matrice d’adjacence
• Listes d’adjacence
– Avantages :
• Ajout, suppression et test d’existence d’un arc en
Θ(1)
• Simplicité d’implantation
– Inconvénients
• Parcours de tous les successeurs ou de tous les
prédécesseurs d’un sommet en Θ(n)
• Une consultation de l’ensemble des arcs du
graphe requiert un temps en Θ(n2) et cette
représentation exige un espace mémoire de Θ(n2)
• Représentation « figée » (réallocation nécessaire si
ajout ou suppression de sommet)
• On représente les nœuds et les arcs
• On associe à chaque nœud la liste de ses arcs
incidents extérieurement (et éventuellement, la liste
de ses arcs incidents intérieurement)
• On associe à chaque arc les nœuds extrémités
initiale et finale
310
Représentations possibles
311
Représentations possibles
• Listes d’adjacences : structures
• Listes d’adjacence
structure Graphe {
nœuds : tableau/liste de Nœud
arcs : tableau/liste d’Arc
}
structure Nœud {
.... /* Attributs du nœud */
arcs_inc_ext : tableau/liste de pointeurs sur Arc
arcs_inc_int : tableau/liste de pointeurs sur Arc
}
structure Arc {
val : entier ou réel
extremite_initiale, extremite_finale : pointeur sur Nœud
}
– Avantages
• Cette représentation utilise un espace mémoire en Θ(n+p)
pour un graphe avec n nœuds et p arcs
• Accès optimisé aux successeurs et prédécesseurs d’un
nœud : Θ(deg+) et Θ(deg-)
• Ajout et suppression de nœud sans réallocation complète
de la structure
– Inconvénient
• Structure plus délicate à implanter et à maintenir que la
matrice d’adjacence
312
Parcours de graphe
313
313
Parcours de graphe
• But : parcourir l’ensemble des nœuds du
graphe, pour effectuer une certaine action en
chacun des nœuds (ex. affichage
d’information)
• Exploration d’un graphe plus compliquée que
celle d’un arbre, mais elle s’en inspire!
• Il existe 2 grandes stratégies de parcours :
• Lors du parcours, on matérialisera l’état
d’un nœud par une couleur
– Blanc : nœud non découvert
– Gris : nœud découvert
– Noir : nœud dont tous les successeurs ont été
parcourus
– le parcours en profondeur (depth-first search)
– le parcours en largeur (breadth-first search)
314
315
8
Parcours en profondeur (DFS)
Parcours en profondeur
• On considère un graphe orienté dont tous
les nœuds sont initialement non découverts
(blanc)
• Le parcours en profondeur consiste à
– choisir un nœud de départ s et le marquer
comme découvert (gris)
– suivre un chemin issu de s aussi loin que
possible en marquant les nœuds au fur et à
mesure qu’on les découvre
– en fin de chemin, revenir au dernier choix fait
et prendre une autre direction.
316
procédure DFS(donnée-résultat G : Graphe)
variable
u : Nœud
Début
pour tout Nœud u de G faire
u.couleur← blanc; u.père ← nil
finpour
temps ← 0
pour tout Nœud u de G faire
si u.couleur = blanc alors
u.découverte ←temps; temps ++
u.couleur← gris
DFS_visite(G,u)
finsi
finpour
fin
317
Parcours en profondeur (DFS)
Procédure DFS_visite(donnée-résultat G : graphe, u : Nœud)
variable
v : Nœud
Début
pour tout Nœud v successeur de u faire
si v.couleur = blanc alors
v.découverte ←temps; temps ++
v.couleur← gris
v.père←u
DFS_visite(G, v)
finsi
finpour
u.couleur ← noir
u.fin ← temps; temps++
318
fin
• On obtient l’ordre de parcours suivant des
nœuds en partant de 1 : 1, 3, 2, 6, 5, 7,
4, 9, 8
7
1
5
6
3
2
• Effectuer le parcours en profondeur sur le
graphe suivant
7
1
5
6
3
2
8
4
9
319
Parcours en profondeur (DFS)
• Complexité en temps :
O(N+M) où N est le nombre de nœuds et
M le nombre d’arcs
– en effet, un nœud n’est empilé qu’une seule
fois (passage de blanc à gris) et chaque arc
n’est traité qu’une seule fois à partir de son
extrémité initiale
8
4
• Complexité en espace : O(N)
9
– comme un nœud est empilé au plus 1 fois, la
pile d’appel a une profondeur en O(N)
320
321
9
Parcours en largeur (BFS)
• Pour un sommet de départ s on commence
par visiter tous les successeurs de s avant
de visiter les autres descendants de s
• Le parcours en largeur consiste à visiter
d’abord
• tous les nœuds à distance 1 de s,
• puis ceux à distance 2 qui n’ont pas été visités,
• et ainsi de suite …
• Le parcours en largeur permet donc de
résoudre les problèmes de plus court
chemin dans un graphe non valué
Parcours en largeur (BFS)
• Pour programmer l’algorithme, on utilise
une structure de file:
– lorsque à partir de s, on s’apprête à visiter ses
successeurs non marqués, il est nécessaire de
les ranger successivement dans une file
– la recherche repartira ainsi de chacun des
successeurs de s, à partir du premier.
322
323
Parcours en largeur (BFS)
procédure BFS(donnée-résultat G: graphe, s : noeud)
variables
u,v : nœud ; F : file
début
pour tout noeud u ≠ s faire
u.couleur←blanc; u.père ← nil; u.dist ← ∞
finpour
s.couleur ← gris; s. père ← nil; s.dist ← 0;
initialise_file_vide(F); enfile(F,s)
tant que non est-vide(F) faire
u ← tête(F);
pour tout noeud v successeur de u faire
si v.couleur=blanc alors
v.couleur ← gris; v.père ← u; v.dist ← u.dist +1;
enfile(F,v)
finsi
finpour
défile(F); u.couleur ← noir
fintantque
fin
• Effectuer le parcours en largeur sur le
graphe suivant
1
5
6
3
2
1
5
6
3
2
8
4
9
324
325
• Complexité en temps : O(N+M)
où N est le nombre de nœuds et M le
nombre d’arcs
• Les sommets sont visités dans l’ordre
1, 3, 5, 6, 7, 2, 8, 4, 9
7
7
– en effet, un sommet n’est mis dans la file
qu’une seule fois (passage de blanc à gris) et
les arêtes sont toutes parcourues 1 fois
(découverte des voisins)
8
4
• Complexité en espace : O(N)
la file a une longueur au plus en O(N) (si s
est connecté à tous les autres sommets)
9
326
327
10
• En fait, parcours en largeur et en profondeur
s’inscrivent dans une même stratégie
générale d’exploration des nœuds du graphe
• Ils diffèrent suivant que les successeurs d’un
nœud seront rangés dans une pile ou une file
328
11