Skip to content

Commit

Permalink
Main example for priority queue using dijkstra's algorithm.
Browse files Browse the repository at this point in the history
  • Loading branch information
treeman committed Jul 22, 2014
1 parent f15d6d2 commit 94500b8
Showing 1 changed file with 137 additions and 1 deletion.
138 changes: 137 additions & 1 deletion src/libcollections/priority_queue.rs
Expand Up @@ -8,7 +8,143 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! A priority queue implemented with a binary heap
//! A priority queue implemented with a binary heap.
//!
//! # Example
//!
//! This is a larger example which implements [Dijkstra's algorithm][dijkstra]
//! to solve the [shortest path problem][sssp] on a [directed graph][dir_graph].
//! It showcases how to use the `PriorityQueue` with custom types.
//!
//! [dijkstra]: http://en.wikipedia.org/wiki/Dijkstra%27s_algorithm
//! [sssp]: http://en.wikipedia.org/wiki/Shortest_path_problem
//! [dir_graph]: http://en.wikipedia.org/wiki/Directed_graph
//!
//! ```
//! use std::collections::PriorityQueue;
//! use std::uint;
//!
//! #[deriving(Eq, PartialEq)]
//! struct State {
//! 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.
//! impl Ord for State {
//! fn cmp(&self, other: &State) -> Ordering {
//! // Notice that the we flip the ordering here
//! other.cost.cmp(&self.cost)
//! }
//! }
//!
//! // `PartialOrd` needs to be implemented as well.
//! impl PartialOrd for State {
//! fn partial_cmp(&self, other: &State) -> Option<Ordering> {
//! Some(self.cmp(other))
//! }
//! }
//!
//! // Each node is represented as an `uint`, for a shorter implementation.
//! struct Edge {
//! 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.
//! fn shortest_path(adj_list: &Vec<Vec<Edge>>, start: uint, goal: uint) -> uint {
//! // dist[node] = current shortest distance from `start` to `node`
//! let mut dist = Vec::from_elem(adj_list.len(), uint::MAX);
//!
//! let mut pq = PriorityQueue::new();
//!
//! // We're at `start`, with a zero cost
//! *dist.get_mut(start) = 0u;
//! pq.push(State { cost: 0u, position: start });
//!
//! // Examine the frontier with lower cost nodes first (min-heap)
//! loop {
//! let State { cost, position } = match pq.pop() {
//! None => break, // empty
//! Some(s) => s
//! };
//!
//! // Alternatively we could have continued to find all shortest paths
//! if position == goal { return cost }
//!
//! // Important as we may have already found a better way
//! if cost > dist[position] { continue }
//!
//! // 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[position].iter() {
//! let next = State { cost: cost + edge.cost, position: edge.node };
//!
//! // If so, add it to the frontier and continue
//! if next.cost < dist[next.position] {
//! pq.push(next);
//! // Relaxation, we have now found a better way
//! *dist.get_mut(next.position) = next.cost;
//! }
//! }
//! }
//!
//! // Goal not reachable
//! uint::MAX
//! }
//!
//! fn main() {
//! // 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: 2, cost: 10 },
//! Edge { node: 1, cost: 1 }],
//! // Node 1
//! vec![Edge { node: 3, cost: 2 }],
//! // Node 2
//! vec![Edge { node: 1, cost: 1 },
//! Edge { node: 3, cost: 3 },
//! Edge { node: 4, cost: 1 }],
//! // Node 3
//! vec![Edge { node: 0, cost: 7 },
//! Edge { node: 4, cost: 2 }],
//! // Node 4
//! vec![]];
//!
//! assert_eq!(shortest_path(&graph, 0, 1), 1);
//! assert_eq!(shortest_path(&graph, 0, 3), 3);
//! assert_eq!(shortest_path(&graph, 3, 0), 7);
//! assert_eq!(shortest_path(&graph, 0, 4), 5);
//! assert_eq!(shortest_path(&graph, 4, 0), uint::MAX);
//! }
//! ```

#![allow(missing_doc)]

Expand Down

9 comments on commit 94500b8

@bors
Copy link
Contributor

@bors bors commented on 94500b8 Jul 22, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bors
Copy link
Contributor

@bors bors commented on 94500b8 Jul 22, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

merging treeman/rust/doc-dijkstra-example = 94500b8 into auto

@bors
Copy link
Contributor

@bors bors commented on 94500b8 Jul 22, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

treeman/rust/doc-dijkstra-example = 94500b8 merged ok, testing candidate = 853f53e9

@bors
Copy link
Contributor

@bors bors commented on 94500b8 Jul 22, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bors
Copy link
Contributor

@bors bors commented on 94500b8 Jul 22, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

merging treeman/rust/doc-dijkstra-example = 94500b8 into auto

@bors
Copy link
Contributor

@bors bors commented on 94500b8 Jul 22, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

treeman/rust/doc-dijkstra-example = 94500b8 merged ok, testing candidate = 2ffccb7

@bors
Copy link
Contributor

@bors bors commented on 94500b8 Jul 22, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fast-forwarding master to auto = 2ffccb7

Please sign in to comment.