Dijkstra's algorithm
This commit is contained in:
parent
d4dd36b4f4
commit
11e33b0eba
198
luku13.tex
198
luku13.tex
|
@ -325,36 +325,32 @@ $O(nm)$ and it is possible to create inputs
|
||||||
that make the algorithm as slow as the
|
that make the algorithm as slow as the
|
||||||
standard Bellman–Ford algorithm.
|
standard Bellman–Ford algorithm.
|
||||||
|
|
||||||
\section{Dijkstran algoritmi}
|
\section{Dijkstra's algorithm}
|
||||||
|
|
||||||
\index{Dijkstran algoritmi@Dijkstran algoritmi}
|
\index{Dijkstra's algorithm}
|
||||||
|
|
||||||
\key{Dijkstran algoritmi} etsii Bellman–Fordin
|
\key{Dijkstra's algorithm} finds the shortest
|
||||||
algoritmin tavoin lyhimmät polut
|
paths from the starting node to all other nodes,
|
||||||
alkusolmusta kaikkiin muihin solmuihin.
|
like the Bellman–Ford algorithm.
|
||||||
Dijkstran algoritmi on tehokkaampi kuin
|
The benefit in Dijsktra's algorithm is that
|
||||||
Bellman–Fordin algoritmi,
|
it is more efficient and can be used for
|
||||||
minkä ansiosta se soveltuu suurten
|
processing large graphs.
|
||||||
verkkojen käsittelyyn.
|
However, the algorithm requires that there
|
||||||
Algoritmi vaatii kuitenkin,
|
are no negative weight edges in the graph.
|
||||||
ettei verkossa ole negatiivisia kaaria.
|
|
||||||
|
|
||||||
Dijkstran algoritmi vastaa
|
Like the Bellman–Ford algorithm,
|
||||||
Bellman–Fordin algoritmia siinä,
|
Dijkstra's algorithm maintains estimated distances
|
||||||
että se pitää
|
for the nodes and improves them during the algorithm.
|
||||||
yllä etäisyysarvioita solmuihin
|
Dijkstra's algorithm is efficient because
|
||||||
ja parantaa niitä algoritmin aikana.
|
it only processes
|
||||||
Algoritmin tehokkuus perustuu
|
each edge in the graph once, using the fact
|
||||||
siihen, että sen riittää käydä läpi
|
that there are no negative edges.
|
||||||
verkon kaaret vain kerran
|
|
||||||
hyödyntäen tietoa,
|
|
||||||
ettei verkossa ole negatiivisia kaaria.
|
|
||||||
|
|
||||||
\subsubsection{Esimerkki}
|
\subsubsection{Example}
|
||||||
|
|
||||||
Tarkastellaan Dijkstran algoritmin toimintaa
|
Let's consider how Dijkstra's algorithm
|
||||||
seuraavassa verkossa, kun alkusolmuna
|
works in the following graph when the
|
||||||
on solmu 1:
|
starting node is node 1:
|
||||||
\begin{center}
|
\begin{center}
|
||||||
\begin{tikzpicture}[scale=0.9]
|
\begin{tikzpicture}[scale=0.9]
|
||||||
\node[draw, circle] (1) at (1,3) {3};
|
\node[draw, circle] (1) at (1,3) {3};
|
||||||
|
@ -377,25 +373,18 @@ on solmu 1:
|
||||||
\path[draw,thick,-] (4) -- node[font=\small,label=below:1] {} (5);
|
\path[draw,thick,-] (4) -- node[font=\small,label=below:1] {} (5);
|
||||||
\end{tikzpicture}
|
\end{tikzpicture}
|
||||||
\end{center}
|
\end{center}
|
||||||
Bellman–Fordin algoritmin tavoin
|
Like in the Bellman–Ford algorithm,
|
||||||
alkusolmun etäisyysarvio on 0
|
the estimated distance is 0 to the starting node
|
||||||
ja kaikissa muissa solmuissa etäisyysarvio
|
and infinite to all other nodes.
|
||||||
on aluksi ääretön.
|
|
||||||
|
|
||||||
Dijkstran algoritmi
|
At each step, Dijkstra's algorithm selects a node
|
||||||
ottaa joka askeleella käsittelyyn
|
that has not been processed yet and whose estimated distance
|
||||||
sellaisen solmun,
|
is as small as possible.
|
||||||
jota ei ole vielä käsitelty
|
The first such node is node 1 with distance 0.
|
||||||
ja jonka etäisyysarvio on
|
|
||||||
mahdollisimman pieni.
|
|
||||||
Alussa tällainen solmu on solmu 1,
|
|
||||||
jonka etäisyysarvio on 0.
|
|
||||||
|
|
||||||
Kun solmu tulee käsittelyyn,
|
When a node is selected, the algorithm
|
||||||
algoritmi käy läpi kaikki
|
goes through all edges that begin from the node
|
||||||
siitä lähtevät kaaret ja
|
and improves the distances using them:
|
||||||
parantaa etäisyysarvioita
|
|
||||||
niiden avulla:
|
|
||||||
\begin{center}
|
\begin{center}
|
||||||
\begin{tikzpicture}[scale=0.9]
|
\begin{tikzpicture}[scale=0.9]
|
||||||
\node[draw, circle] (1) at (1,3) {3};
|
\node[draw, circle] (1) at (1,3) {3};
|
||||||
|
@ -422,12 +411,10 @@ niiden avulla:
|
||||||
\path[draw=red,thick,->,line width=2pt] (4) -- (5);
|
\path[draw=red,thick,->,line width=2pt] (4) -- (5);
|
||||||
\end{tikzpicture}
|
\end{tikzpicture}
|
||||||
\end{center}
|
\end{center}
|
||||||
Solmun 1 käsittely paransi etäisyysarvioita
|
The edges from node 1 improved distances to
|
||||||
solmuihin 2, 4 ja 5,
|
nodes 2, 4 and 5 whose now distances are now 5, 9 and 1.
|
||||||
joiden uudet etäisyydet ovat nyt 5, 9 ja 1.
|
|
||||||
|
|
||||||
Seuraavaksi käsittelyyn tulee solmu 5,
|
The next node to be processed is node 5 with distance 1:
|
||||||
jonka etäisyys on 1:
|
|
||||||
\begin{center}
|
\begin{center}
|
||||||
\begin{tikzpicture}
|
\begin{tikzpicture}
|
||||||
\node[draw, circle] (1) at (1,3) {3};
|
\node[draw, circle] (1) at (1,3) {3};
|
||||||
|
@ -452,7 +439,7 @@ jonka etäisyys on 1:
|
||||||
\path[draw=red,thick,->,line width=2pt] (5) -- (2);
|
\path[draw=red,thick,->,line width=2pt] (5) -- (2);
|
||||||
\end{tikzpicture}
|
\end{tikzpicture}
|
||||||
\end{center}
|
\end{center}
|
||||||
Tämän jälkeen vuorossa on solmu 4:
|
After this, the next node is node 4:
|
||||||
\begin{center}
|
\begin{center}
|
||||||
\begin{tikzpicture}[scale=0.9]
|
\begin{tikzpicture}[scale=0.9]
|
||||||
\node[draw, circle] (1) at (1,3) {3};
|
\node[draw, circle] (1) at (1,3) {3};
|
||||||
|
@ -478,17 +465,14 @@ Tämän jälkeen vuorossa on solmu 4:
|
||||||
\end{tikzpicture}
|
\end{tikzpicture}
|
||||||
\end{center}
|
\end{center}
|
||||||
|
|
||||||
Dijkstran algoritmissa on hienoutena,
|
A nice property in Dijkstra's algorithm is that
|
||||||
että aina kun solmu tulee käsittelyyn,
|
whenever a node is selected, its distance is final.
|
||||||
sen etäisyysarvio on siitä lähtien lopullinen.
|
For example, at this point of the algorithm,
|
||||||
Esimerkiksi tässä vaiheessa
|
the distances 0, 1 and 3 are the final distances
|
||||||
etäisyydet 0, 1 ja 3 ovat lopulliset
|
to nodes 1, 5 and 4.
|
||||||
etäisyydet solmuihin 1, 5 ja 4.
|
|
||||||
|
|
||||||
Algoritmi käsittelee vastaavasti
|
After this, the algorithm processes the two
|
||||||
vielä kaksi viimeistä solmua,
|
remaining nodes, and the final distances are as follows:
|
||||||
minkä jälkeen algoritmin päätteeksi
|
|
||||||
etäisyydet ovat:
|
|
||||||
|
|
||||||
\begin{center}
|
\begin{center}
|
||||||
\begin{tikzpicture}[scale=0.9]
|
\begin{tikzpicture}[scale=0.9]
|
||||||
|
@ -513,13 +497,14 @@ etäisyydet ovat:
|
||||||
\end{tikzpicture}
|
\end{tikzpicture}
|
||||||
\end{center}
|
\end{center}
|
||||||
|
|
||||||
\subsubsection{Negatiiviset kaaret}
|
\subsubsection{Negative edges}
|
||||||
|
|
||||||
Dijkstran algoritmin tehokkuus perustuu siihen,
|
The efficiency of Dijkstra's algorithm is
|
||||||
että verkossa ei ole negatiivisia kaaria.
|
based on the fact that the graph doesn't
|
||||||
Jos verkossa on negatiivinen kaari,
|
contain negative edges.
|
||||||
algoritmi ei välttämättä toimi oikein.
|
If there is a negative edge,
|
||||||
Tarkastellaan esimerkkinä seuraavaa verkkoa:
|
the algorithm may give incorrect results.
|
||||||
|
As an example, consider the following graph:
|
||||||
|
|
||||||
\begin{center}
|
\begin{center}
|
||||||
\begin{tikzpicture}[scale=0.9]
|
\begin{tikzpicture}[scale=0.9]
|
||||||
|
@ -535,54 +520,53 @@ Tarkastellaan esimerkkinä seuraavaa verkkoa:
|
||||||
\end{tikzpicture}
|
\end{tikzpicture}
|
||||||
\end{center}
|
\end{center}
|
||||||
\noindent
|
\noindent
|
||||||
Lyhin polku solmusta 1 solmuun 4 on
|
The shortest path from node 1 to node 4 is
|
||||||
$1 \rightarrow 3 \rightarrow 4$,
|
$1 \rightarrow 3 \rightarrow 4$,
|
||||||
ja sen pituus on 1.
|
and its length is 1.
|
||||||
Dijkstran algoritmi löytää
|
However, Dijkstra's algorithm
|
||||||
kuitenkin keveimpiä kaaria seuraten
|
finds the path $1 \rightarrow 2 \rightarrow 4$
|
||||||
polun $1 \rightarrow 2 \rightarrow 4$.
|
by following the lightest edges.
|
||||||
Algoritmi ei pysty ottamaan huomioon,
|
The algorithm cannot recognize that
|
||||||
että alemmalla polulla kaaren paino $-5$
|
in the lower path, the weight $-5$
|
||||||
kumoaa aiemman suuren kaaren painon $6$.
|
compensates the previous large weight $6$.
|
||||||
|
|
||||||
\subsubsection{Toteutus}
|
\subsubsection{Implementation}
|
||||||
|
|
||||||
Seuraava Dijkstran algoritmin toteutus laskee
|
The following implementation of Dijkstra's algorithm
|
||||||
pienimmän etäisyyden solmusta $x$ kaikkiin muihin solmuihin.
|
calculates the minimum distance from a node $x$
|
||||||
Verkko on tallennettu taulukkoon \texttt{v}
|
to all other nodes.
|
||||||
vieruslistoina, joissa on pareina kohdesolmu
|
The graph is stored in an array \texttt{v}
|
||||||
ja kaaren pituus.
|
as adjacency lists that contain target nodes
|
||||||
|
and weights for each edge.
|
||||||
|
|
||||||
Dijkstran algoritmin tehokas toteutus vaatii,
|
An efficient implementation of Dijkstra's algorithm
|
||||||
että verkosta pystyy löytämään
|
requires that it is possible to quickly find the
|
||||||
nopeasti vielä käsittelemättömän solmun,
|
smallest node that has not been processed.
|
||||||
jonka etäisyysarvio on pienin.
|
A suitable data structure for this is a priority queue
|
||||||
Sopiva tietorakenne tähän on prioriteettijono,
|
that contains the nodes ordered by the estimated distances.
|
||||||
jossa solmut ovat järjestyksessä etäisyys\-arvioiden mukaan.
|
Using a priority queue, the next node to be processed
|
||||||
Prioriteettijonon avulla
|
can be retrieved in logarithmic time.
|
||||||
seuraavaksi käsiteltävän solmun saa selville logaritmisessa ajassa.
|
|
||||||
|
|
||||||
Seuraavassa toteutuksessa prioriteettijono sisältää
|
In the following implementation,
|
||||||
pareja, joiden ensimmäinen kenttä on etäisyysarvio
|
the priority queue contains pairs whose first
|
||||||
ja toinen kenttä on solmun tunniste:
|
element is the estimated distance and second
|
||||||
|
element is the identifier of the corresponding node.
|
||||||
\begin{lstlisting}
|
\begin{lstlisting}
|
||||||
priority_queue<pair<int,int>> q;
|
priority_queue<pair<int,int>> q;
|
||||||
\end{lstlisting}
|
\end{lstlisting}
|
||||||
Pieni hankaluus on,
|
A small difficulty is that in Dijkstra's algorithm,
|
||||||
että Dijkstran algoritmissa täytyy saada selville
|
we should find the node with \emph{minimum} distance,
|
||||||
\emph{pienimmän} etäisyysarvion solmu,
|
while the C++ priority queue finds the \emph{maximum}
|
||||||
kun taas C++:n prioriteettijono antaa oletuksena
|
element as default.
|
||||||
\emph{suurimman} alkion.
|
An easy solution is to use \emph{negative} distances,
|
||||||
Helppo ratkaisu on tallentaa etäisyysarviot
|
so we can directly use the C++ priority queue.
|
||||||
\emph{negatiivisina}, jolloin C++:n prioriteettijonoa
|
|
||||||
voi käyttää suoraan.
|
|
||||||
|
|
||||||
Koodi merkitsee taulukkoon \texttt{z},
|
The code keeps track of processed nodes
|
||||||
onko solmu käsitelty,
|
in array \texttt{z},
|
||||||
ja pitää yllä etäisyysarvioita taulukossa \texttt{e}.
|
and maintains estimated distances in array \texttt{e}.
|
||||||
Alussa alkusolmun etäisyysarvio on 0
|
Initially, the distance to the starting node is 0,
|
||||||
ja jokaisen muun solmun etäisyysarviona
|
and the distance to all other nodes is $10^9$
|
||||||
on ääretöntä vastaava $10^9$.
|
that corresponds to infinity.
|
||||||
|
|
||||||
\begin{lstlisting}
|
\begin{lstlisting}
|
||||||
for (int i = 1; i <= n; i++) e[i] = 1e9;
|
for (int i = 1; i <= n; i++) e[i] = 1e9;
|
||||||
|
@ -601,10 +585,10 @@ while (!q.empty()) {
|
||||||
}
|
}
|
||||||
\end{lstlisting}
|
\end{lstlisting}
|
||||||
|
|
||||||
Yllä olevan toteutuksen aikavaativuus on $O(n+m \log m)$,
|
The time complexity of the above implementation is
|
||||||
koska algoritmi käy läpi kaikki verkon solmut
|
$O(n+m \log m)$ because the algorithm goes through
|
||||||
ja lisää jokaista kaarta kohden korkeintaan
|
all nodes in the graph, and adds for each edge
|
||||||
yhden etäisyysarvion prioriteettijonoon.
|
at most one estimated distance to the priority queue.
|
||||||
|
|
||||||
\section{Floyd–Warshallin algoritmi}
|
\section{Floyd–Warshallin algoritmi}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue