Dijkstra's Algorithm
Published:
Revised:
in
a029167
For rust, I’m updating the documentation for the standard library and specifically with the collections. For the priority queue I had the idea to use Dijkstra’s algorithm as a fun example. That idea was well received and that example is now live.
At first I wanted to use A* to solve the eight puzzle, which I’ve done before, but that example became far too big.
Here’s the example code currently up in docs:
Using rustc 0.12.0-pre (ef352faea84fa16616b773bd9aa5020d7c76bff0 2014-07-18 21:46:32 +0000
)
use PriorityQueue;
use uint;
cost: uint,
position: uint
// The priority queue depends on `Ord`.
// Explicitly implement the trait so the queue becomes a min-heap
// instead of a max-heap.
// Notice that the we flip the ordering here
other.cost.cmp
// `PartialOrd` needs to be implemented as well.
Some
// Each node is represented as an `uint`, for a shorter implementation.
node: uint,
cost: uint
// Dijkstra's shortest path algorithm.
// Start at `start` and use `dist` to track the current shortest distance
// to each node. This implementation isn't memory efficient as it may leave duplicate
// nodes in the queue. It also uses `uint::MAX` as a sentinel value,
// for a simpler implementation.
// dist[node] = current shortest distance from `start` to `node`
let mut dist = Vec from_elem;
let mut pq = new;
// We're at `start`, with a zero cost
*dist.get_mut = 0u;
pq.push;
// Examine the frontier with lower cost nodes first (min-heap)
loop let State = match pq.pop None => break, // empty
Some => s
;
// Alternatively we could have continued to find all shortest paths
if position == goal
// Important as we may have already found a better way
if cost > dist
// For each node we can reach, see if we can find a way with
// a lower cost going through this node
for edge in adj_list .iter let next = State ;
// If so, add it to the frontier and continue
if next.cost < dist pq.push;
// Relaxation, we have now found a better way
*dist.get_mut = next.cost;
// Goal not reachable
MAX
// This is the directed graph we're going to use.
// The node numbers correspond to the different states,
// and the edge weights symbolises the cost of moving
// from one node to another.
// Note that the edges are one-way.
//
// 7
// +-----------------+
// | |
// v 1 2 |
// 0 -----> 1 -----> 3 ---> 4
// | ^ ^ ^
// | | 1 | |
// | | | 3 | 1
// +------> 2 -------+ |
// 10 | |
// +---------------+
//
// The graph is represented as an adjecency list where each index,
// corresponding to a node value, has a list of outgoing edges.
// Chosen for it's efficiency.
let graph = vec! // Node 0
vec! Edge ],
// Node 1
vec!,
// Node 2
vec! Edge ,
Edge ],
// Node 3
vec! Edge ],
// Node 4
vec!];
assert_eq!;
assert_eq!;
assert_eq!;
assert_eq!;
assert_eq!;