liballoc: VecDeque: Add binary search functions
This commit is contained in:
parent
fc3d8e3fcc
commit
36d9b72354
@ -2181,7 +2181,7 @@ impl<T> VecDeque<T> {
|
||||
///
|
||||
/// This method does not allocate and does not change the order of the
|
||||
/// inserted elements. As it returns a mutable slice, this can be used to
|
||||
/// sort or binary search a deque.
|
||||
/// sort a deque.
|
||||
///
|
||||
/// Once the internal storage is contiguous, the [`as_slices`] and
|
||||
/// [`as_mut_slices`] methods will return the entire contents of the
|
||||
@ -2430,6 +2430,154 @@ impl<T> VecDeque<T> {
|
||||
self.wrap_copy(self.tail, self.head, k);
|
||||
}
|
||||
}
|
||||
|
||||
/// Binary searches this sorted `VecDeque` for a given element.
|
||||
///
|
||||
/// If the value is found then [`Result::Ok`] is returned, containing the
|
||||
/// index of the matching element. If there are multiple matches, then any
|
||||
/// one of the matches could be returned. If the value is not found then
|
||||
/// [`Result::Err`] is returned, containing the index where a matching
|
||||
/// element could be inserted while maintaining sorted order.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Looks up a series of four elements. The first is found, with a
|
||||
/// uniquely determined position; the second and third are not
|
||||
/// found; the fourth could match any position in `[1, 4]`.
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(vecdeque_binary_search)]
|
||||
/// use std::collections::VecDeque;
|
||||
///
|
||||
/// let deque: VecDeque<_> = vec![0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55].into();
|
||||
///
|
||||
/// assert_eq!(deque.binary_search(&13), Ok(9));
|
||||
/// assert_eq!(deque.binary_search(&4), Err(7));
|
||||
/// assert_eq!(deque.binary_search(&100), Err(13));
|
||||
/// let r = deque.binary_search(&1);
|
||||
/// assert!(matches!(r, Ok(1..=4)));
|
||||
/// ```
|
||||
///
|
||||
/// If you want to insert an item to a sorted `VecDeque`, while maintaining
|
||||
/// sort order:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(vecdeque_binary_search)]
|
||||
/// use std::collections::VecDeque;
|
||||
///
|
||||
/// let mut deque: VecDeque<_> = vec![0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55].into();
|
||||
/// let num = 42;
|
||||
/// let idx = deque.binary_search(&num).unwrap_or_else(|x| x);
|
||||
/// deque.insert(idx, num);
|
||||
/// assert_eq!(deque, &[0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 42, 55]);
|
||||
/// ```
|
||||
#[unstable(feature = "vecdeque_binary_search", issue = "1")]
|
||||
#[inline]
|
||||
pub fn binary_search(&self, x: &T) -> Result<usize, usize>
|
||||
where
|
||||
T: Ord,
|
||||
{
|
||||
self.binary_search_by(|e| e.cmp(x))
|
||||
}
|
||||
|
||||
/// Binary searches this sorted `VecDeque` with a comparator function.
|
||||
///
|
||||
/// The comparator function should implement an order consistent
|
||||
/// with the sort order of the underlying `VecDeque`, returning an
|
||||
/// order code that indicates whether its argument is `Less`,
|
||||
/// `Equal` or `Greater` than the desired target.
|
||||
///
|
||||
/// If the value is found then [`Result::Ok`] is returned, containing the
|
||||
/// index of the matching element. If there are multiple matches, then any
|
||||
/// one of the matches could be returned. If the value is not found then
|
||||
/// [`Result::Err`] is returned, containing the index where a matching
|
||||
/// element could be inserted while maintaining sorted order.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Looks up a series of four elements. The first is found, with a
|
||||
/// uniquely determined position; the second and third are not
|
||||
/// found; the fourth could match any position in `[1, 4]`.
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(vecdeque_binary_search)]
|
||||
/// use std::collections::VecDeque;
|
||||
///
|
||||
/// let deque: VecDeque<_> = vec![0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55].into();
|
||||
///
|
||||
/// assert_eq!(deque.binary_search_by(|x| x.cmp(&13)), Ok(9));
|
||||
/// assert_eq!(deque.binary_search_by(|x| x.cmp(&4)), Err(7));
|
||||
/// assert_eq!(deque.binary_search_by(|x| x.cmp(&100)), Err(13));
|
||||
/// let r = deque.binary_search_by(|x| x.cmp(&1));
|
||||
/// assert!(matches!(r, Ok(1..=4)));
|
||||
/// ```
|
||||
#[unstable(feature = "vecdeque_binary_search", issue = "1")]
|
||||
pub fn binary_search_by<'a, F>(&'a self, mut f: F) -> Result<usize, usize>
|
||||
where
|
||||
F: FnMut(&'a T) -> Ordering,
|
||||
{
|
||||
if self.is_empty() {
|
||||
return Err(0);
|
||||
}
|
||||
|
||||
let (front, back) = self.as_slices();
|
||||
|
||||
match back.first().map(|elem| f(elem)) {
|
||||
Some(Ordering::Equal) => return Ok(front.len()),
|
||||
Some(Ordering::Less) => {
|
||||
return back[1..]
|
||||
.binary_search_by(f)
|
||||
.map(|idx| idx + front.len() + 1)
|
||||
.map_err(|idx| idx + front.len() + 1);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
front.binary_search_by(f)
|
||||
}
|
||||
|
||||
/// Binary searches this sorted `VecDeque` with a key extraction function.
|
||||
///
|
||||
/// Assumes that the `VecDeque` is sorted by the key, for instance with
|
||||
/// [`make_contiguous().sort_by_key()`](#method.make_contiguous) using the same
|
||||
/// key extraction function.
|
||||
///
|
||||
/// If the value is found then [`Result::Ok`] is returned, containing the
|
||||
/// index of the matching element. If there are multiple matches, then any
|
||||
/// one of the matches could be returned. If the value is not found then
|
||||
/// [`Result::Err`] is returned, containing the index where a matching
|
||||
/// element could be inserted while maintaining sorted order.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Looks up a series of four elements in a slice of pairs sorted by
|
||||
/// their second elements. The first is found, with a uniquely
|
||||
/// determined position; the second and third are not found; the
|
||||
/// fourth could match any position in `[1, 4]`.
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(vecdeque_binary_search)]
|
||||
/// use std::collections::VecDeque;
|
||||
///
|
||||
/// let deque: VecDeque<_> = vec![(0, 0), (2, 1), (4, 1), (5, 1),
|
||||
/// (3, 1), (1, 2), (2, 3), (4, 5), (5, 8), (3, 13),
|
||||
/// (1, 21), (2, 34), (4, 55)].into();
|
||||
///
|
||||
/// assert_eq!(deque.binary_search_by_key(&13, |&(a,b)| b), Ok(9));
|
||||
/// assert_eq!(deque.binary_search_by_key(&4, |&(a,b)| b), Err(7));
|
||||
/// assert_eq!(deque.binary_search_by_key(&100, |&(a,b)| b), Err(13));
|
||||
/// let r = deque.binary_search_by_key(&1, |&(a,b)| b);
|
||||
/// assert!(matches!(r, Ok(1..=4)));
|
||||
/// ```
|
||||
#[unstable(feature = "vecdeque_binary_search", issue = "1")]
|
||||
#[inline]
|
||||
pub fn binary_search_by_key<'a, B, F>(&'a self, b: &B, mut f: F) -> Result<usize, usize>
|
||||
where
|
||||
F: FnMut(&'a T) -> B,
|
||||
B: Ord,
|
||||
{
|
||||
self.binary_search_by(|k| f(k).cmp(b))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Clone> VecDeque<T> {
|
||||
|
@ -20,6 +20,7 @@
|
||||
#![feature(inplace_iteration)]
|
||||
#![feature(iter_map_while)]
|
||||
#![feature(int_bits_const)]
|
||||
#![feature(vecdeque_binary_search)]
|
||||
|
||||
use std::collections::hash_map::DefaultHasher;
|
||||
use std::hash::{Hash, Hasher};
|
||||
|
@ -1659,3 +1659,42 @@ fn test_drain_leak() {
|
||||
drop(v);
|
||||
assert_eq!(unsafe { DROPS }, 7);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_binary_search() {
|
||||
// Contiguous (front only) search:
|
||||
let deque: VecDeque<_> = vec![1, 2, 3, 5, 6].into();
|
||||
assert!(deque.as_slices().1.is_empty());
|
||||
assert_eq!(deque.binary_search(&3), Ok(2));
|
||||
assert_eq!(deque.binary_search(&4), Err(3));
|
||||
|
||||
// Split search (both front & back non-empty):
|
||||
let mut deque: VecDeque<_> = vec![5, 6].into();
|
||||
deque.push_front(3);
|
||||
deque.push_front(2);
|
||||
deque.push_front(1);
|
||||
deque.push_back(10);
|
||||
assert!(!deque.as_slices().0.is_empty());
|
||||
assert!(!deque.as_slices().1.is_empty());
|
||||
assert_eq!(deque.binary_search(&0), Err(0));
|
||||
assert_eq!(deque.binary_search(&1), Ok(0));
|
||||
assert_eq!(deque.binary_search(&5), Ok(3));
|
||||
assert_eq!(deque.binary_search(&7), Err(5));
|
||||
assert_eq!(deque.binary_search(&20), Err(6));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_binary_search_by() {
|
||||
let deque: VecDeque<_> = vec![(1,), (2,), (3,), (5,), (6,)].into();
|
||||
|
||||
assert_eq!(deque.binary_search_by(|&(v,)| v.cmp(&3)), Ok(2));
|
||||
assert_eq!(deque.binary_search_by(|&(v,)| v.cmp(&4)), Err(3));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_binary_search_by_key() {
|
||||
let deque: VecDeque<_> = vec![(1,), (2,), (3,), (5,), (6,)].into();
|
||||
|
||||
assert_eq!(deque.binary_search_by_key(&3, |&(v,)| v), Ok(2));
|
||||
assert_eq!(deque.binary_search_by_key(&4, |&(v,)| v), Err(3));
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user