CSI2510 Structures de données et algorithmes Automne 2009

publicité
CSI2510
Structures de données et
algorithmes
Arbres couvrants minimaux
1
Arbre couvrant minimal (Minimum spanning
tree)
Définitions
L'algorithme de Prim-Jarnik
L'algorithme de Kruskal
CSI2510 - ACM
2
Arbre couvrant minimal
Sous-graphe couvrant
 Sous-graphe d’un graphe G
contenant tous les sommets de
G
ORD
1
Arbre couvrant
 Sous-graphe couvrant qui est un
arbre
6
9
 Arbre couvrant d’un graphe
pondéré avec la somme
minimale de poids des arêtes
constituant l'arbre
 Réseaux informatiques
 Réseaux routiers
PIT
DEN
Arbre couvrant minimal (ACM)
Applications
10
8
CSI2510 - ACM
3
DCA
STL
4
DFW
7
5
2
ATL
3
ACM versus PCC
ORD
ORD
9
1
6
9
7
3
8
DCA
5
PIT
DEN
STL
4
DFW
1
PIT
DEN
9
9
2
DFW
7
3
DCA
STL
4
8
ATL
6
5
2
ATL
Arbre des plus courts chemin
Arbre couvrant minimal
CSI2510 - ACM
4
4
Propriété des cycles
 Soit T un arbre couvrant minimal
d’un graphe pondéré G
 Soit e une arête de G
n’appartenant pas à T et soit C le
cycle obtenu lorsqu’on ajoute e à
T
 Pour chaque arête f dans C,
poids(f)  poids(e)
Preuve:
Par contradiction
 Si poids(f) > poids(e) nous
pouvons obtenir un arbre
couvrant de plus petit poids en
remplaçant e par f
f
2
6
8
4
C
9
3
e
8
7
7
Remplacer f avec e produit un
meilleur arbre couvrant
f
2
6
8
4
C
9
3
8
e
7
7
CSI2510 - ACM
5
Propriété de partition
Propriété de partition:
U
Considérons une partition des
sommets de G en deux ensembles U
et V. Soit e une arête de poids
minimal entre U et V. Alors, il existe
un arbre couvrant minimal de G
contenant e
Preuve:
Soit T un arbre couvrant minimal de G
Si T ne contient pas e, soit C le cycle
formé par l’addition de e à T et soit f une
arête de C entre U et V
Par la propriété de cycles,
poids(f)  poids(e)
Alors, poids(f) = poids(e)
Nous obtenons un autre ACM en
remplaçant f par e
CSI2510 - ACM
f
V
7
4
9
5
2
8
8
3
e
7
V
Remplacer f avec e
donne un autre ACM
U
f
2
7
4
9
5
8
8
e
3
7
6
L’algorithme de Prim-Jarnik
L'algorithme de Prim-Jarnik pour calculer un ACM est
similaire à l'algorithme de Dijkstra
Nous supposons que le graphe est connexe
Nous choisissons un sommet arbitraire s et nous faisons
grossir l’ACM comme un nuage de sommets, commençant
de s
Nous emmagasinons avec chaque sommet v une étiquette
d(v) représentant le plus petit poids d'une arête reliant v à un
sommet du nuage (au lieu de la somme totale des poids sur
un chemin du sommet de départ jusqu’à v dans Dijkstra)
CSI2510 - ACM
7
L’algorithme de Prim-Jarnik
Pour chaque étape
 Nous ajoutons au nuage le sommet extérieur u ayant la
plus petite étiquette de distance
 Nous mettons à jour les étiquettes des sommets adjacents
àu
CSI2510 - ACM
8
L’algorithme de Prim-Jarnik
Utiliser une file à priorité Q dont les clés sont les étiquettes D, et dont
les éléments sont des paires sommet-arête
 Clé : distance
 Élément: (sommet, arête de poids minimal)
Tout sommet v peut être le sommet de départ (D[v] =0)
On initialise toutes les valeurs de D[u] à “infini”, mais nous
initialisons aussi E[v] (l’arête associé à v) à “null”
Retourne l’arbre recouvrant minimal T.
Nous pouvons réutiliser le code produit par Dijkstra, et ne changer que quelques parties. Observons
le pseudo-code....
CSI2510 - ACM
9
Algorithm PrimJarnik(G):
Entrée: Un graphe pondéré G.
Sortie: Un ACM T pour G.
Choisir un sommer v de G
{bâtir l’arbre à partir de v}
T  {}
D[v]  0
E[v]  null
Pour chaque sommet u ≠ v faire
D[u]  ∞
Soit Q une file à priorité contenant des sommets avec les étiquettes D comme clé
Tant que Q n’est pas vide
(u,E(u))  Q.removeMinElement()
ajouter le sommet u et l’arête E[u] à T
Pour chaque sommet z adjacent à u et dans Q
{effectuer la relaxation de l’arête (u, z) }
if poids(u, z) < D[z] then
D[z] weight(u, z)
E[z]  (u, z)
mettre à jour D[z]
retourner l’arbre T
CSI2510 - ACM
10
Prim-Jarnik: Exemple
2
D
7
4
9
8
C
5
F
8
8
A
E
2
0
A
2
F
8

