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