Skip to content

Commit ea7aa76

Browse files
committed
Document BinaryHeap time complexity
I went into some detail on the time complexity of `push` because it is relevant for using BinaryHeap efficiently -- specifically that you should avoid pushing many elements in ascending order when possible.
1 parent 963184b commit ea7aa76

File tree

1 file changed

+43
-0
lines changed

1 file changed

+43
-0
lines changed

src/liballoc/collections/binary_heap.rs

+43
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,20 @@ use super::SpecExtend;
231231
/// assert_eq!(heap.pop(), Some(Reverse(5)));
232232
/// assert_eq!(heap.pop(), None);
233233
/// ```
234+
///
235+
/// # Time complexity
236+
///
237+
/// | [push] | [pop] | [peek]/[peek\_mut] |
238+
/// |--------|----------|--------------------|
239+
/// | O(1)~ | O(log n) | O(1) |
240+
///
241+
/// The value for `push` is an expected cost; the method documentation gives a
242+
/// more detailed analysis.
243+
///
244+
/// [push]: #method.push
245+
/// [pop]: #method.pop
246+
/// [peek]: #method.peek
247+
/// [peek\_mut]: #method.peek_mut
234248
#[stable(feature = "rust1", since = "1.0.0")]
235249
pub struct BinaryHeap<T> {
236250
data: Vec<T>,
@@ -384,6 +398,10 @@ impl<T: Ord> BinaryHeap<T> {
384398
/// }
385399
/// assert_eq!(heap.peek(), Some(&2));
386400
/// ```
401+
///
402+
/// # Time complexity
403+
///
404+
/// Cost is O(1) in the worst case.
387405
#[stable(feature = "binary_heap_peek_mut", since = "1.12.0")]
388406
pub fn peek_mut(&mut self) -> Option<PeekMut<'_, T>> {
389407
if self.is_empty() {
@@ -411,6 +429,11 @@ impl<T: Ord> BinaryHeap<T> {
411429
/// assert_eq!(heap.pop(), Some(1));
412430
/// assert_eq!(heap.pop(), None);
413431
/// ```
432+
///
433+
/// # Time complexity
434+
///
435+
/// The worst case cost of `pop` on a heap containing *n* elements is O(log
436+
/// n).
414437
#[stable(feature = "rust1", since = "1.0.0")]
415438
pub fn pop(&mut self) -> Option<T> {
416439
self.data.pop().map(|mut item| {
@@ -438,6 +461,22 @@ impl<T: Ord> BinaryHeap<T> {
438461
/// assert_eq!(heap.len(), 3);
439462
/// assert_eq!(heap.peek(), Some(&5));
440463
/// ```
464+
///
465+
/// # Time complexity
466+
///
467+
/// The expected cost of `push`, averaged over every possible ordering of
468+
/// the elements being pushed, and over a sufficiently large number of
469+
/// pushes, is O(1). This is the most meaningful cost metric when pushing
470+
/// elements that are *not* already in any sorted pattern.
471+
///
472+
/// The time complexity degrades if elements are pushed in predominantly
473+
/// ascending order. In the worst case, elements are pushed in ascending
474+
/// sorted order and the amortized cost per push is O(log n) against a heap
475+
/// containing *n* elements.
476+
///
477+
/// The worst case cost of a *single* call to `push` is O(n). The worst case
478+
/// occurs when capacity is exhausted and needs a resize. The resize cost
479+
/// has been amortized in the previous figures.
441480
#[stable(feature = "rust1", since = "1.0.0")]
442481
pub fn push(&mut self, item: T) {
443482
let old_len = self.len();
@@ -650,6 +689,10 @@ impl<T> BinaryHeap<T> {
650689
/// assert_eq!(heap.peek(), Some(&5));
651690
///
652691
/// ```
692+
///
693+
/// # Time complexity
694+
///
695+
/// Cost is O(1) in the worst case.
653696
#[stable(feature = "rust1", since = "1.0.0")]
654697
pub fn peek(&self) -> Option<&T> {
655698
self.data.get(0)

0 commit comments

Comments
 (0)