2
3
E
7
9
5
C
5
F
8
E
7
0
CSI2510 - ACM
A
7
7
B
4
9
5
C
5
F
8
8
7
D
7

3
7
9
5
C
4
8
4
5
B
2
7
B
8
A
D
7

7
D
7
3
7
2
0
2
B
2
0

3
E
7
7
11
4
Prim-Jarnik: Exemple
2
2
B
4
9
5
C
5
0
F
8
8
A
D
7
7
3
E
7
4
3
2
2
B
4
9
5
C
5
0
CSI2510 - ACM
F
8
8
A
D
7
7
3
E
7
4
3
12
ACM versus PCC
A
8
0
4
2
B
8
7
3

2
C
8
1

F
3
2
E
5

5
0
4
2 1
C
7
B
4
PRIM
(Minimum Spanning Tree)
A
8
2
8
D
9
E
Djkstra
(Shortest Path Spanning Tree)
A
2
D
4
3
B
7
7
8
5

2
11
CSI2510 - ACM
4
2
9
F
0
C
3
E
 3
2
1
D
1
4
9
F
5
 9
13
Prim-Jarnik
L’algorithme applique la propriété des cycles
Soit (u,v) l’arête minimale pour une itération donnée.
S’il y a un ACM ne contenant pas (u,v), alors (u,v)
complète un cycle. Puisque (u,v) a été préférée à toute
autres arête connectant v au groupe, elle doit avoir un
poids inférieur ou égal au poids de l’autre arête. Un
nouveau ACM peut être formé par permutation
CSI2510 - ACM
14
Prim-Jarnik: Analyse de complexité
Opérations sur les graphes:
 Méthode incidentEdges est appelée une fois pour chaque
sommet
Opérations d’étiquetage:
 Nous plaçons/obtenons les étiquettes du sommet z O(deg(z))
fois
Opérations de file de priorité (implémenté par un monceau):
 Chaque sommet est inséré une fois et enlevé une fois de la file à
priorité, où chaque insertion ou suppression prend O(log n)
 La clé d'un sommet w dans la file à priorité est modifiée au plus
deg(w) fois, où chaque changement de clé prend O(log n)
CSI2510 - ACM
15
Prim-Jarnik: Analyse de complexité
On effectue un retrait du monceau pour chaque nœud O(nlogn)
Pour chaque nœud v, il faut mettre à jour tous ses voisins (et les
réinsérer dans le monceau) O(deg(v)logn) par noeud; donc pour tous
les noeuds: O(2mlogn)
Rappelez-vous que Sv deg(v) = 2m
L’algorithme de Prim-Jarnik est exécuté en O((n + m) log n)
si le graphe est représenté par la structure de liste d’adjacence (et en
utilisant un monceau)
Le temps d’exécution est O(m log n) parce que le graphe est
connexe
CSI2510 - ACM
16
Dijkstra vs. Prim-Jarnik
Algorithm DijkstraShortestPaths(G, s)
Q  new heap-based priority queue
for all v  G.vertices()
if v = s
setDistance(v, 0)
else
setDistance(v, )
setParent(v, )
l  Q.insert(getDistance(v), v)
setLocator(v,l)
while !Q.isEmpty()
u  Q.removeMin()
for all e  G.incidentEdges(u)
z  G.opposite(u,e)
r  getDistance(u) + weight(e)
if r < getDistance(z)
setDistance(z,r)
setParent(z,e)
Q.replaceKey(getLocator(z),r)
Algorithm PrimJarnikMST(G)
Q  new heap-based priority queue
s  a vertex of G
for all v  G.vertices()
if v = s
setDistance(v, 0)
else
setDistance(v, )
setParent(v, )
l  Q.insert(getDistance(v), v)
setLocator(v,l)
while !Q.isEmpty()
u  Q.removeMin()
for all e  G.incidentEdges(u)
z  G.opposite(u,e)
r  weight(e)
if r < getDistance(z)
setDistance(z,r)
setParent(z,e)
Q.replaceKey(getLocator(z),r)
CSI2510 - ACM
17
L’algorithme de Kruskal
Chaque sommet est emmagasiné initialement comme son propre
groupe.
A chaque itération, l’arête de poids minimal dans le graphe est
ajoutée à l'arbre couvrant si elle relie 2 groupes distincts.
L'algorithme se termine quand tous les sommets sont dans le
même groupe.
Ceci est une application de la propriété de partition!
Si l’arête minimale pour une itération donnée est (u,v), alors
si nous considérons une partition de G avec u dans un
groupe et v dans l’autre, alors la propriété de partition dit
qu’il doit y avoir un ACM contenant (u,v)
CSI2510 - ACM
18
L’algorithme de Kruskal
Une file à priorité
emmagasine les arêtes
extérieures (hors du nuage)
 clé: poids
 élément: arête
