auto merge of #20133 : apasel422/rust/binary_heap, r=alexcrichton
Some more tidying up.
This commit is contained in:
commit
c06edbad34
@ -11,15 +11,15 @@
|
|||||||
//! A priority queue implemented with a binary heap.
|
//! A priority queue implemented with a binary heap.
|
||||||
//!
|
//!
|
||||||
//! Insertion and popping the largest element have `O(log n)` time complexity. Checking the largest
|
//! Insertion and popping the largest element have `O(log n)` time complexity. Checking the largest
|
||||||
//! element is `O(1)`. Converting a vector to a priority queue can be done in-place, and has `O(n)`
|
//! element is `O(1)`. Converting a vector to a binary heap can be done in-place, and has `O(n)`
|
||||||
//! complexity. A priority queue can also be converted to a sorted vector in-place, allowing it to
|
//! complexity. A binary heap can also be converted to a sorted vector in-place, allowing it to
|
||||||
//! be used for an `O(n log n)` in-place heapsort.
|
//! be used for an `O(n log n)` in-place heapsort.
|
||||||
//!
|
//!
|
||||||
//! # Examples
|
//! # Examples
|
||||||
//!
|
//!
|
||||||
//! This is a larger example which implements [Dijkstra's algorithm][dijkstra]
|
//! This is a larger example that implements [Dijkstra's algorithm][dijkstra]
|
||||||
//! to solve the [shortest path problem][sssp] on a [directed graph][dir_graph].
|
//! to solve the [shortest path problem][sssp] on a [directed graph][dir_graph].
|
||||||
//! It showcases how to use the `BinaryHeap` with custom types.
|
//! It shows how to use `BinaryHeap` with custom types.
|
||||||
//!
|
//!
|
||||||
//! [dijkstra]: http://en.wikipedia.org/wiki/Dijkstra%27s_algorithm
|
//! [dijkstra]: http://en.wikipedia.org/wiki/Dijkstra%27s_algorithm
|
||||||
//! [sssp]: http://en.wikipedia.org/wiki/Shortest_path_problem
|
//! [sssp]: http://en.wikipedia.org/wiki/Shortest_path_problem
|
||||||
@ -32,7 +32,7 @@
|
|||||||
//! #[deriving(Copy, Eq, PartialEq)]
|
//! #[deriving(Copy, Eq, PartialEq)]
|
||||||
//! struct State {
|
//! struct State {
|
||||||
//! cost: uint,
|
//! cost: uint,
|
||||||
//! position: uint
|
//! position: uint,
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
//! // The priority queue depends on `Ord`.
|
//! // The priority queue depends on `Ord`.
|
||||||
@ -55,13 +55,13 @@
|
|||||||
//! // Each node is represented as an `uint`, for a shorter implementation.
|
//! // Each node is represented as an `uint`, for a shorter implementation.
|
||||||
//! struct Edge {
|
//! struct Edge {
|
||||||
//! node: uint,
|
//! node: uint,
|
||||||
//! cost: uint
|
//! cost: uint,
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
//! // Dijkstra's shortest path algorithm.
|
//! // Dijkstra's shortest path algorithm.
|
||||||
//!
|
//!
|
||||||
//! // Start at `start` and use `dist` to track the current shortest distance
|
//! // 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
|
//! // 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,
|
//! // nodes in the queue. It also uses `uint::MAX` as a sentinel value,
|
||||||
//! // for a simpler implementation.
|
//! // for a simpler implementation.
|
||||||
//! fn shortest_path(adj_list: &Vec<Vec<Edge>>, start: uint, goal: uint) -> uint {
|
//! fn shortest_path(adj_list: &Vec<Vec<Edge>>, start: uint, goal: uint) -> uint {
|
||||||
@ -71,21 +71,16 @@
|
|||||||
//! let mut heap = BinaryHeap::new();
|
//! let mut heap = BinaryHeap::new();
|
||||||
//!
|
//!
|
||||||
//! // We're at `start`, with a zero cost
|
//! // We're at `start`, with a zero cost
|
||||||
//! dist[start] = 0u;
|
//! dist[start] = 0;
|
||||||
//! heap.push(State { cost: 0u, position: start });
|
//! heap.push(State { cost: 0, position: start });
|
||||||
//!
|
//!
|
||||||
//! // Examine the frontier with lower cost nodes first (min-heap)
|
//! // Examine the frontier with lower cost nodes first (min-heap)
|
||||||
//! loop {
|
//! while let Some(State { cost, position }) = heap.pop() {
|
||||||
//! let State { cost, position } = match heap.pop() {
|
|
||||||
//! None => break, // empty
|
|
||||||
//! Some(s) => s
|
|
||||||
//! };
|
|
||||||
//!
|
|
||||||
//! // Alternatively we could have continued to find all shortest paths
|
//! // Alternatively we could have continued to find all shortest paths
|
||||||
//! if position == goal { return cost }
|
//! if position == goal { return cost; }
|
||||||
//!
|
//!
|
||||||
//! // Important as we may have already found a better way
|
//! // Important as we may have already found a better way
|
||||||
//! if cost > dist[position] { continue }
|
//! if cost > dist[position] { continue; }
|
||||||
//!
|
//!
|
||||||
//! // For each node we can reach, see if we can find a way with
|
//! // For each node we can reach, see if we can find a way with
|
||||||
//! // a lower cost going through this node
|
//! // a lower cost going through this node
|
||||||
@ -108,7 +103,7 @@
|
|||||||
//! fn main() {
|
//! fn main() {
|
||||||
//! // This is the directed graph we're going to use.
|
//! // This is the directed graph we're going to use.
|
||||||
//! // The node numbers correspond to the different states,
|
//! // The node numbers correspond to the different states,
|
||||||
//! // and the edge weights symbolises the cost of moving
|
//! // and the edge weights symbolize the cost of moving
|
||||||
//! // from one node to another.
|
//! // from one node to another.
|
||||||
//! // Note that the edges are one-way.
|
//! // Note that the edges are one-way.
|
||||||
//! //
|
//! //
|
||||||
@ -126,7 +121,7 @@
|
|||||||
//! //
|
//! //
|
||||||
//! // The graph is represented as an adjacency list where each index,
|
//! // The graph is represented as an adjacency list where each index,
|
||||||
//! // corresponding to a node value, has a list of outgoing edges.
|
//! // corresponding to a node value, has a list of outgoing edges.
|
||||||
//! // Chosen for it's efficiency.
|
//! // Chosen for its efficiency.
|
||||||
//! let graph = vec![
|
//! let graph = vec![
|
||||||
//! // Node 0
|
//! // Node 0
|
||||||
//! vec![Edge { node: 2, cost: 10 },
|
//! vec![Edge { node: 2, cost: 10 },
|
||||||
@ -184,10 +179,11 @@ impl<T: Ord> BinaryHeap<T> {
|
|||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::collections::BinaryHeap;
|
/// use std::collections::BinaryHeap;
|
||||||
/// let heap: BinaryHeap<uint> = BinaryHeap::new();
|
/// let mut heap = BinaryHeap::new();
|
||||||
|
/// heap.push(4u);
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable = "matches collection reform specification, waiting for dust to settle"]
|
#[unstable = "matches collection reform specification, waiting for dust to settle"]
|
||||||
pub fn new() -> BinaryHeap<T> { BinaryHeap{data: vec!(),} }
|
pub fn new() -> BinaryHeap<T> { BinaryHeap { data: vec![] } }
|
||||||
|
|
||||||
/// Creates an empty `BinaryHeap` with a specific capacity.
|
/// Creates an empty `BinaryHeap` with a specific capacity.
|
||||||
/// This preallocates enough memory for `capacity` elements,
|
/// This preallocates enough memory for `capacity` elements,
|
||||||
@ -198,7 +194,8 @@ impl<T: Ord> BinaryHeap<T> {
|
|||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::collections::BinaryHeap;
|
/// use std::collections::BinaryHeap;
|
||||||
/// let heap: BinaryHeap<uint> = BinaryHeap::with_capacity(10u);
|
/// let mut heap = BinaryHeap::with_capacity(10);
|
||||||
|
/// heap.push(4u);
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable = "matches collection reform specification, waiting for dust to settle"]
|
#[unstable = "matches collection reform specification, waiting for dust to settle"]
|
||||||
pub fn with_capacity(capacity: uint) -> BinaryHeap<T> {
|
pub fn with_capacity(capacity: uint) -> BinaryHeap<T> {
|
||||||
@ -214,17 +211,17 @@ impl<T: Ord> BinaryHeap<T> {
|
|||||||
/// use std::collections::BinaryHeap;
|
/// use std::collections::BinaryHeap;
|
||||||
/// let heap = BinaryHeap::from_vec(vec![9i, 1, 2, 7, 3, 2]);
|
/// let heap = BinaryHeap::from_vec(vec![9i, 1, 2, 7, 3, 2]);
|
||||||
/// ```
|
/// ```
|
||||||
pub fn from_vec(xs: Vec<T>) -> BinaryHeap<T> {
|
pub fn from_vec(vec: Vec<T>) -> BinaryHeap<T> {
|
||||||
let mut q = BinaryHeap{data: xs,};
|
let mut heap = BinaryHeap { data: vec };
|
||||||
let mut n = q.len() / 2;
|
let mut n = heap.len() / 2;
|
||||||
while n > 0 {
|
while n > 0 {
|
||||||
n -= 1;
|
n -= 1;
|
||||||
q.siftdown(n)
|
heap.sift_down(n);
|
||||||
}
|
}
|
||||||
q
|
heap
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An iterator visiting all values in underlying vector, in
|
/// Returns an iterator visiting all values in the underlying vector, in
|
||||||
/// arbitrary order.
|
/// arbitrary order.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
@ -244,17 +241,17 @@ impl<T: Ord> BinaryHeap<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a consuming iterator, that is, one that moves each value out of
|
/// Creates a consuming iterator, that is, one that moves each value out of
|
||||||
/// the binary heap in arbitrary order. The binary heap cannot be used
|
/// the binary heap in arbitrary order. The binary heap cannot be used
|
||||||
/// after calling this.
|
/// after calling this.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::collections::BinaryHeap;
|
/// use std::collections::BinaryHeap;
|
||||||
/// let pq = BinaryHeap::from_vec(vec![1i, 2, 3, 4]);
|
/// let heap = BinaryHeap::from_vec(vec![1i, 2, 3, 4]);
|
||||||
///
|
///
|
||||||
/// // Print 1, 2, 3, 4 in arbitrary order
|
/// // Print 1, 2, 3, 4 in arbitrary order
|
||||||
/// for x in pq.into_iter() {
|
/// for x in heap.into_iter() {
|
||||||
/// // x has type int, not &int
|
/// // x has type int, not &int
|
||||||
/// println!("{}", x);
|
/// println!("{}", x);
|
||||||
/// }
|
/// }
|
||||||
@ -264,20 +261,19 @@ impl<T: Ord> BinaryHeap<T> {
|
|||||||
IntoIter { iter: self.data.into_iter() }
|
IntoIter { iter: self.data.into_iter() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the greatest item in a queue, or `None` if it is empty.
|
/// Returns the greatest item in the binary heap, or `None` if it is empty.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::collections::BinaryHeap;
|
/// use std::collections::BinaryHeap;
|
||||||
///
|
|
||||||
/// let mut heap = BinaryHeap::new();
|
/// let mut heap = BinaryHeap::new();
|
||||||
/// assert_eq!(heap.peek(), None);
|
/// assert_eq!(heap.peek(), None);
|
||||||
///
|
///
|
||||||
/// heap.push(1i);
|
/// heap.push(1i);
|
||||||
/// heap.push(5i);
|
/// heap.push(5);
|
||||||
/// heap.push(2i);
|
/// heap.push(2);
|
||||||
/// assert_eq!(heap.peek(), Some(&5i));
|
/// assert_eq!(heap.peek(), Some(&5));
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
#[stable]
|
#[stable]
|
||||||
@ -285,15 +281,15 @@ impl<T: Ord> BinaryHeap<T> {
|
|||||||
self.data.get(0)
|
self.data.get(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the number of elements the queue can hold without reallocating.
|
/// Returns the number of elements the binary heap can hold without reallocating.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::collections::BinaryHeap;
|
/// use std::collections::BinaryHeap;
|
||||||
///
|
/// let mut heap = BinaryHeap::with_capacity(100);
|
||||||
/// let heap: BinaryHeap<uint> = BinaryHeap::with_capacity(100u);
|
/// assert!(heap.capacity() >= 100);
|
||||||
/// assert!(heap.capacity() >= 100u);
|
/// heap.push(4u);
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable = "matches collection reform specification, waiting for dust to settle"]
|
#[unstable = "matches collection reform specification, waiting for dust to settle"]
|
||||||
pub fn capacity(&self) -> uint { self.data.capacity() }
|
pub fn capacity(&self) -> uint { self.data.capacity() }
|
||||||
@ -313,13 +309,15 @@ impl<T: Ord> BinaryHeap<T> {
|
|||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::collections::BinaryHeap;
|
/// use std::collections::BinaryHeap;
|
||||||
///
|
/// let mut heap = BinaryHeap::new();
|
||||||
/// let mut heap: BinaryHeap<uint> = BinaryHeap::new();
|
/// heap.reserve_exact(100);
|
||||||
/// heap.reserve_exact(100u);
|
/// assert!(heap.capacity() >= 100);
|
||||||
/// assert!(heap.capacity() >= 100u);
|
/// heap.push(4u);
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable = "matches collection reform specification, waiting for dust to settle"]
|
#[unstable = "matches collection reform specification, waiting for dust to settle"]
|
||||||
pub fn reserve_exact(&mut self, additional: uint) { self.data.reserve_exact(additional) }
|
pub fn reserve_exact(&mut self, additional: uint) {
|
||||||
|
self.data.reserve_exact(additional);
|
||||||
|
}
|
||||||
|
|
||||||
/// Reserves capacity for at least `additional` more elements to be inserted in the
|
/// Reserves capacity for at least `additional` more elements to be inserted in the
|
||||||
/// `BinaryHeap`. The collection may reserve more space to avoid frequent reallocations.
|
/// `BinaryHeap`. The collection may reserve more space to avoid frequent reallocations.
|
||||||
@ -332,88 +330,82 @@ impl<T: Ord> BinaryHeap<T> {
|
|||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::collections::BinaryHeap;
|
/// use std::collections::BinaryHeap;
|
||||||
///
|
/// let mut heap = BinaryHeap::new();
|
||||||
/// let mut heap: BinaryHeap<uint> = BinaryHeap::new();
|
/// heap.reserve(100);
|
||||||
/// heap.reserve(100u);
|
/// assert!(heap.capacity() >= 100);
|
||||||
/// assert!(heap.capacity() >= 100u);
|
/// heap.push(4u);
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable = "matches collection reform specification, waiting for dust to settle"]
|
#[unstable = "matches collection reform specification, waiting for dust to settle"]
|
||||||
pub fn reserve(&mut self, additional: uint) {
|
pub fn reserve(&mut self, additional: uint) {
|
||||||
self.data.reserve(additional)
|
self.data.reserve(additional);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Discards as much additional capacity as possible.
|
/// Discards as much additional capacity as possible.
|
||||||
#[unstable = "matches collection reform specification, waiting for dust to settle"]
|
#[unstable = "matches collection reform specification, waiting for dust to settle"]
|
||||||
pub fn shrink_to_fit(&mut self) {
|
pub fn shrink_to_fit(&mut self) {
|
||||||
self.data.shrink_to_fit()
|
self.data.shrink_to_fit();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Removes the greatest item from a queue and returns it, or `None` if it
|
/// Removes the greatest item from the binary heap and returns it, or `None` if it
|
||||||
/// is empty.
|
/// is empty.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::collections::BinaryHeap;
|
/// use std::collections::BinaryHeap;
|
||||||
///
|
|
||||||
/// let mut heap = BinaryHeap::from_vec(vec![1i, 3]);
|
/// let mut heap = BinaryHeap::from_vec(vec![1i, 3]);
|
||||||
///
|
///
|
||||||
/// assert_eq!(heap.pop(), Some(3i));
|
/// assert_eq!(heap.pop(), Some(3));
|
||||||
/// assert_eq!(heap.pop(), Some(1i));
|
/// assert_eq!(heap.pop(), Some(1));
|
||||||
/// assert_eq!(heap.pop(), None);
|
/// assert_eq!(heap.pop(), None);
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable = "matches collection reform specification, waiting for dust to settle"]
|
#[unstable = "matches collection reform specification, waiting for dust to settle"]
|
||||||
pub fn pop(&mut self) -> Option<T> {
|
pub fn pop(&mut self) -> Option<T> {
|
||||||
match self.data.pop() {
|
self.data.pop().map(|mut item| {
|
||||||
None => { None }
|
if !self.is_empty() {
|
||||||
Some(mut item) => {
|
swap(&mut item, &mut self.data[0]);
|
||||||
if !self.is_empty() {
|
self.sift_down(0);
|
||||||
swap(&mut item, &mut self.data[0]);
|
|
||||||
self.siftdown(0);
|
|
||||||
}
|
|
||||||
Some(item)
|
|
||||||
}
|
}
|
||||||
}
|
item
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Pushes an item onto the queue.
|
/// Pushes an item onto the binary heap.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::collections::BinaryHeap;
|
/// use std::collections::BinaryHeap;
|
||||||
///
|
|
||||||
/// let mut heap = BinaryHeap::new();
|
/// let mut heap = BinaryHeap::new();
|
||||||
/// heap.push(3i);
|
/// heap.push(3i);
|
||||||
/// heap.push(5i);
|
/// heap.push(5);
|
||||||
/// heap.push(1i);
|
/// heap.push(1);
|
||||||
///
|
///
|
||||||
/// assert_eq!(heap.len(), 3);
|
/// assert_eq!(heap.len(), 3);
|
||||||
/// assert_eq!(heap.peek(), Some(&5i));
|
/// assert_eq!(heap.peek(), Some(&5));
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable = "matches collection reform specification, waiting for dust to settle"]
|
#[unstable = "matches collection reform specification, waiting for dust to settle"]
|
||||||
pub fn push(&mut self, item: T) {
|
pub fn push(&mut self, item: T) {
|
||||||
let old_len = self.len();
|
let old_len = self.len();
|
||||||
self.data.push(item);
|
self.data.push(item);
|
||||||
self.siftup(0, old_len);
|
self.sift_up(0, old_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Pushes an item onto a queue then pops the greatest item off the queue in
|
/// Pushes an item onto the binary heap, then pops the greatest item off the queue in
|
||||||
/// an optimized fashion.
|
/// an optimized fashion.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::collections::BinaryHeap;
|
/// use std::collections::BinaryHeap;
|
||||||
///
|
|
||||||
/// let mut heap = BinaryHeap::new();
|
/// let mut heap = BinaryHeap::new();
|
||||||
/// heap.push(1i);
|
/// heap.push(1i);
|
||||||
/// heap.push(5i);
|
/// heap.push(5);
|
||||||
///
|
///
|
||||||
/// assert_eq!(heap.push_pop(3i), 5);
|
/// assert_eq!(heap.push_pop(3), 5);
|
||||||
/// assert_eq!(heap.push_pop(9i), 9);
|
/// assert_eq!(heap.push_pop(9), 9);
|
||||||
/// assert_eq!(heap.len(), 2);
|
/// assert_eq!(heap.len(), 2);
|
||||||
/// assert_eq!(heap.peek(), Some(&3i));
|
/// assert_eq!(heap.peek(), Some(&3));
|
||||||
/// ```
|
/// ```
|
||||||
pub fn push_pop(&mut self, mut item: T) -> T {
|
pub fn push_pop(&mut self, mut item: T) -> T {
|
||||||
match self.data.get_mut(0) {
|
match self.data.get_mut(0) {
|
||||||
@ -425,30 +417,29 @@ impl<T: Ord> BinaryHeap<T> {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
self.siftdown(0);
|
self.sift_down(0);
|
||||||
item
|
item
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Pops the greatest item off a queue then pushes an item onto the queue in
|
/// Pops the greatest item off the binary heap, then pushes an item onto the queue in
|
||||||
/// an optimized fashion. The push is done regardless of whether the queue
|
/// an optimized fashion. The push is done regardless of whether the binary heap
|
||||||
/// was empty.
|
/// was empty.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::collections::BinaryHeap;
|
/// use std::collections::BinaryHeap;
|
||||||
///
|
|
||||||
/// let mut heap = BinaryHeap::new();
|
/// let mut heap = BinaryHeap::new();
|
||||||
///
|
///
|
||||||
/// assert_eq!(heap.replace(1i), None);
|
/// assert_eq!(heap.replace(1i), None);
|
||||||
/// assert_eq!(heap.replace(3i), Some(1i));
|
/// assert_eq!(heap.replace(3), Some(1));
|
||||||
/// assert_eq!(heap.len(), 1);
|
/// assert_eq!(heap.len(), 1);
|
||||||
/// assert_eq!(heap.peek(), Some(&3i));
|
/// assert_eq!(heap.peek(), Some(&3));
|
||||||
/// ```
|
/// ```
|
||||||
pub fn replace(&mut self, mut item: T) -> Option<T> {
|
pub fn replace(&mut self, mut item: T) -> Option<T> {
|
||||||
if !self.is_empty() {
|
if !self.is_empty() {
|
||||||
swap(&mut item, &mut self.data[0]);
|
swap(&mut item, &mut self.data[0]);
|
||||||
self.siftdown(0);
|
self.sift_down(0);
|
||||||
Some(item)
|
Some(item)
|
||||||
} else {
|
} else {
|
||||||
self.push(item);
|
self.push(item);
|
||||||
@ -463,7 +454,6 @@ impl<T: Ord> BinaryHeap<T> {
|
|||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::collections::BinaryHeap;
|
/// use std::collections::BinaryHeap;
|
||||||
///
|
|
||||||
/// let heap = BinaryHeap::from_vec(vec![1i, 2, 3, 4, 5, 6, 7]);
|
/// let heap = BinaryHeap::from_vec(vec![1i, 2, 3, 4, 5, 6, 7]);
|
||||||
/// let vec = heap.into_vec();
|
/// let vec = heap.into_vec();
|
||||||
///
|
///
|
||||||
@ -494,35 +484,34 @@ impl<T: Ord> BinaryHeap<T> {
|
|||||||
while end > 1 {
|
while end > 1 {
|
||||||
end -= 1;
|
end -= 1;
|
||||||
self.data.swap(0, end);
|
self.data.swap(0, end);
|
||||||
self.siftdown_range(0, end)
|
self.sift_down_range(0, end);
|
||||||
}
|
}
|
||||||
self.into_vec()
|
self.into_vec()
|
||||||
}
|
}
|
||||||
|
|
||||||
// The implementations of siftup and siftdown use unsafe blocks in
|
// The implementations of sift_up and sift_down use unsafe blocks in
|
||||||
// order to move an element out of the vector (leaving behind a
|
// order to move an element out of the vector (leaving behind a
|
||||||
// zeroed element), shift along the others and move it back into the
|
// zeroed element), shift along the others and move it back into the
|
||||||
// vector over the junk element. This reduces the constant factor
|
// vector over the junk element. This reduces the constant factor
|
||||||
// compared to using swaps, which involves twice as many moves.
|
// compared to using swaps, which involves twice as many moves.
|
||||||
fn siftup(&mut self, start: uint, mut pos: uint) {
|
fn sift_up(&mut self, start: uint, mut pos: uint) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let new = replace(&mut self.data[pos], zeroed());
|
let new = replace(&mut self.data[pos], zeroed());
|
||||||
|
|
||||||
while pos > start {
|
while pos > start {
|
||||||
let parent = (pos - 1) >> 1;
|
let parent = (pos - 1) >> 1;
|
||||||
if new > self.data[parent] {
|
|
||||||
let x = replace(&mut self.data[parent], zeroed());
|
if new <= self.data[parent] { break; }
|
||||||
ptr::write(&mut self.data[pos], x);
|
|
||||||
pos = parent;
|
let x = replace(&mut self.data[parent], zeroed());
|
||||||
continue
|
ptr::write(&mut self.data[pos], x);
|
||||||
}
|
pos = parent;
|
||||||
break
|
|
||||||
}
|
}
|
||||||
ptr::write(&mut self.data[pos], new);
|
ptr::write(&mut self.data[pos], new);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn siftdown_range(&mut self, mut pos: uint, end: uint) {
|
fn sift_down_range(&mut self, mut pos: uint, end: uint) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let start = pos;
|
let start = pos;
|
||||||
let new = replace(&mut self.data[pos], zeroed());
|
let new = replace(&mut self.data[pos], zeroed());
|
||||||
@ -540,33 +529,31 @@ impl<T: Ord> BinaryHeap<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ptr::write(&mut self.data[pos], new);
|
ptr::write(&mut self.data[pos], new);
|
||||||
self.siftup(start, pos);
|
self.sift_up(start, pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn siftdown(&mut self, pos: uint) {
|
fn sift_down(&mut self, pos: uint) {
|
||||||
let len = self.len();
|
let len = self.len();
|
||||||
self.siftdown_range(pos, len);
|
self.sift_down_range(pos, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the length of the queue.
|
/// Returns the length of the binary heap.
|
||||||
#[unstable = "matches collection reform specification, waiting for dust to settle"]
|
#[unstable = "matches collection reform specification, waiting for dust to settle"]
|
||||||
pub fn len(&self) -> uint { self.data.len() }
|
pub fn len(&self) -> uint { self.data.len() }
|
||||||
|
|
||||||
/// Returns true if the queue contains no elements
|
/// Checks if the binary heap is empty.
|
||||||
#[unstable = "matches collection reform specification, waiting for dust to settle"]
|
#[unstable = "matches collection reform specification, waiting for dust to settle"]
|
||||||
pub fn is_empty(&self) -> bool { self.len() == 0 }
|
pub fn is_empty(&self) -> bool { self.len() == 0 }
|
||||||
|
|
||||||
/// Clears the queue, returning an iterator over the removed elements.
|
/// Clears the binary heap, returning an iterator over the removed elements.
|
||||||
#[inline]
|
#[inline]
|
||||||
#[unstable = "matches collection reform specification, waiting for dust to settle"]
|
#[unstable = "matches collection reform specification, waiting for dust to settle"]
|
||||||
pub fn drain<'a>(&'a mut self) -> Drain<'a, T> {
|
pub fn drain(&mut self) -> Drain<T> {
|
||||||
Drain {
|
Drain { iter: self.data.drain() }
|
||||||
iter: self.data.drain(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Drops all items from the queue.
|
/// Drops all items from the binary heap.
|
||||||
#[unstable = "matches collection reform specification, waiting for dust to settle"]
|
#[unstable = "matches collection reform specification, waiting for dust to settle"]
|
||||||
pub fn clear(&mut self) { self.drain(); }
|
pub fn clear(&mut self) { self.drain(); }
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user