Czy wiesz dlaczego w linii prostej jest dalej niż po łuku? Wyznaczanie odległości między dwiema równoległymi liniami Jaka jest najkrótsza odległość między dwoma punktami

Ścieżka wzdłuż linii przerywanej na obrazku jest krótsza niż ścieżka wzdłuż linii ciągłej. A teraz trochę więcej szczegółów na przykładzie szlaków morskich:

Jeśli płyniesz stałym kursem, to trajektoria statku wzdłuż powierzchnia ziemi będzie krzywą zwaną w matematyce logarytmicznyspirala.

W nawigacji nazywa się tę złożoną linię podwójnej krzywizny rododrom, co w tłumaczeniu z języka greckiego oznacza „ukośny bieg”.

Jednak najkrótszą odległość między dwoma punktami na kuli ziemskiej mierzy się wzdłuż łuku wielkiego koła.

Łuk koła wielkiego otrzymuje się jako ślad z przecięcia powierzchni ziemi z płaszczyzną przechodzącą przez środek ziemi, przyjmowaną jako kula.

W nawigacji nazywa się to wielkim kołem ortodromia, co w tłumaczeniu oznacza „bieg prosto”. Drugą cechą ortodromii jest to, że przecina ona południki pod różnymi kątami (ryc. 29).

Różnica odległości pomiędzy dwoma punktami na powierzchni Ziemi według loksodromy i ortodromy ma praktyczne znaczenie tylko podczas dużych przepraw oceanicznych.

W normalnych warunkach różnica ta jest pomijana i pływanie odbywa się po stałym kursie, tj. przez rododrom.

Aby wyprowadzić równanie, weźmy rodoksodrome (ryc. 30, A) dwa punkty A I W, odległość między nimi jest po prostu niewielka. Rysując przez nie południki i równoleżniki, otrzymujemy elementarny trójkąt sferyczny prostokątny ABC. W tym trójkącie kąt utworzony przez przecięcie południka i równoleżnika jest prosty i kąt PNAB równy kursowi statku K. Katet AC reprezentuje odcinek łuku południka i można go wyrazić

Gdzie R - promień Ziemi w postaci kuli;

Δφ - elementarny przyrost szerokości geograficznej (różnica szerokości geograficznej).

Noga NE reprezentuje równoległy segment łuku

gdzie r - promień równoległy;

Δλ - elementarna różnica długości geograficznej.

Z trójkąta OO 1 C można to znaleźć

Następnie w ostatecznej formie noga NE można wyrazić w ten sposób:

Biorąc elementarny trójkąt sferyczny ABC za mieszkanie napiszemy

Po redukcji R i zastąpienie elementarnych małych przyrostów współrzędnych nieskończenie małymi przyrostami, które będziemy mieli

Całkujmy otrzymane wyrażenie w zakresie od φ 1, λ 1 do φ 2, λ 2 zakładając, że wartość tgK jest stała:

Po prawej stronie mamy całkę tabelaryczną. Po podstawieniu jego wartości otrzymujemy równanie loksodromii na kuli

Analiza tego równania pozwala wyciągnąć następujące wnioski:

Przy kursach 0 i 180° loksodrome zamienia się w łuk koła wielkiego – południk;

Przy kursach 90 i 270° rododrom pokrywa się z równoleżnikiem;

Loksodrome przecina każdy równoleżnik tylko raz, ale każdy południk nieskończoną liczbę razy. te. spiralnie w kierunku bieguna, nie dociera do niego.

Żeglowanie stałym kursem, czyli po rododromie, choć nie jest to najkrótsza odległość pomiędzy dwoma punktami na Ziemi, zapewnia nawigatorowi znaczną wygodę.

Wymagania stawiane morskiej mapie nawigacyjnej można sformułować w oparciu o przewagę płynącą z żeglowania po rododromie i wyniki analizy jej równania w następujący sposób.

1. Loksodrome przecinające południki pod stałym kątem należy przedstawić jako linię prostą.

2. Projekcja mapy, używany do konstruowania map, musi być równokątny, tak aby znajdujące się na nim kursy, namiar i kąty odpowiadały ich znaczeniu w terenie.

3. Południki i równoleżniki, podobnie jak linie kursowe o kątach 0, 90, 180° i 270°, muszą być wzajemnie prostopadłymi liniami prostymi.

Najkrótsza odległość między dwoma danymi punktami na powierzchni Ziemi, rozumiana jako kula, to mniejszy z łuków koła wielkiego przechodzącego przez te punkty. Z wyjątkiem przypadku, gdy statek płynie wzdłuż południka lub równika, ortodroma przecina południki pod różnymi kątami. Dlatego statek podążający po takiej krzywiźnie musi stale zmieniać swój kurs. W praktyce wygodniej jest podążać kursem tworzącym stały kąt z południkami i zaznaczanym na mapie w rzucie Mercatora linią prostą – loksodromą. Jednak na dużych odległościach różnica w długości ortodromy i loksodromy osiąga znaczną wartość. Dlatego w takich przypadkach obliczana jest ortodroma i zaznaczane są na niej punkty pośrednie, pomiędzy którymi płyną wzdłuż loksodromy.

Projekcję kartograficzną spełniającą powyższe wymagania zaproponował holenderski kartograf Gerard Cramer (Mercator) w 1569 roku. Na cześć swojego twórcy projekcję nazwano Mercatorian

A kto chce dowiedzieć się jeszcze więcej? interesująca informacja Dowiedz się więcej Oryginał artykułu znajduje się na stronie internetowej InfoGlaz.rf Link do artykułu, z którego powstała ta kopia -

ODLEGŁOŚĆ, odległości, śr. 1. Przestrzeń oddzielająca dwa punkty, przerwa między czymś. Najkrótsza odległość między dwoma punktami w linii prostej. Mieszka dwa kilometry od nas. „Komendant pozwolił im podejść jak najbliżej... Słownik Uszakowa

dystans- rzeczownik, s., używany często Morfologia: (nie) co? dystanse, dlaczego? odległość, (widzisz) co? odległość, co? odległość, o co? o odległości; pl. Co? odległość, (nie) co? dystanse, co? odległości, (widzę) co? dystanse, co? odległości... Słownik wyjaśniający Dmitriewa