À la fin de l’algorithme
 On se retrouve avec un
nuage qui entoure
l’ACM
 Un arbre T qui est notre
ACM
Algorithm KruskalMST(G)
Pour chaque sommet V dans G faire
définir Cloud(v) de  {v}
Soit Q une file à priorité.
Insérer toutes les arête dans Q en
utilisant leur poids comme clé
T
Tant que T a moins que n-1 sommets
Faire
sommet e = Q.removeMin()
Soit u, v les extrémités de e
Si Cloud(v)  Cloud(u) alors
ajouter arête e à T
Fusionner Cloud(v) et Cloud(u)
return T
CSI2510 - ACM
19
Structure de données pour l’algorithme
de Kruskal
L’algorithme maintient une forêt d’arbres
Une arête est acceptée, si elle relie deux arbres distincts
Nous avons besoin d’une structure de données qui maintient une
partition c.-à-d. une collection d’ensembles disjoints, avec les
opérations:
find(u): retourne l’ensemble contenant u
union(u,v): remplace les ensembles contenant u et v
par leur union
CSI2510 - ACM
20
Représentation d’une
partition:
Chaque élément d’un ensemble est mis en mémoire dans
une séquence (l’ensemble pointe vers la séquence
contenant ces éléments)
Chaque élément à un pointeur vers l’ensemble
 L’opération find(u) se fait en O(1) et retourne l’ensemble dont u fait
partie
 Pour l’opération union(u,v), nous déplaçons les éléments du plus petit
ensemble dans la séquence du plus grand ensemble et nous mettons à
jour leur pointeur
 La complexité en temps de union(u,v) est min(nu,nv), où nu et nv sont les
tailles des ensembles contenant u et v
Chaque fois qu’un élément est traité, il est mis dans un ensemble de
taille au moins double, donc chaque élément est traité au plus log n
fois donc les unions coûtent O(n log n)
CSI2510 - ACM
21
Complexité de Kruskal
La construction du monceau d’arêtes O(m log m)
Chaque itération coûte un retrait du monceau et
une union
 Chaque retrait coûte O(log m), au pire cas on fait m
itérations, donc au total nous aurons O(m log m)


n-1 < m < n2
donc O(log m) est toujours O( log n)
 Au total les unions coûtent O(n log n) parce que chaque
élément est impliqué dans au plus log n unions
Complexité O((n+m)log n)
CSI2510 - ACM
22
Implémentation à base de partition
Une version à base de partition de l’algorithme de Kruskal
exécute les fusions des nuages comme des union(u,v) et les
tests comme des find(u)
Algorithm Kruskal(G):
Entrée: Un graphe pondéré G.
Sortie: Un ACM T pour G.
Soit P une partition des sommets de G, où chaque sommet est dans un ensemble séparé.
Soit Q une file à priorité gardant en mémoire les arêtes de G, ordonnées selon leur poids
Soit T un arbre initialement vide
Tant que T contient moins que n-1 arêtes faire
(u,v)  Q.removeMinElement()
Si P.find(u) != P.find(v) alors
Temps: O((n+m)log n)
Ajouter (u,v) à T
P.union(u,v)
retourner T
CSI2510 - ACM
23
Exemple
8
B
9
5
1
G
A
F
H
D
9
C 11
7
10
1
C 11
7
A
E
6
F
3
D
H
1
2
CSI2510 - ACM
6
F
3
H
D
2
G
9
5
C 11
7
A
E
8
B
4
4
10
G
8
5
9
5
2
10
B
A
6
3
C 11
7
1
E
B
4
G
8
10
E
4
6
F
3
D
H
2
24
Exemple (suite)
8
B
9
5
1
G
E
A
F
H
D
10
B
6
3
C 11
7
4
9
5
1
G
8
C 11
2
7
A
4
E
6
H
D
10
F
3
2
4 étapes
8
B
1
9
5
C 11
7
A
G
10
E
6
F
3
D
H
8
B
4
1
2
9
5
C 11
7
A
CSI2510 - ACM
G
10
E
4
6
F
3
D
H
2
25
Téléchargement