Descoperitor sau inventator | Edsger Dijkstra |
---|---|
Data descoperirii | 1959 |
Probleme similare | Algoritmul de căutare a căii ( d ) , algoritmul teoriei graficelor ( d ) , algoritm lacom , algoritm |
Structură de date | Grafic |
Bazat pe | Algoritm de traversare a lățimii |
La inceputul | Algoritmul A * , protocolul de rutare a statului de legătură ( en ) , Deschideți cea mai scurtă cale mai întâi , IS-IS |
Cel mai rău caz | , |
---|
În teoria graficelor , algoritmul Dijkstra (pronunțat [dɛɪkstra] ) este utilizat pentru a rezolva cea mai scurtă problemă de cale . Permite, de exemplu, să se determine o cale mai scurtă pentru a merge dintr-un oraș în altul, cunoscând rețeaua rutieră a unei regiuni. Mai precis, calculează cele mai scurte căi de la o sursă la toate celelalte vârfuri într-un grafic direcționat ponderat de reali pozitivi. Poate fi, de asemenea, utilizat pentru a calcula o cale mai scurtă între un vârf de pornire și un vârf de final.
Algoritmul poartă numele inventatorului său, informaticianul olandez Edsger Dijkstra și a fost publicat în 1959.
Acest algoritm este de complexitate polinomială . Mai precis, pentru vârfuri și arce, timpul este în sau chiar în .
Algoritmul lui Dijkstra rezolvă o problemă algoritmică : cea mai scurtă problemă de cale . Această problemă are mai multe variante. Cel mai simplu este următorul: dat un grafic nedirecționat , ale cărui margini sunt prevăzute cu greutăți și două vârfuri ale acestui grafic, găsiți o cale între cele două vârfuri din grafic, cu greutate minimă. Algoritmul lui Dijkstra face posibilă rezolvarea unei probleme mai generale: graficul poate fi orientat și putem desemna un vârf unic și putem cere lista celor mai scurte căi pentru toate celelalte noduri ale graficului.
Algoritmul ia ca intrare un grafic direcționat ponderat de reali pozitivi și un vârf sursă. Aceasta implică construirea progresivă a unui subgraf în care diferiții vârfuri sunt clasificate în ordinea crescătoare a distanței lor minime față de vârful de pornire. Distanța corespunde sumei greutăților arcurilor împrumutate.
Inițial, considerăm că distanțele de la fiecare vârf la vârful de pornire sunt infinite, cu excepția vârfului de pornire pentru care distanța este zero. Subgraful de pornire este setul gol.
În timpul fiecărei iterații, alegem în afara subgrafului un vârf de distanță minimă și îl adăugăm la subgraf. Apoi, actualizăm distanțele vârfurilor vecine ale celui adăugat. Actualizarea se efectuează după cum urmează: noua distanță față de vârful vecin este minima dintre distanța existentă și cea obținută prin adăugarea greutății arcului între vârful vecin și vârful adăugat la distanța de la vârful adăugat.
Continuăm în acest mod până când vârfurile sunt epuizate (sau până când este selectat vârful de sosire).
Algoritmul lui Dijkstra funcționează și pe un grafic nedirecționat (care poate face mai mult poate face mai puțin). Exemplul opus arată pașii succesivi în rezolvarea celei mai scurte căi dintr-un grafic. Nodurile simbolizează orașele identificate printr-o literă, iar crestele indică distanța dintre aceste orașe. Încercăm să determinăm cea mai scurtă rută pentru a merge din orașul A în orașul J.
În nouă etape, putem determina cea mai scurtă cale care duce de la A la J, trece prin C și H și are o lungime de 487 km .
De asemenea, putem rezuma execuția algoritmului lui Dijkstra cu o matrice. Fiecare pas corespunde unei linii. O linie oferă vârfurile curente distanțe față de vârful de pornire. O coloană oferă evoluția distanțelor unui vârf dat de vârful de pornire în timpul algoritmului. Distanța de la un vârf ales (deoarece minimă) este subliniată. Distanțele actualizate sunt tăiate dacă sunt mai mari decât distanțele deja calculate.
la A | la B | la C | la D | la E | la F. | la G | la H | avea | la J | |
---|---|---|---|---|---|---|---|---|---|---|
pasul inițial | 0 | ∞ | ∞ | ∞ | ∞ | ∞ | ∞ | ∞ | ∞ | ∞ |
A (0) | 85 | 217 | ∞ | 173 | ∞ | ∞ | ∞ | ∞ | ∞ | |
B (85 A ) | - | 217 | ∞ | 173 | 165 | ∞ | ∞ | ∞ | ∞ | |
F (165 B ) | - | 217 | ∞ | 173 | - | ∞ | ∞ | 415 | ∞ | |
E (173 A ) | - | 217 | ∞ | - | - | ∞ | ∞ | 415 | 675 | |
C (217 A ) | - | - | ∞ | - | - | 403 | 320 | 415 | 675 | |
H (320 C ) | - | - | 503 | - | - | 403 | - | 415 | 675 487 | |
G (403 C ) | - | - | 503 | - | - | - | - | 415 | 487 | |
I (415 F ) | - | - | 503 | - | - | - | - | - | 487 | |
J (487 H ) | - | - | 503 | - | - | - | - | - | - | |
D (503 M ) | - | - | - | - | - | - | - | - | - |
Tabelul oferă nu numai distanța minimă de la orașul A la orașul J (487), ci și calea înapoi (J - H - C - A) pentru a merge de la A la J, precum și toate distanțele minime de la orașul A la celelalte orașe enumerate în ordine crescătoare.
Graficul este notat unde:
Greutatea căii dintre două vârfuri este suma greutăților arcurilor care o compun. Pentru o pereche dată de vârfuri (vârful de pornire) (vârful de sosire) aparținând , algoritmul găsește o cale de la până la cu o greutate mai mică (cu alte cuvinte o cale mai ușoară sau chiar cea mai scurtă).
Algoritmul funcționează prin construirea unui subgraf astfel încât distanța dintre un vârf în de la este cunoscută și este minimă în . Inițial, conține doar nodul izolat, iar distanța de la el însuși este zero. Arcurile sunt adăugate la fiecare pas:
1. prin identificarea tuturor arcurilor din ; 2. prin alegerea arcului în care se dă distanța minimă de la până la trecerea tuturor căilor create care duc la acest nod.Algoritmul de capete , fie atunci când devine un arbore de acoperire a , sau atunci când toate nodurile de interes sunt .
Prin urmare, putem scrie algoritmul după cum urmează:
Entrées : un graphe avec une pondération positive des arcs, un sommet de pour chaque sommet Tant qu'il existe un sommet hors de Choisir un sommet hors de de plus petite distance Mettre dans Pour chaque sommet hors de voisin de Si d[b] > d[a] + poids(a, b) prédécesseur[b] := a Fin Pour Fin Tant QueAlgoritmul folosește următoarele funcții auxiliare.
Inițializarea algoritmului Initialisation(G,sdeb) 1 pour chaque point s de G faire 2 d[s] := infini /* on initialise les sommets autres que sdeb à infini */ 3 fin pour 4 d[sdeb] := 0 /* la distance au sommet de départ sdeb est nulle */ Găsirea unui nod de distanță minimăIată funcția principală care folosește funcțiile laterale anterioare:
Dijkstra(G,Poids,sdeb) 1 Initialisation(G,sdeb) 2 Q := ensemble de tous les nœuds 3 tant que Q n'est pas un ensemble vide faire 4 s1 := Trouve_min(Q) 5 Q := Q privé de s1 6 pour chaque nœud s2 voisin de s1 faire 7 maj_distances(s1,s2) 8 fin pour 9 fin tant queCea mai scurtă cale de la la poate fi apoi calculată iterativ în conformitate cu următorul algoritm, secvența reprezentând cea mai scurtă cale de la la :
1 A = suite vide 2 s := sfin 3 tant que s != sdeb faire 4 A = A + s /* on ajoute s à la suite A */ 5 s = prédécesseur[s] /* on continue de suivre le chemin */ 6 fin tant queAtenție: dacă nu există o cale către această parte a algoritmului este o buclă infinită sau o eroare în funcție de implementarea dvs.
Este posibil să se specializeze algoritmul oprind căutarea atunci când se verifică egalitatea , în cazul în care se caută doar distanța minimă dintre și .
Eficiența algoritmului Dijkstra se bazează pe o implementare eficientă a Trouve_min . Întregul este implementat printr-o coadă prioritară . Dacă graficul are arce și noduri, că este reprezentat de liste de adiacență și dacă coada de prioritate este implementată de o grămadă binară (presupunând că comparațiile dintre greutățile arcurilor sunt în timp constant), atunci complexitatea temporală a algoritmului este . Pe de altă parte, dacă implementăm coada prioritară cu o grămadă Fibonacci , algoritmul este în .
Dovada corectării este o reapariție pe Card ( P ) (care crește cu 1 la fiecare iterație) și se bazează pe următorul invariant:
sau:
Dacă n = Card ( P ), dovada este următoarea:
Algoritmul selectează un pivot astfel încât și îl adaugă în P. Prin urmare, este necesar să se arate că după modificarea lui P:
Prin ipoteză, înainte de modificarea lui P , deci dacă există o cale C astfel încât atunci această cale conține cel puțin un vârf b a astfel încât .
Deci, să fie un astfel de vârf b astfel încât toți predecesorii săi din C să fie în P (există pentru că primul vârf al lui C este originea care se află în P ). Descompună C în Cb - și Cb + în cazul în care Cb - este prima parte a C , care este ultimul vârf b , și Cb + După C . Deci : contradicție.
Prin urmare, nu există o cale C, cum ar fi de unde . Egalitatea este întotdeauna valabil și pentru alte elemente P .
În cele din urmă, algoritmul pune actualizare funcția de (și predecesorul) pentru succesorii b pivot are : .
Să arătăm că atunci :
Algoritmul lui Dijkstra găsește utilitate în calculul rutelor rutiere. Greutatea arcurilor poate fi distanța (pentru cea mai scurtă rută), timpul estimat (pentru cea mai rapidă rută), consumul de combustibil și prețul taxelor (pentru cea mai economică rută).
O aplicație obișnuită a algoritmului lui Dijkstra apare în protocoalele de rutare interne de „stare de legătură”, cum ar fi Open Shortest Path First ( OSPF ) sau IS-IS - sau chiar PNNI (en) pe rețelele ATM -, care permit rutare foarte eficientă a informațiilor prin internet căutând cel mai eficient traseu.