Add Dijkstra algorithm illustrations and explanations

This commit is contained in:
trekhleb 2025-11-08 23:08:37 +01:00
parent 062703489b
commit f41e6abe8a
2 changed files with 134 additions and 1 deletions

View File

@ -1,7 +1,8 @@
# Dijkstra's Algorithm
_Read this in other languages:_
[_한국어_](README.ko-KR.md)
[_한국어_](README.ko-KR.md),
[_Українська_](README.uk-UA.md)
Dijkstra's algorithm is an algorithm for finding the shortest
paths between nodes in a graph, which may represent, for example,

View File

@ -0,0 +1,132 @@
# Алгоритм Дейкстри
_Читайте іншими мовами:_
[_English_](README.md),
[_한국어_](README.ko-KR.md)
Алгоритм Дейкстри — це алгоритм пошуку найкоротших шляхів між вершинами графа, який може представляти, наприклад, дорожню мережу.
Існує багато варіантів цього алгоритму; оригінальний варіант Дейкстри знаходив найкоротший шлях між двома вершинами, але більш поширений варіант фіксує одну вершину як «джерело» і знаходить найкоротші шляхи від неї до всіх інших вершин графа, утворюючи дерево найкоротших шляхів.
![Dijkstra](https://upload.wikimedia.org/wikipedia/commons/5/57/Dijkstra_Animation.gif)
Алгоритм Дейкстри для пошуку найкоротшого шляху між `a` та `b`.
Він вибирає непереглянуту вершину з найменшою відстанню, обчислює відстань через неї до кожного непереглянутого сусіда й оновлює відстань до сусіда, якщо вона менша. Коли всі сусіди опрацьовані — вершина позначається як відвідана (червоним кольором).
## Практичні застосування алгоритму Дейкстри
- GPS / навігаційні системи
- Оптимізація маршрутів громадського транспорту та авіаліній
- Інтернет-маршрутизація (протоколи OSPF, IS-IS)
- Оптимізація мережевого трафіку та затримок
- Пошук шляху в іграх (найкоротший шлях на карті)
- Оптимізація маршрутів доставки
- Проєктування логістичних та транспортних мереж
## Покроковий приклад алгоритму Дейкстри
Припустімо, ми маємо зважений граф вершин, де кожне ребро має певну довжину. Наприклад, відстань між вершинами `A` і `B` становить `7 метрів` (або просто `7m`).
Алгоритм використовує [чергу з пріоритетом](../../../data-structures/priority-queue/), щоб завжди вибирати наступну непереглянуту вершину з найменшою відстанню від початкової вершини.
Початкова вершина, за визначенням, має відстань `0m` від самої себе. З неї й починається пошук — вона єдина в черзі на початку.
Решта вершин додаються до черги з пріоритетом пізніше, у процесі обходу графа (під час відвідування сусідів).
![Dijkstra step 1](./images/dijkstra-01.png)
Кожен сусід витягнутої з черги вершини перевіряється для обчислення відстані до нього від початкової вершини. Наприклад, відстань від `A` до `B` — це `0m + 7m = 7m`.
Щоразу, коли ми відвідуємо нового (ще не баченого) сусіда, ми додаємо його в чергу з пріоритетом, де пріоритет — це відстань до цієї вершини від початкової.
Вершину `B` додаємо до мінімальної черги з пріоритетом, щоб відвідати її пізніше.
![Dijkstra step 2](./images/dijkstra-02.png)
Відвідуємо наступного сусіда `C` вершини `A`. Відстань від `A` до `C` становить `0m + 9m = 9m`.
Додаємо вершину `C` до мінімальної черги з пріоритетом.
![Dijkstra step 3](./images/dijkstra-03.png)
Те саме робимо для вершини `F`. Поточна відстань від `A` до `F``0m + 14m = 14m`.
Вершину `F` додаємо до черги для подальшого обходу.
![Dijkstra step 4](./images/dijkstra-04.png)
Коли всі сусіди поточної вершини перевірені, ми додаємо її до множини `visited`. Такі вершини більше не відвідуємо.
Тепер вибираємо з черги наступну вершину, найближчу до початкової, і починаємо відвідувати її сусідів.
![Dijkstra step 5](./images/dijkstra-05.png)
Якщо вершина, яку ми відвідуємо (наприклад, `C`), уже є в черзі, це означає, що відстань до неї вже обчислювалася раніше з іншого шляху (`A → C`). Якщо нова відстань (через інший шлях, наприклад `A → B → C`) менша, ми оновлюємо її в черзі. Якщо більша — залишаємо без змін.
Під час відвідування `C` через `B` (`A → B → C`), відстань дорівнює `7m + 10m = 17m`. Це більше, ніж уже відома `9m` для шляху `A → C`. Тож ми ігноруємо довший шлях.
![Dijkstra step 6](./images/dijkstra-06.png)
Відвідуємо іншого сусіда `B` — вершину `D`. Відстань до `D` дорівнює `7m + 15m = 22m`.
Оскільки `D` ще не відвідано і її немає в черзі, додаємо її з пріоритетом `22m`.
![Dijkstra step 7](./images/dijkstra-07.png)
Тепер усіх сусідів `B` відвідано, тож додаємо `B` до множини `visited`.
Наступною вибираємо вершину, що найближча до початкової.
![Dijkstra step 8](./images/dijkstra-08.png)
Відвідуємо непереглянутих сусідів вершини `C`.
Відстань до вершини `F` через `C` (`A → C → F`) дорівнює `9m + 2m = 11m`.
Це коротше за попередній шлях `A → F` довжиною `14m`.
Тому оновлюємо відстань до `F` — з `14m` до `11m`. Ми щойно знайшли коротший шлях.
![Dijkstra step 9](./images/dijkstra-09.png)
Так само для `D`: шлях `A → C → D` коротший за `A → B → D`.
Оновлюємо відстань з `22m` до `20m`.
![Dijkstra step 10](./images/dijkstra-10.png)
Усі сусіди `C` пройдені, додаємо її до `visited`.
Дістаємо з черги наступну найближчу вершину — `F`.
![Dijkstra step 11](./images/dijkstra-11.png)
Записуємо відстань до `E`: `11m + 9m = 20m`.
![Dijkstra step 12](./images/dijkstra-12.png)
Додаємо `F` до множини `visited`, далі дістаємо `D`.
![Dijkstra step 13](./images/dijkstra-13.png)
Відстань до `E` через `D`: `20m + 6m = 26m`.
Це більше, ніж уже обчислені `20m` через `F`, тому ігноруємо довший шлях.
![Dijkstra step 14](./images/dijkstra-14.png)
Вершину `D` відвідано.
![Dijkstra step 15](./images/dijkstra-15.png)
Вершину `E` також відвідано. Обхід графа завершено.
![Dijkstra step 16](./images/dijkstra-16.png)
Тепер ми знаємо найкоротші відстані до кожної вершини від початкової `A`.
На практиці під час обчислення відстаней також зберігаються `previousVertices` — попередні вершини, щоб можна було відновити повний шлях.
Наприклад, найкоротший шлях від `A` до `E` — це `A → C → F → E`.
## Приклад реалізації
- [dijkstra.js](./dijkstra.js)
## Джерела
- [Вікіпедія](https://uk.wikipedia.org/wiki/Алгоритм_Дейкстри)
- [Відео на YouTube від Nathaniel Fan](https://www.youtube.com/watch?v=gdmfOwyQlcI&list=PLLXdhg_r2hKA7DPDsunoDZ-Z769jWn4R8)
- [Відео на YouTube від Tushar Roy](https://www.youtube.com/watch?v=lAXZGERcDf4&list=PLLXdhg_r2hKA7DPDsunoDZ-Z769jWn4R8)