Arbre de plus court chemins

publicité
CSI2510
Structures de données et
algorithmes
Plus court chemin
1
Graphe pondéré
Les poids des arêtes d’un graphe représentent des
distances, des coûts, etc.
Exemple d’un graphe pondéré non-orienté:
 Dans un graphe des route aériennes, le poids d'une
arête représente la distance en miles entre les
aéroports de chaque extrémité
SFO
PVD
ORD
LGA
HNL
LAX
DFW
CSI2510 -- PCC
MIA
2
Plus court chemin
Étant donné un graphe pondéré et deux sommets u
et v, nous voulons trouver un chemin de poids total
minimal entre u et v
Applications
 Les réservations de vol
 Directions de conduite
 Routage des paquets d‘Internet
Exemple:
 Plus court chemin entre Providence et Honolulu
SFO
PVD
ORD
LGA
HNL
LAX
DFW
CSI2510 -- PCC
MIA
3
Propriétés
Propriété 1:
Un sous-chemin d’un plus court chemin est aussi un plus court
chemin
Propriété 2:
L’ensemble des plus courts chemins d’un sommet à tous les
autres sommets forme un arbre
Exemple:
Un arbre des plus courts chemins de Providence
SFO
PVD
ORD
LGA
HNL
LAX
DFW
CSI2510 -- PCC
MIA
4
Algorithme de Dijkstra
La distance entre un sommet v à un autre sommet
s est la longueur du plus court chemin entre s et v
L’algorithme de Dijkstra calcule la distance entre
un sommet donnée s de départ et tous les autres
sommets
Suppositions:
 Le graphe est connexe
 Les arêtes sont non-orientées
 Les poids des arêtes sont non-négatifs
CSI2510 -- PCC
5
Algorithme de Dijkstra
L’algorithme conserve l’ensemble des sommets pour lesquels la
distance a été calculée, appelé nuage (cloud) C
On fait grossir un “nuage” de sommets, contenant au départ s et
couvrant éventuellement tous les sommets
Pour chaque sommet v nous emmagasinons d(v) = La plus courte
distance entre v et s dans le sous-graphe constitué du nuage et de ses
sommets adjacents.
0
A
8
2
8 B
7
Exemple
3
2
CSI2510 -- PCC
C
4
2
1
9
E
F


6
D
5
4
Algorithme de Dijkstra
Pour chaque étape:
Nous ajoutons au nuage le sommet extérieur u qui
a la plus petite étiquette de distance

Nous mettons à jour les étiquettes des sommets
adjacents à u

Dans l’exemple …
A
8
2
8
B
8
7
C
3
2
E

0
1
8
D
4
B
2
E

5

2 1
C
7
3
9
F
4
2
4
2
A
8
0
D
4
3 --> chemin
5 plus court!
9
F

5 - chemin plus court! 11 - chemin plus court!
CSI2510 -- PCC
7
Algorithme de Dijkstra
Mise à jour = la relaxation des arêtes
Considérer une arête
e = (u,z) telle que:
 u est le sommet le plus
récemment ajouté au nuage
 z n’est pas dans le nuage
d(u) = 50
s
La relaxation d’une arête e
consiste a mettre à jour la
distance d(z) comme suit:
u
d(u) = 50
s
u
d(z) = 75
z
d(z) = 60
z
d(z)  min( d(z), d(u) + poids(e) )
CSI2510 -- PCC
8
Exemple
A
8
0
4
A
8
2
B
8
7
2
C
2
1
D
9
E

F
A
8
4
5
B
8
7
5
E
2
C
3
B
2
7
5
E
D
8
A
8
3
5
0
4
2
C
3
1
9
0
4
2
F
2
8
4
2
3

