diff --git a/src/algorithms/graph/dijkstra/README.md b/src/algorithms/graph/dijkstra/README.md index 98e85969..91cde790 100644 --- a/src/algorithms/graph/dijkstra/README.md +++ b/src/algorithms/graph/dijkstra/README.md @@ -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, diff --git a/src/algorithms/graph/dijkstra/README.uk-UA.md b/src/algorithms/graph/dijkstra/README.uk-UA.md new file mode 100644 index 00000000..0b901b5b --- /dev/null +++ b/src/algorithms/graph/dijkstra/README.uk-UA.md @@ -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)