dystans- I; Poślubić Przestrzeń oddzielająca dwa punkty, dwa obiekty itp., odstęp między którymi, to l. Najkrótsza rzeka pomiędzy dwoma punktami. R. z domu do szkoły. Przejdź do pobliskiej rzeki. W odległości metra, na długość ramienia. Wiedz coś, poczuj coś. na… … słownik encyklopedyczny

dystans- I; Poślubić Zobacz też odległość a) Przestrzeń oddzielająca dwa punkty, dwa obiekty itp., odstęp między kim, niż l. Najkrótsza odległość między dwoma punktami. Odległość z domu do szkoły. Przejdź na bliską odległość... Słownik wielu wyrażeń

GEOMETRIA- dział matematyki badający właściwości różnych figur (punktów, linii, kątów, obiektów dwuwymiarowych i trójwymiarowych), ich rozmiary i względne położenie. Dla ułatwienia nauczania geometrię dzielimy na planimetrię i stereometrię. W… … Encyklopedia Colliera

Nawigacja*

Nawigacja- wydział nawigacji (patrz), który zawiera zestawienie metod określania pozycji statku na morzu za pomocą kompasu i dziennika (patrz). Określenie miejsca statku na morzu oznacza naniesienie na mapę punktu, w którym znajduje się statek ten moment usytuowany.… … Słownik encyklopedyczny F.A. Brockhausa i I.A. Efrona

COHEN- (Cohen) Hermann (1842 1918) Niemiecki filozof, założyciel i najwybitniejszy przedstawiciel marburskiej szkoły neokantyzmu. Główne dzieła: „Kantowska teoria doświadczenia” (1885), „Kantowe uzasadnienie etyki” (1877), „Kantowe uzasadnienie estetyki” (1889), „Logika... ...

Kanta Immanuela- Droga życiowa i twórczość Kanta Immanuel Kant urodził się w Królewcu (obecnie Kaliningrad) w Prusach Wschodnich w 1724 r. Jego ojciec był rymarzem, a matka gospodynią domową, sześcioro ich dzieci nie dożyło wieku dorosłego. Kant zawsze pamiętał swoich rodziców z... ... Filozofia Zachodu od jej początków do współczesności

FILOZOFIA KRYTYCZNA KANTA: NAUCZANIE ZDOLNOŚCI- (La philosophie critique de Kant: Doctrines des facultes, 1963) praca Deleuze'a. Charakteryzując metodę transcendentalną we wstępie, Deleuze zauważa, że ​​Kant rozumie filozofię jako naukę o stosunku wszelkiej wiedzy do istotnych celów... ... Historia filozofii: encyklopedia

Zasada farmy- podstawowa zasada optyki geometrycznej (patrz Optyka geometryczna). Najprostszą formą f.p. jest stwierdzenie, że promień światła rozchodzi się zawsze w przestrzeni pomiędzy dwoma punktami po drodze, po której czas jego podróży jest krótszy niż... Duży Encyklopedia radziecka