0
2
1
9
D
11
F
3
5
B
2
CSI2510 -- PCC
7
7
5
E
C
3
2
1
9
D
8
F
3
5
9
Exemple (suite)
A
8
0
4
2
B
2
7
7
C
3
5
E
2
1
9
D
8
F
3
5
A
8
0
4
2
B
2
CSI2510 -- PCC
7
7
C
3
5
E
2
1
9
D
8
F
3
5
10
Algorithme de Dijkstra
Nous emmagasinons les sommets, qui ne sont
pas dans le nuage, dans une file de priorité Q.
élément: un sommet v
clé: D[v] la distance du sommet
CSI2510 -- PCC
11
Algorithme de Dijkstra
Algorithm ShortestPath(G, v):
Entrés : Un graphe pondéré G et un sommet particulier v de G.
Sortie : Une étiquette D[u], pour chaque sommet u de G, telle que
D[u] est la longueur d'un plus court chemin de v à u dans G.
initialise D[v]  0 et D[u]  ∞ pour chaque sommet v  u
Soit Q une file à priorité qui contient tous les sommets de G
utilisant les étiquettes de D comme clés.
while Q   do {insérer u dans le nuage C}
u  Q.removeMinElement()
pour chaque sommet z adjacent à u tel que z est dans Q faire
{exécuter l'opération de relaxation sur l’arête (u, z) }
Si D[u] + w((u, z)) < D[z] alors
D[z] D[u] + w((u, z))
changer la valeur de la clé de z dans Q à D[z]
Retourner l’étiquette D[u] de chaque sommet u.
CSI2510 -- PCC
12
D
Même exemple, avec un tas
A
8
0
8
2
4


A
B
C
D
E
F
0
4
2
B
2
8
7
C
3

2
1
9
D

E
F
A
8
4
(A,C) 2
5
(A,B) 8
(A,D) 4
RemoveMin()
et mise-a-jour
0
4
2
B
2
8
7
5
E
C
3
2
1
9
D
11
F
3
5
CSI2510 -- PCC
13
D
0
8
2
4
A
B
C
D

E

F
(A,D) 4
RemoveMin()
A
8
(A,B) 8
0
4
2
B
2
8
7
5
E
C
3
2
1
9
D
11
F
3
Relaxation:
Mise-a-jour:
5
(C,D) 3
YES (3 < 4)
(C,E) 5 YES (5 < )
(C,F) 11 YES (11 < )
(C,B)
CSI2510 -- PCC
9
NON (9>8)
14
D
0
8
2
4


A
B
C
D
E
F
(A,D) 4
Mise à jour signifie: enlever les anciennes clés
et remplacer par les nouvelles
(C,D) 3
au lieu de 4
(C,E) 5
au lieu de

(C,F) 11
au lieu de

(A,B) 8
Remplacer (A,D) 4 avec (C,D) 3
Insert (C,E) 5
Insert (C,F) 11
CSI2510 -- PCC
15
D
0
8
2
3
A
B
C
D


E
F
Mise à jour signifie: enlever les anciennes clés
et remplacer par les nouvelles
(C,D) 3
au lieu de 4
(C,E) 5
au lieu de

(C,F) 11
au lieu de

(A,B) 8
Remplacer (A,D) 4 avec (C,D) 3
Insert (C,E) 5
Insert (C,F) 11
(C,D) 3
Quand on doit remplacer, il faut
aussi réarranger le heap
(pas montré dans cet exemple)
CSI2510 -- PCC
16
D
0
8
2
A
B
C
3
D

5
E
Mise à jour signifie: enlever les anciennes clés
et remplacer par les nouvelles
(C,D) 3
au lieu de 4
(C,E) 5
au lieu de

(C,F) 11
au lieu de

F
(C,D) 3
(A,B) 8
(C,E) 5
Remplacer (A,D) 4 avec (C,D) 3
Insert (C,E) 5
Insert (C,F) 11
CSI2510 -- PCC
17
D
0
8
2
A
B
C
3
5
D
11
E
Mise à jour signifie: enlever les anciennes clés
et remplacer par les nouvelles
(C,D) 3
Instead of 4
(C,E) 5
Instead of

(C,F) 11
Instead of

F
(C,D) 3
(A,B) 8
(C,E) 5
(C,F) 11
Remplacer (A,D) 4 avec (C,D) 3
Insert (C,E) 5
Insert (C,F) 11
CSI2510 -- PCC
18
D
A
8
0
8
2
A
B
C
3
D
5
11
E
0
4
2
B
2
8
7
5
E
C
3
F
2
1
9
D
8
F
(C,D) 3
3
(A,B) 8
(C,E) 5
5
(C,F) 11
RemoveMin()
Mis-a-jour
CSI2510 -- PCC
19
D
A
8
0
8
2
3
A
B
C
D
5
11
E
0
4
2
B
2
8
7
5
E
C
3
F
2
1
9
D
8
F
(C,E) 5
3
(A,B) 8
(C,F) 11
5
RemoveMin()
Mise à jour (D,F) 8 ? Yes 8 < 11
Remplacer (C,F) 11
avec (D,F) 8
CSI2510 -- PCC
20
D
A
8
0
8
2
3
A
B
C
D
5
E
B
2
7
5
E
C
3
F
0
4
2
8
8
2
1
9
D
8
F
(C,E) 5
3
(A,B) 8
(D,F) 8
5
RemoveMin()
Mise à jour (D,F) 8 ? Yes 8 < 11
Remplacer (C,F) 11
avec (D,F) 8
CSI2510 -- PCC
21
Pourquoi l‘algorithme de Dijkstra fonctionne?
L’algorithme de Dijkstra utilise un algorithme glouton.
C’est-à-dire un algorithme qui effectue à chaque étape
le choix optimal local dans l’espoir d’arriver à la
solution optimale globale.
 Supposons qu'il n'a pas trouvé toutes les
plus courtes distances. Soit F le premier
mauvais sommet que l'algorithme a traité.
 Quand le nœud précédent, D, sur le vrai
plus court chemin a été considéré, sa
distance était correcte.
 Mais l’arête (D,F) a été relaxée à ce
moment-là!
 Ainsi, aussi longtemps que d(F)>d(D) la
distance de F ne peut pas être fausse.
C'est-à-dire, il n'y a pas de mauvais
sommet.
CSI2510 -- PCC
A
8
0
4
2
B
2
7
7
C
3
5
E
2
1
9
D
8
F
5
22
3
Le temps d’exécution
Si nous représentons G avec une liste d’adjacence, alors nous pouvons parcourir tous les
sommets adjacents à u pendant un temps proportionnel à deg(u)
La file de priorité Q
Avec heap.
while Q   do {insérer u dans le nuage C}
A chaque itération:
- Extraction des sommets avec la distance la plus petite: O(log n).
- Mises à jour des clés: O(log n) pour chaque mise à jour (remplacer une clé et insérer
dans le tas)=>Apres chaque extraction (deg(u) mises à jour): O(deg(u) log n)
En total: uG (1 + deg(u)) log n = O((n+2m) log n) = O(m*log n)
Pire cas: O(n2 log n)
CSI2510 -- PCC
23
Le temps d’exécution
Avec une séquence non-triée:
O(n) quand on extrait les éléments minimaux
mais des mises à jour des clés plus rapides en O(1).
Il y a n-1 extractions d’ordre n et m mises à jour
d’ordre constant.
Le temps d’exécution est O(n2+m) = O(n2 )
En conclusion:
Séquence
Monceau
O(m log n)
O(n2 )
CSI2510 -- PCC
24
Téléchargement