Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add BinaryHeap::contains and BinaryHeap::remove #82002

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 89 additions & 0 deletions library/alloc/src/collections/binary_heap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,8 @@
#![allow(missing_docs)]
#![stable(feature = "rust1", since = "1.0.0")]

use core::borrow::Borrow;
use core::cmp::Ordering;
use core::fmt;
use core::iter::{FromIterator, FusedIterator, InPlaceIterable, SourceIter, TrustedLen};
use core::mem::{self, swap, ManuallyDrop};
Expand Down Expand Up @@ -708,6 +710,93 @@ impl<T: Ord> BinaryHeap<T> {
self.data.retain(f);
self.rebuild();
}

/// Returns `true` if the `BinaryHeap` contains the specified item.
///
/// The item may be any borrowed form of the heap's item type, but
/// `PartialEq` on the borrowed form *must* match that for the item type.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// #![feature(binary_heap_contains_remove)]
/// use std::collections::BinaryHeap;
///
/// let heap = BinaryHeap::from(vec![1, 3, 5, 7, 9]);
billyrieger marked this conversation as resolved.
Show resolved Hide resolved
///
/// assert!(heap.contains(&5));
/// assert!(!heap.contains(&2));
/// ```
///
/// # Time complexity
///
/// The worst case time complexity is *O*(*n*).
#[unstable(feature = "binary_heap_contains_remove", issue = "82001")]
pub fn contains<Q: ?Sized>(&self, item: &Q) -> bool
where
T: Borrow<Q>,
Q: PartialEq,
{
self.data.iter().any(|x| x.borrow() == item)
}

/// Removes an item from the `BinaryHeap` and returns it, if it exists.
///
/// The item may be any borrowed form of the heap's item type, but
/// `PartialEq` on the borrowed form *must* match that for the item type. If
/// there are multiple matching elements, an arbitrary and unspecified one is
billyrieger marked this conversation as resolved.
Show resolved Hide resolved
/// removed.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// #![feature(binary_heap_contains_remove)]
/// use std::collections::BinaryHeap;
///
/// let mut heap = BinaryHeap::from(vec![1, 3, 5, 7, 9]);
///
/// assert_eq!(heap.remove(&7), Some(7));
/// assert_eq!(heap.remove(&7), None);
/// ```
///
/// # Time complexity
///
/// The worst case time complexity is *O*(*n*).
#[unstable(feature = "binary_heap_contains_remove", issue = "82001")]
pub fn remove<Q: ?Sized>(&mut self, item: &Q) -> Option<T>
where
T: Borrow<Q>,
Q: PartialEq,
{
self.data.iter().position(|x| x.borrow() == item).map(|pos| {
let last = self.data.len() - 1;
let comparison = self.data[last].cmp(&self.data[pos]);
let removed_item = self.data.swap_remove(pos);
match comparison {
Ordering::Less => {
// If the swapped item is less than the removed item, sift
// it down the heap to its correct position.
debug_assert!(pos < last);
self.sift_down(pos);
}
Ordering::Greater => {
// If the swapped item is greater than the removed item,
// sift it up the heap to its correct position.
debug_assert!(pos < last);
self.sift_up(0, pos);
}
Ordering::Equal => {
// If the swapped item is equal to the removed item, it's
// already in the correct position.
}
}
removed_item
})
}
}

impl<T> BinaryHeap<T> {
Expand Down
36 changes: 36 additions & 0 deletions library/alloc/tests/binary_heap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,42 @@ fn test_retain() {
assert_eq!(a.into_sorted_vec(), [-10, 2, 4])
}

#[test]
fn test_contains_remove() {
let mut a = BinaryHeap::from(vec![5, 7, 13, -2, -2, 8, -9]);

assert!(a.contains(&7));
assert_eq!(a.remove(&7), Some(7));
assert_eq!(a.remove(&7), None);
assert!(!a.contains(&7));

assert!(a.contains(&-2));
assert_eq!(a.remove(&-2), Some(-2));
assert_eq!(a.remove(&-2), Some(-2));
assert_eq!(a.remove(&-2), None);
assert!(!a.contains(&-2));

assert!(a.contains(&13));
assert_eq!(a.remove(&13), Some(13));
assert_eq!(a.remove(&13), None);
assert!(!a.contains(&13));

assert_eq!(a.into_sorted_vec(), [-9, 5, 8]);
}

#[test]
fn test_empty_remove() {
let mut a = BinaryHeap::<i32>::new();
assert_eq!(a.remove(&5), None);
}

#[test]
fn test_singleton_remove() {
let mut a = BinaryHeap::from(vec![5]);
assert_eq!(a.remove(&5), Some(5));
assert!(a.is_empty());
}

// old binaryheap failed this test
//
// Integrity means that all elements are present after a comparison panics,
Expand Down
1 change: 1 addition & 0 deletions library/alloc/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#![feature(vecdeque_binary_search)]
#![feature(slice_group_by)]
#![feature(vec_extend_from_within)]
#![feature(binary_heap_contains_remove)]

use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
Expand Down