(Geometria opisowa)
  • Płyta CD (CXDX, C2D2) przedstawiony jako punkt C5 = D5 A5B5 równa się...
    (Geometria opisowa)
  • Wyznaczanie odległości pomiędzy dwiema równoległymi płaszczyznami
    Wyznaczanie odległości pomiędzy dwiema równoległymi płaszczyznami w położeniu ogólnym 01| X Wygodnie jest sprowadzić to do problemu określenia odległości pomiędzy tymi samymi dwiema płaszczyznami, przekształconej na położenie projektorów. W tym przypadku odległość między płaszczyznami zostanie określona jako prostopadła między liniami...
    (Geometria opisowa)
  • Wyznaczanie odległości pomiędzy dwiema przecinającymi się liniami
    Jeżeli chcemy wyznaczyć najkrótszą odległość pomiędzy dwiema przecinającymi się liniami prostymi, musimy dwukrotnie zmienić układy płaszczyzn rzutowania. Przy rozwiązywaniu tego problemu linia prosta Płyta CD (CXDX, C2D2) przedstawiony jako punkt C5 = D5(ryc. 198). Odległość od tego punktu do rzutu A5B5 równa się...
    (Geometria opisowa)
  • Kąt pomiędzy dwiema przecinającymi się liniami prostymi
    Jest to kąt pomiędzy dwiema przecinającymi się liniami równoległymi do danych. Zatem to zadanie jest podobne do poprzedniego. Aby go rozwiązać, należy wziąć dowolny punkt i przeciągnąć przez niego dwie linie, równoległe do danych przecinających się linii, i korzystając z transformacji rzutów, określić pożądany kąt....
    (Podstawy geometrii wykreślnej. Krótki kurs i zbiór problemów.)
  • Wyznaczanie odległości pomiędzy dwiema równoległymi liniami
    Problem rozwiązuje się metodą podwójnej zamiany płaszczyzn projekcyjnych. Na ostatnim etapie jedna z płaszczyzn projekcji musi być prostopadła do jednej z przecinających się linii. Następnie najkrótszą odległość między nimi wyznacza wielkość odcinka prostopadłego do drugiej linii przecięcia (ryc. 199)....
    (Geometria opisowa)
  • Po zaznaczeniu kredą dwóch punktów na tablicy nauczyciel stawia młodemu uczniowi zadanie: narysować najkrótszą drogę pomiędzy obydwoma punktami.

    Uczeń po namyśle ostrożnie rysuje między nimi krętą linię.

    - To najkrótsza droga! – dziwi się nauczyciel. -Kto cię tego nauczył?

    - Mój tata. Jest taksówkarzem.

    Rysunek naiwnego ucznia jest oczywiście anegdotyczny, ale czy nie uśmiechnąłbyś się, gdyby powiedziano Ci, że przerywany łuk na ryc. 1 - najkrótsza trasa z Przylądka Dobrej Nadziei na południowy kraniec Australii!

    Jeszcze bardziej uderzające jest stwierdzenie: pokazane na ryc. 2 okrężna trasa z Japonii do Kanału Panamskiego jest krótsza niż linia prosta narysowana między nimi na tej samej mapie!

    Ryż. 1. Włączone mapa morska Najkrótszą trasę z Przylądka Dobrej Nadziei na południowy kraniec Australii wyznacza nie linia prosta („loxodrome”), ale łuk („ortodroma”)


    Wszystko to wygląda na żart, a przecież przed wami stoją bezsporne prawdy, dobrze znane kartografom.




    Ryż. 2. Wydaje się niewiarygodne, że zakrzywiona ścieżka łącząca Jokohamę z Kanałem Panamskim na mapie morskiej jest krótsza niż linia prosta poprowadzona pomiędzy tymi samymi punktami


    Aby wyjaśnić tę kwestię, będziemy musieli powiedzieć kilka słów o mapach w ogóle, a mapach morskich w szczególności. Przedstawienie na papierze części powierzchni Ziemi nie jest zadaniem łatwym, nawet w zasadzie, gdyż Ziemia jest kulą, a wiadomo, że żadna część powierzchni kulistej nie może zostać rozłożona na płaszczyźnie bez fałd i rozdarć. Nieuchronnie trzeba się pogodzić z nieuniknionymi zniekształceniami map. Wynaleziono wiele sposobów rysowania map, ale nie wszystkie mapy są wolne od wad: niektóre mają zniekształcenia takiego, inne innego rodzaju, ale nie ma map bez zniekształceń.

    Żeglarze posługują się mapami sporządzonymi metodą starożytnego holenderskiego kartografa i matematyka z XVI wieku. Merkator. Ta metoda nazywa się „projekcją merkatorską”. Mapę morską łatwo rozpoznać po prostokątnej siatce: południki są na niej przedstawione w postaci szeregu równoległych linii prostych; okręgi szerokości geograficznej są również liniami prostymi, prostopadłymi do pierwszych (patrz ryc. 5).

    Wyobraź sobie teraz, że musisz znaleźć najkrótszą drogę z jednego portu oceanicznego do drugiego, leżącą na tym samym równoleżniku. Na oceanie wszystkie ścieżki są dostępne, a podróżowanie tam najkrótszą ścieżką jest zawsze możliwe, jeśli wiesz, jak ona przebiega. W naszym przypadku naturalne jest, że najkrótsza droga przebiega wzdłuż równoleżnika, na którym leżą oba porty: w końcu na mapie jest to linia prosta, a cóż może być krótsza niż prosta ścieżka! Ale mylimy się: równoległa ścieżka wcale nie jest najkrótsza.

    Rzeczywiście: na powierzchni kuli najkrótszą odległością między dwoma punktami jest łączący je łuk koła wielkiego. Ale krąg podobieństw - mały koło. Łuk dużego koła jest mniej zakrzywiony niż łuk dowolnego małego okręgu poprowadzonego przez te same dwa punkty: większy promień odpowiada mniejszej krzywiźnie. Rozciągnij nić na kuli ziemskiej pomiędzy naszymi dwoma punktami (por. ryc. 3); przekonasz się, że wcale nie będzie leżał równolegle. Napięta nić jest niepodważalnym wskaźnikiem najkrótsza droga, a jeśli nie pokrywa się z równoleżnikiem na kuli ziemskiej, to na mapie morskiej najkrótsza droga nie jest oznaczona linią prostą: pamiętaj, że okręgi równoleżników są przedstawiane na takiej mapie jako linie proste, ale każda linia, która tak nie pokrywa się z linią prostą krzywa .



    Ryż. 3. Prosty sposób na znalezienie naprawdę najkrótszej ścieżki pomiędzy dwoma punktami: trzeba przeciągnąć nitkę na globusie pomiędzy tymi punktami


    Po tym, co zostało powiedziane, staje się jasne, dlaczego najkrótsza droga na mapie morskiej jest przedstawiana nie jako linia prosta, ale jako linia zakrzywiona.

    Mówią, że wybierając kierunek dla Nikołajewskiej (obecnie Oktyabrskiej) kolej żelazna Dyskusje na temat tego, jaką drogę wybrać, trwały w nieskończoność. Spór położyła kres interwencja cara Mikołaja I, który rozwiązał problem dosłownie „od ręki”: połączył linią Petersburg z Moskwą. Gdyby zrobiono to na mapie Mercatora, rezultat byłby żenującą niespodzianką: zamiast prostej drogi droga okazałaby się kręta.

    Każdy, kto nie stroni od obliczeń, może za pomocą prostych obliczeń upewnić się, że ścieżka, która wydaje nam się krzywa na mapie, jest w rzeczywistości krótsza niż ta, którą jesteśmy gotowi uznać za prostą. Niech nasze dwa porty leżą na 60. równoleżniku i dzieli je odległość 60°. (To, czy takie dwa porty rzeczywiście istnieją, jest oczywiście nieistotne w obliczeniach).



    Ryż. 4. Obliczanie odległości pomiędzy punktami A i B na kuli po łuku równoległym i po łuku wielkiego koła


    Na ryc. 4 punkty O - Centrum glob, AB –łuk koła szerokości geograficznej, na którym leżą porty A i B; V jest 60°. Środek okręgu szerokości geograficznej znajduje się w punkcie Z Wyobraźmy sobie to od środka O kula ziemska przebiega przez te same porty łukiem wielkiego koła: jego promieniem OB = OA = R; przejdzie blisko narysowanego łuku AB, ale nie będzie się z tym pokrywać.

    Obliczmy długość każdego łuku. Od punktów A I W leżą na 60° szerokości geograficznej, następnie promienie OA I OB wynieść system operacyjny(oś kuli ziemskiej) pod kątem 30°. W trójkącie prostokątnym ASO noga AC (=r), leży naprzeciw kąta 30°, równego połowie przeciwprostokątnej Spółka jawna;

    Oznacza, r=R/2 Długość łuku AB stanowi jedną szóstą długości koła o szerokości geograficznej, a ponieważ okrąg ten ma połowę długości dużego koła (odpowiadającą połowie promienia), to długość łuku małego koła



    Aby teraz wyznaczyć długość łuku koła wielkiego narysowanego pomiędzy tymi samymi punktami (tj. najkrótszą drogę między nimi), musimy poznać wielkość kąta AOB. Akord JAK, oparty na łuku 60° (małego koła), jest bokiem foremnego sześciokąta wpisanego w to samo małe kółko; Dlatego AB = r=R/2

    Po narysowaniu linii prostej ODłączący centrum O kula ziemska ze środkiem D akordy AB, otrzymamy trójkąt prostokątny ODA, gdzie jest kąt D - prosty:

    DA= 1/2 AB i OA = R.

    sinAOD=AD: AO=R/4:R=0,25

    Stąd znajdujemy (z tabel):

    =14°28",5

    i dlatego

    = 28°57".

    Teraz nie jest trudno znaleźć wymaganą długość najkrótszej ścieżki w kilometrach. Obliczenia można uprościć, jeśli pamiętamy, że długość jednej minuty koła wielkiego globu wynosi

    Dowiadujemy się, że droga po okręgu równoleżnikowym, przedstawiona na mapie morskiej linią prostą, wynosi 3333 km, a droga po kole wielkim – po krzywej na mapie – ma długość 3213 km, czyli jest o 120 km krótsza.

    Uzbrojeni w nić i mając pod ręką globus, z łatwością sprawdzicie poprawność naszych rysunków i przekonacie się, czy łuki wielkich kół rzeczywiście leżą tak, jak pokazano na rysunkach. Pokazane na ryc. 1 rzekomo „prosta” trasa morska z Afryki do Australii ma długość 6020 mil, a „krzywa” 5450 mil, czyli krótsza o 570 mil, czyli 1050 km. „Bezpośrednia” trasa lotnicza z Londynu do Szanghaju na mapie morskiej przecina Morze Kaspijskie, podczas gdy tak naprawdę najkrótsza trasa biegnie na północ od Sankt Petersburga. Jasne jest, jaką rolę odgrywają te kwestie w oszczędzaniu czasu i paliwa.

    Jeśli w dobie żeglugi nie zawsze ceniono czas – to „czasu” nie uważano jeszcze za „pieniądz” – to wraz z pojawieniem się statków parowych za każdą tonę węgla nadmiernie zużytą trzeba płacić. Dlatego obecnie statki prowadzone są naprawdę najkrótszą trasą, często wykorzystując mapy wykonane nie w rzucie Mercatora, ale w tzw. rzucie „centralnym”: na tych mapach łuki wielkich kół są przedstawiane jako linie proste.

    Dlaczego wcześniejsi nawigatorzy korzystali z takich zwodniczych map i wybierali niekorzystne trasy? Błędem jest sądzić, że w dawnych czasach nie znano obecnie wskazanej cechy map morskich. Sprawę tłumaczy się oczywiście nie tym, ale faktem, że mapy sporządzone metodą Mercatora, oprócz niedogodności, mają także bardzo cenne dla żeglarzy korzyści. Taka mapa, po pierwsze, przedstawia poszczególne małe części powierzchni ziemi bez zniekształceń, zachowując kąty konturu. Nie zaprzecza temu fakt, że wraz z odległością od równika wszystkie kontury zauważalnie się rozciągają. Na dużych szerokościach geograficznych rozciągnięcie jest tak duże, że mapa morska daje osobie niezaznajomionej z jej cechami całkowicie fałszywe wyobrażenie o prawdziwej wielkości kontynentów: Grenlandia wydaje się tej samej wielkości co Afryka, Alaska jest większa niż Australia, chociaż Grenlandia jest 15 razy mniejsza od Afryki, a Alaska wraz z Grenlandią jest o połowę mniejsza od Australii. Jednak marynarz dobrze zaznajomiony z tymi cechami mapy nie może dać się przez nie zwieść. Znosi je, zwłaszcza, że ​​na małych obszarach mapa morza oddaje dokładne podobieństwo do natury (ryc. 5).

    Jednak mapa morska znacznie ułatwia rozwiązywanie problemów praktycznych nawigacyjnych. Jest to jedyny rodzaj mapy, na którym droga statku poruszającego się stałym kursem jest przedstawiona w postaci linii prostej. Chodzenie „niezmiennym kursem” oznacza konsekwentne trzymanie się jednego kierunku, jednego konkretnego „punktu odniesienia”, czyli chodzenie w taki sposób, aby wszystkie południki przecinały się pod równym kątem. Ale tę ścieżkę („loksodrom”) można przedstawić jako linię prostą tylko na mapie, na której wszystkie południki są liniami prostymi równoległymi do siebie. A ponieważ na globusie okręgi szerokości geograficznej przecinają się z południkami pod kątem prostym, to na takiej mapie okręgi szerokości geograficznej powinny być liniami prostymi prostopadłymi do linii południków. Krótko mówiąc, dochodzimy do dokładnie siatki współrzędnych, która jest cechą charakterystyczną mapy morskiej.




    Ryż. 5. Mapa globu morska lub Mercator. Mapy takie znacznie wyolbrzymiają wielkość konturów odległych od równika. Co na przykład jest większe: Grenlandia czy Australia? (Odpowiedź w tekście)


    Upodobanie żeglarzy do map Mercatora jest teraz zrozumiałe. Chcąc wyznaczyć kurs, jakim należy podążać, udając się do wyznaczonego portu, nawigator przykłada linijkę do końcowych punktów trasy i mierzy kąt, jaki tworzy ona z południkami. Trzymając się cały czas na otwartym morzu w tym kierunku, nawigator dokładnie doprowadzi statek do celu. Widać, że „loksodrom” nie jest wprawdzie najkrótszą i nie najtańszą, ale pod pewnymi względami bardzo dogodną trasą dla żeglarza. Aby dotrzeć np. z Przylądka Dobrej Nadziei na południowy kraniec Australii (patrz rys. 1), należy zawsze trzymać się tego samego kursu S 87°.50”. Tymczasem doprowadzić statek do tego samego finału punkt najkrótsza trasa(wg „ortodromy”), jak widać na rysunku, należy w sposób ciągły zmieniać kurs statku: rozpocząć od kursu S 42°.50”, a zakończyć kursem N 53°.50 (w tym przypadku najkrótsza ścieżka nie jest nawet możliwa - opiera się ona na ścianie lodowej Antarktyki).

    Obie ścieżki - wzdłuż „loksodromy” i wzdłuż „ortodromy” - pokrywają się tylko wtedy, gdy ścieżka wzdłuż wielkiego koła jest przedstawiona na mapie morskiej jako linia prosta: podczas poruszania się wzdłuż równika lub wzdłuż południka. We wszystkich pozostałych przypadkach ścieżki te są inne.

    Algorytm Dijkstry to algorytm grafowy wynaleziony przez holenderskiego naukowca Edsgera Dijkstrę w 1959 roku. Znajduje najkrótszą ścieżkę z jednego z wierzchołków grafu do wszystkich pozostałych. Algorytm działa tylko dla grafów bez krawędzi o ujemnej wadze.

    Rozważmy wykonanie algorytmu na przykładzie wykresu pokazanego na rysunku.

    Załóżmy, że musisz znaleźć najkrótszą odległość od pierwszego wierzchołka do wszystkich pozostałych.

    Okręgi oznaczają wierzchołki, linie wskazują ścieżki pomiędzy nimi (krawędzie grafu). Numery wierzchołków są wskazane w okręgach, a ich „cena” jest wskazana nad krawędziami - długość ścieżki. Przy każdym wierzchołku znajduje się czerwony znacznik - długość najkrótszej ścieżki do tego wierzchołka od wierzchołka 1.

    Pierwszy krok. Dla naszego przykładu spójrzmy na krok algorytmu Dijkstry. Wierzchołek 1 ma etykietę minimum, a jego sąsiadami są wierzchołki 2, 3 i 6.

    Pierwszym sąsiadem wierzchołka 1 jest wierzchołek 2, ponieważ długość ścieżki do niego jest minimalna. Długość ścieżki do niego przez wierzchołek 1 jest równa sumie wartości etykiety wierzchołka 1 i długości krawędzi przechodzącej od 1 do 2, czyli 0 + 7 = 7. Jest to mniej niż bieżąca etykieta wierzchołka 2, nieskończoność, więc nowa etykieta to 2. wierzchołek to 7.

    Podobną operację wykonujemy z dwoma innymi sąsiadami pierwszego wierzchołka - trzecim i szóstym.

    Sprawdzani są wszyscy sąsiedzi wierzchołka 1. Obecna minimalna odległość do wierzchołka 1 jest uważana za ostateczną i nie można jej zmienić (że rzeczywiście tak jest, po raz pierwszy udowodnił E. Dijkstra). Przekreślmy to na wykresie, aby zaznaczyć, że ten wierzchołek został odwiedzony.

    Drugi krok. Krok algorytmu jest powtarzany. Ponownie znajdujemy „najbliższy” z nieodwiedzonych wierzchołków. To jest wierzchołek 2 z etykietą 7.

    Ponownie próbujemy zredukować etykiety sąsiadów wybranego wierzchołka, próbując przejść do nich przez drugi wierzchołek. Sąsiadami wierzchołka 2 są wierzchołki 1, 3 i 4.

    Pierwszym (w kolejności) sąsiadem wierzchołka 2 jest wierzchołek 1. Jednak został on już odwiedzony, więc z pierwszym wierzchołkiem nie robimy nic.

    Następnym sąsiadem wierzchołka 2 jest wierzchołek 3, ponieważ ma on minimalną etykietę wierzchołków oznaczonych jako nieodwiedzone. Jeśli przejdziesz do tego przez 2, długość takiej ścieżki będzie równa 17 (7 + 10 = 17). Ale bieżąca etykieta trzeciego wierzchołka to 9, czyli mniej niż 17, więc etykieta się nie zmienia.

    Kolejnym sąsiadem wierzchołka 2 jest wierzchołek 4. Jeżeli przejdziemy do niego przez wierzchołek 2, to długość takiej ścieżki będzie równa sumie najkrótszej odległości do wierzchołka 2 i odległości pomiędzy wierzchołkami 2 i 4, czyli , 22 (7 + 15 = 22) . Od 22<, устанавливаем метку вершины 4 равной 22.

    Obejrzani zostali wszyscy sąsiedzi wierzchołka 2, zamrażamy odległość do niego i oznaczamy jako odwiedzoną.

    Trzeci krok. Powtarzamy krok algorytmu, wybierając wierzchołek 3. Po „przetworzeniu” go otrzymujemy następujące wyniki:

    Następne kroki. Powtarzamy krok algorytmu dla pozostałych wierzchołków. Będą to wierzchołki 6, 4 i 5, zgodnie z kolejnością.

    Zakończenie wykonywania algorytmu. Algorytm kończy się, gdy nie można przetworzyć więcej wierzchołków. W tym przykładzie wszystkie wierzchołki są przekreślone, jednak błędem jest zakładać, że tak będzie w każdym przykładzie - niektóre wierzchołki mogą pozostać nieprzekreślone, jeśli nie można do nich dotrzeć, czyli jeśli graf jest rozłączony. Wynik działania algorytmu widoczny jest na ostatnim rysunku: najkrótsza droga od wierzchołka 1 do 2 to 7, do 3 to 9, do 4 to 20, do 5 to 20, do 6 to 11.

    Implementacja algorytmu w różnych językach programowania:

    C++

    #include "stdafx.h" #include używając przestrzeni nazw std; stała int V=6; //Algorytm Dijkstry void Dijkstra(int GR[V][V], int st) ( int odległość[V], liczba, indeks, i, u, m=st+1; bool odwiedzono[V]; for (i= 0;tj "< "<> "; cin>>start; Dijkstra(GR, start-1); system("pauza>>void"); )

    Pascal

    program DijkstraAlgorithm; używa crt; stała V=6; inf=100000; wpisz wektor=tablica liczb całkowitych; var początek: liczba całkowita; const GR: tablica liczb całkowitych=((0, 1, 4, 0, 2, 0), (0, 0, 0, 9, 0, 0), (4, 0, 0, 7, 0, 0), (0, 9, 7, 0, 0, 2), (0, 0, 0, 0, 0, 8), (0, 0, 0, 0, 0, 0)); (algorytm Dijkstry) procedura Dijkstra(GR: tablica liczb całkowitych; st: liczba całkowita); var liczba, indeks, i, u, m, min: liczba całkowita; odległość: wektor; odwiedzone: tablica wartości logicznych; rozpocznij m:=st; dla i:=1 do V rozpocznij odległość[i]:=inf; odwiedziliśmy[i]:=false; koniec; odległość:=0; dla count:=1 do V-1 rozpocznij min:=inf; dla i:=1 do V wykonaj if (nieodwiedzony[i]) i (odległość[i]<=min) then begin min:=distance[i]; index:=i; end; u:=index; visited[u]:=true; for i:=1 to V do if (not visited[i]) and (GR<>0) i (odległość[u]<>inf) i (odległość[u]+GR inf następnie writeln(m,” > „, i” = „, odległość[i]) else writeln(m”, > „, i” = „, „trasa niedostępna”); koniec; (główny blok programu) rozpocząć clrscr; write("Początek wierzchołka >> "); czytaj (start); Dijkstra(GR, początek); koniec.

    Jawa

    importuj java.io.BufferedReader; importuj wyjątek java.io.IO; importuj java.io.InputStreamReader; importuj java.io.PrintWriter; importuj java.util.ArrayList; importuj java.util.Arrays; importuj java.util.StringTokenizer; klasa publiczna Rozwiązanie ( private static int INF = Integer.MAX_VALUE / 2; private int n; //liczba wierzchołków w dwuznaku private int m; //liczba łuków w dwuznaku private ArrayList przym.; //lista sąsiedztwa prywatna ArrayList waga; //waga krawędzi użytej prywatnej wartości logicznej dwuznaku; //tablica do przechowywania informacji o przebytych i nieprzebytych wierzchołkach private int dist; //tablica do przechowywania odległości od wierzchołka początkowego //tablica przodków niezbędna do odtworzenia najkrótszej ścieżki z wierzchołka początkowego private int pred; int początek; //wierzchołek początkowy, od którego szukana jest odległość do wszystkich pozostałych wierzchołków private BufferedReader cin; prywatny PrintWriter cout; prywatny tokenizer StringTokenizer; //procedura uruchamiania algorytmu Dijkstry z wierzchołka początkowego private void dejkstra(int s) ( dist[s] = 0; //najkrótsza odległość do wierzchołka początkowego wynosi 0 for (int iter = 0; iter< n; ++iter) { int v = -1; int distV = INF; //выбираем вершину, кратчайшее расстояние до которого еще не найдено for (int i = 0; i < n; ++i) { if (used[i]) { continue; } if (distV < dist[i]) { continue; } v = i; distV = dist[i]; } //рассматриваем все дуги, исходящие из найденной вершины for (int i = 0; i < adj[v].size(); ++i) { int u = adj[v].get(i); int weightU = weight[v].get(i); //релаксация вершины if (dist[v] + weightU < dist[u]) { dist[u] = dist[v] + weightU; pred[u] = v; } } //помечаем вершину v просмотренной, до нее найдено кратчайшее расстояние used[v] = true; } } //процедура считывания входных данных с консоли private void readData() throws IOException { cin = new BufferedReader(new InputStreamReader(System.in)); cout = new PrintWriter(System.out); tokenizer = new StringTokenizer(cin.readLine()); n = Integer.parseInt(tokenizer.nextToken()); //считываем количество вершин графа m = Integer.parseInt(tokenizer.nextToken()); //считываем количество ребер графа start = Integer.parseInt(tokenizer.nextToken()) - 1; //инициализируем списка смежности графа размерности n adj = new ArrayList[n]; for (int i = 0; i < n; ++i) { adj[i] = new ArrayList(); ) //inicjalizacja listy przechowującej wagi krawędzi Weight = new ArrayList[n]; for (int i = 0; tj< n; ++i) { weight[i] = new ArrayList(); ) //odczytaj graf określony przez listę krawędzi dla (int i = 0; i< m; ++i) { tokenizer = new StringTokenizer(cin.readLine()); int u = Integer.parseInt(tokenizer.nextToken()); int v = Integer.parseInt(tokenizer.nextToken()); int w = Integer.parseInt(tokenizer.nextToken()); u--; v--; adj[u].add(v); weight[u].add(w); } used = new boolean[n]; Arrays.fill(used, false); pred = new int[n]; Arrays.fill(pred, -1); dist = new int[n]; Arrays.fill(dist, INF); } //процедура восстановления кратчайшего пути по массиву предком void printWay(int v) { if (v == -1) { return; } printWay(pred[v]); cout.print((v + 1) + " "); } //процедура вывода данных в консоль private void printData() throws IOException { for (int v = 0; v < n; ++v) { if (dist[v] != INF) { cout.print(dist[v] + " "); } else { cout.print("-1 "); } } cout.println(); for (int v = 0; v < n; ++v) { cout.print((v + 1) + ": "); if (dist[v] != INF) { printWay(v); } cout.println(); } cin.close(); cout.close(); } private void run() throws IOException { readData(); dejkstra(start); printData(); cin.close(); cout.close(); } public static void main(String args) throws IOException { Solution solution = new Solution(); solution.run(); } }

    Inna opcja:

    Importuj Java.io.*; importuj java.util.*; publiczna klasa Dijkstra ( prywatna statyczna finalna Graph.Edge GRAPH = ( new Graph.Edge("a", "b", 7), new Graph.Edge("a", "c", 9), new Graph.Edge( "a", "f", 14), nowy Graph.Edge("b", "c", 10), nowy Graph.Edge("b", "d", 15), nowy Graph.Edge("c ", "d", 11), nowy Graph.Edge("c", "f", 2), nowy Graph.Edge("d", "e", 6), nowy Graph.Edge("e", "f", 9), ); prywatny statyczny końcowy String START = "a"; prywatny statyczny końcowy String END = "e"; publiczny statyczny void main(String args) ( Wykres g = nowy wykres(GRAPH); g.dijkstra (START); g.printPath(END); //g.printAllPaths(); ) ) class Graph (prywatna mapa końcowa wykres; // mapowanie nazw wierzchołków na obiekty Vertex zbudowane z zestawu Edges /** Jedna krawędź grafu (używana tylko przez konstruktora Graph) */ public static class Edge ( public final String v1, v2; public final int dist; public Edge(String v1, String v2, int dist) ( this.v1 = v1; this.v2 = v2; this.dist = dist; ) ) /** Jeden wierzchołek grafu wraz z odwzorowaniami na sąsiednie wierzchołki */ publiczna klasa statyczna Vertex implementuje Comparable ( public final String name; public int dist = Integer.MAX_VALUE; // MAX_VALUE przyjmuje się za nieskończoność public Vertex poprzedni = null; public final Map sąsiedzi = nowa HashMap<>(); public Vertex(String name) ( this.name = name; ) private void printPath() ( if (this == this.previous) ( System.out.printf("%s", this.name); ) else if ( this.previous == null) ( System.out.printf("%s(nieosiągnięte)", this.name); ) else ( this.previous.printPath(); System.out.printf(" -> %s( %d)", this.name, this.dist); ) ) public int CompareTo(Vertex other) ( return Integer.compare(dist, other.dist); ) ) /** Tworzy wykres ze zbioru krawędzi * / public Graph(krawędzie krawędzi) ( graph = nowy HashMap<>(krawędzie.długość); //jedno przejście, aby znaleźć wszystkie wierzchołki dla (Edge e: krawędzie) ( if (!graph.containsKey(e.v1)) graph.put(e.v1, new Vertex(e.v1)); if (!graph. zawieraKey(e.v2)) graph.put(e.v2, new Vertex(e.v2)); ) //kolejne przejście w celu ustawienia sąsiednich wierzchołków dla (Edge e: krawędzie) ( graph.get(e.v1). sąsiedzi.put(graph.get(e.v2), e.dist); //graph.get(e.v2).neighbors.put(graph.get(e.v1), e.dist); // także zrób to dla grafu nieskierowanego ) ) /** Uruchamia dijkstra przy użyciu określonego wierzchołka źródłowego */ public void dijkstra(String startName) ( if (!graph.containsKey(startName)) ( System.err.printf("Graph nie" zawiera wierzchołek początkowy \"%s\"\n", nazwa_początkowa); return; ) źródło wierzchołka końcowego = graph.get(NazwaPoczątkowa); Zestaw NavigableSet q = nowy zestaw drzew<>(); // skonfiguruj wierzchołki dla (Vertex v: graph.values()) ( v.previous = v == źródło ? źródło: null; v.dist = v == źródło ? 0: Integer.MAX_VALUE; q.add( v); ) dijkstra(q); ) /** Implementacja algorytmu dijkstry przy użyciu sterty binarnej. */ private void dijkstra(final NavigableSet q) ( Vertex u, v; while (!q.isEmpty()) ( u = q.pollFirst(); // wierzchołek o najkrótszej odległości (pierwsza iteracja zwróci źródło) if (u.dist == Integer.MAX_VALUE) break; // możemy zignorować u (i inne pozostałe wierzchołki), ponieważ są one nieosiągalne //sprawdź odległości do każdego sąsiada dla (Map.Entry a: u.neighbours.entrySet()) ( v = a.getKey(); //sąsiad w tej iteracji final int alterDist = u.dist + a.getValue(); if (alternateDist< v.dist) { // shorter path to neighbour found q.remove(v); v.dist = alternateDist; v.previous = u; q.add(v); } } } } /** Prints a path from the source to the specified vertex */ public void printPath(String endName) { if (!graph.containsKey(endName)) { System.err.printf("Graph doesn"t contain end vertex \"%s\"\n", endName); return; } graph.get(endName).printPath(); System.out.println(); } /** Prints the path from the source to every vertex (output order is not guaranteed) */ public void printAllPaths() { for (Vertex v: graph.values()) { v.printPath(); System.out.println(); } } }

    C

    #włączać #włączać #włączać //#define BIG_EXAMPLE typedef struct węzeł_t węzeł_t, *heap_t; typedef struktura Edge_t Edge_t; struct Edge_t ( węzeł_t *nd; /* cel tej krawędzi */ Edge_t *rodzeństwo;/* dla listy pojedynczo połączonej */ int len; /* koszt krawędzi */ ); struct node_t ( Edge_t *edge; /* pojedynczo połączona lista krawędzi */ node_t *via; /* gdzie poprzedni węzeł znajduje się na najkrótszej ścieżce */ double dist; /* odległość od węzła początkowego */ char name; /* the, er , nazwa */ int heap_idx; /* link do pozycji sterty w celu aktualizacji odległości */ ); /* --- zarządzanie krawędziami --- */ #ifdef BIG_EXAMPLE # zdefiniuj BLOCK_SIZE (1024 * 32 - 1) #else # zdefiniuj BLOCK_SIZE 15 #endif Edge_t *edge_root = 0, *e_next = 0; /* Nie przejmuj się zarządzaniem pamięcią, to nie ma sensu.Udawaj, że e_next = malloc(sizeof(edge_t)) */ void add_edge(node_t *a, node_t *b, double d) ( if (e_next == Edge_root ) ( Edge_root = malloc(sizeof(edge_t) * (BLOCK_SIZE + 1)); Edge_root.sibling = e_next; e_next = Edge_root + BLOCK_SIZE; ) --e_next; e_next->nd = b; e_next->len = d; e_next ->sibling = a->edge; a->edge = e_next; ) void free_edges() ( for (; Edge_root; Edge_root = e_next) ( e_next = Edge_root.sibling; free(edge_root); ) ) /* --- kolejka priorytetowa --- */ heap_t *heap; int heap_len; void set_dist(node_t *nd, node_t *via, double d) ( int i, j; /* znał już lepszą ścieżkę */ if (nd->via && d >= nd->dist) return; /* znajdź istniejący wpis na stercie lub utwórz nowy */ nd->dist = d; nd->via = via; i = nd->heap_idx; if (!i) i = ++heap_len; /* góra */ for (; i > 1 && nd->dist< heap->odległość; i = j) (sterta[i] = sterta[j])->heap_idx = i; sterta[i] = nd; nd->idx_sterty = i; ) node_t * pop_queue() ( node_t *nd, *tmp; int i, j; if (!heap_len) return 0; /* usuń element wiodący, przeciągnij tam element końcowy i opuść stertę */ nd = sterta; tmp = sterta; for (i = 1; tj< heap_len && (j = i * 2) <= heap_len; i = j) { if (j < heap_len && heap[j]->dist > sterta->odległość) j++; if (sterta[j]->odległość >= tmp->odległość) przerwa; (sterta[i] = sterta[j])->heap_idx = i; ) sterta[i] = tmp; tmp->id_sterty = i; powrót i; ) /* --- Rzeczy Dijkstry; nieosiągalne węzły nigdy nie zostaną utworzone w kolejka --- */ void calc_all(node_t *start) ( węzeł_t *lead; Edge_t *e; set_dist(start, start, 0); while ((lead = pop_queue())) for (e = lead->edge; e; e = e->rodzeństwo) set_dist(e->nd, lead, lead->dist + e->len); ) void show_path(node_t *nd) ( if (nd->via == nd) printf( "%s", nd->nazwa); else if (!nd->przez) printf("%s(nieosiągnięty)", nd->nazwa); else ( ścieżka_pokaż(nd->przez); printf("- > %s(%g) ", nd->nazwa, nd->odległość); ) ) int main(void) ( #ifndef BIG_EXAMPLE int i; # zdefiniuj N_NODES ("f" - "a" + 1) węzeł_t * węzły = calloc(sizeof(node_t), N_NODES); for (i = 0; i< N_NODES; i++) sprintf(nodes[i].name, "%c", "a" + i); # define E(a, b, c) add_edge(nodes + (a - "a"), nodes + (b - "a"), c) E("a", "b", 7); E("a", "c", 9); E("a", "f", 14); E("b", "c", 10);E("b", "d", 15);E("c", "d", 11); E("c", "f", 2); E("d", "e", 6); E("e", "f", 9); # undef E #else /* BIG_EXAMPLE */ int i, j, c; # define N_NODES 4000 node_t *nodes = calloc(sizeof(node_t), N_NODES); for (i = 0; i < N_NODES; i++) sprintf(nodes[i].name, "%d", i + 1); /* given any pair of nodes, there"s about 50% chance they are not connected; if connected, the cost is randomly chosen between 0 and 49 (inclusive! see output for consequences) */ for (i = 0; i < N_NODES; i++) { for (j = 0; j < N_NODES; j++) { /* majority of runtime is actually spent here */ if (i == j) continue; c = rand() % 100; if (c < 50) continue; add_edge(nodes + i, nodes + j, c - 50); } } #endif heap = calloc(sizeof(heap_t), N_NODES + 1); heap_len = 0; calc_all(nodes); for (i = 0; i < N_NODES; i++) { show_path(nodes + i); putchar("\n"); } #if 0 /* real programmers don"t free memories (they use Fortran) */ free_edges(); free(heap); free(nodes); #endif return 0; }

    PHP

    $krawędź, "koszt" => $przewaga); $sąsiedzi[$krawędź] = array("koniec" => $krawędź, "koszt" => $krawędź); ) $wierzchołki = array_unique($wierzchołki); foreach ($wierzchołki jako $wierzchołek) ( $dist[$vertex] = INF; $poprzedni[$vertex] = NULL; ) $dist[$source] = 0; $Q = $wierzchołki; while (count($Q) > 0) ( // TODO - Znajdź szybszy sposób na uzyskanie minimum $min = INF; foreach ($Q jako $vertex)( if ($dist[$vertex]< $min) { $min = $dist[$vertex]; $u = $vertex; } } $Q = array_diff($Q, array($u)); if ($dist[$u] == INF or $u == $target) { break; } if (isset($neighbours[$u])) { foreach ($neighbours[$u] as $arr) { $alt = $dist[$u] + $arr["cost"]; if ($alt < $dist[$arr["end"]]) { $dist[$arr["end"]] = $alt; $previous[$arr["end"]] = $u; } } } } $path = array(); $u = $target; while (isset($previous[$u])) { array_unshift($path, $u); $u = $previous[$u]; } array_unshift($path, $u); return $path; } $graph_array = array(array("a", "b", 7), array("a", "c", 9), array("a", "f", 14), array("b", "c", 10), array("b", "d", 15), array("c", "d", 11), array("c", "f", 2), array("d", "e", 6), array("e", "f", 9)); $path = dijkstra($graph_array, "a", "e"); echo "path is: ".implode(", ", $path)."\n";


    Pyton

    z kolekcji import nametuple, kolejka z pprint import pprint as pp inf = float("inf") Edge = nametuple("Edge", "start, end, koszt") class Graph(): def __init__(self, krawędzie): self .edges = krawędzie2 = self.vertices = set(suma((dla e w krawędziach2, )) def dijkstra(self, source, dest): potwierdź źródło w self.vertices dist = (wierzchołek: inf dla wierzchołka w self.vertices ) poprzedni = (wierzchołek: Brak dla wierzchołka w własnych.wierzchołkach) dist = 0 q = self.vertices.copy() sąsiadów = (wierzchołek: set() dla wierzchołka w własnych.wierzchołkach) dla początku, końca, kosztu w własnych krawędziach : sąsiedzi.add((koniec, koszt)) #pp(sąsiedzi) while q: u = min(q, klucz=lambda wierzchołek: dist) q.remove(u) if dist[u] == inf lub u = = dest: przerwa dla v, koszt w sąsiadach[u]: alt = dist[u] + koszt jeśli alt< dist[v]: # Relax (u,v,a) dist[v] = alt previous[v] = u #pp(previous) s, u = deque(), dest while previous[u]: s.pushleft(u) u = previous[u] s.pushleft(u) return s graph = Graph([("a", "b", 7), ("a", "c", 9), ("a", "f", 14), ("b", "c", 10), ("b", "d", 15), ("c", "d", 11), ("c", "f", 2), ("d", "e", 6), ("e", "f", 9)]) pp(graph.dijkstra("a", "e")) Output: ["a", "c", "d", "e"]