Dijkstra's algorithm: Difference between revisions
Content added Content deleted
m (→{{header|REXX}}: corrected comments and DO-END comment labels, changed indentation, simplified logic, added whitespace. -- ~~~~) |
(added haskell) |
||
Line 702: | Line 702: | ||
[a c d e] length 26 |
[a c d e] length 26 |
||
</pre> |
</pre> |
||
=={{header|Haskell}}== |
|||
{{trans|C++}} |
|||
Translation of the C++ solution, and all the complexities are the same as in the C++ solution. In particular, we again use a self-balancing binary search tree (<code>Data.Set</code>) to implement the priority queue, which results in an optimal complexity. |
|||
<lang haskell>import Data.Array |
|||
import Data.Array.MArray |
|||
import Data.Array.ST |
|||
import Control.Monad.ST |
|||
import Control.Monad (foldM) |
|||
import Data.Set as S |
|||
dijkstra :: (Ix v, Num w, Ord w, Bounded w) => v -> v -> Array v [(v,w)] -> (Array v w, Array v v) |
|||
dijkstra src invalid_index adj_list = runST $ do |
|||
min_distance <- newSTArray b maxBound |
|||
writeArray min_distance src 0 |
|||
previous <- newSTArray b invalid_index |
|||
let aux vertex_queue = |
|||
case S.minView vertex_queue of |
|||
Nothing -> return () |
|||
Just ((dist, u), vertex_queue') -> |
|||
let edges = adj_list ! u |
|||
f vertex_queue (v, weight) = do |
|||
let dist_thru_u = dist + weight |
|||
old_dist <- readArray min_distance v |
|||
if dist_thru_u >= old_dist then |
|||
return vertex_queue |
|||
else do |
|||
let vertex_queue' = S.delete (old_dist, v) vertex_queue |
|||
writeArray min_distance v dist_thru_u |
|||
writeArray previous v u |
|||
return $ S.insert (dist_thru_u, v) vertex_queue' |
|||
in |
|||
foldM f vertex_queue' edges >>= aux |
|||
aux (S.singleton (0, src)) |
|||
m <- freeze min_distance |
|||
p <- freeze previous |
|||
return (m, p) |
|||
where b = bounds adj_list |
|||
newSTArray :: Ix i => (i,i) -> e -> ST s (STArray s i e) |
|||
newSTArray = newArray |
|||
shortest_path_to :: (Ix v) => v -> v -> Array v v -> [v] |
|||
shortest_path_to target invalid_index previous = |
|||
aux target [] where |
|||
aux vertex acc | vertex == invalid_index = acc |
|||
| otherwise = aux (previous ! vertex) (vertex : acc) |
|||
adj_list :: Array Int [(Int, Int)] |
|||
adj_list = listArray (0, 5) [ [(1,7), (2,9), (5,14)], |
|||
[(0,7), (2,10), (3,15)], |
|||
[(0,9), (1,10), (3,11), (5,2)], |
|||
[(1,15), (2,11), (4,6)], |
|||
[(3,6), (5,9)], |
|||
[(0,14), (2,2), (4,9)] ] |
|||
main :: IO () |
|||
main = do |
|||
let (min_distance, previous) = dijkstra 0 (-1) adj_list |
|||
putStrLn $ "Distance from 0 to 4: " ++ show (min_distance ! 4) |
|||
let path = shortest_path_to 4 (-1) previous |
|||
putStrLn $ "Path: " ++ show path</lang> |
|||
=={{header|Java}}== |
=={{header|Java}}== |