Skip to content

Commit 36d9b72

Browse files
committed
liballoc: VecDeque: Add binary search functions
1 parent fc3d8e3 commit 36d9b72

File tree

3 files changed

+189
-1
lines changed

3 files changed

+189
-1
lines changed

library/alloc/src/collections/vec_deque.rs

+149-1
Original file line numberDiff line numberDiff line change
@@ -2181,7 +2181,7 @@ impl<T> VecDeque<T> {
21812181
///
21822182
/// This method does not allocate and does not change the order of the
21832183
/// inserted elements. As it returns a mutable slice, this can be used to
2184-
/// sort or binary search a deque.
2184+
/// sort a deque.
21852185
///
21862186
/// Once the internal storage is contiguous, the [`as_slices`] and
21872187
/// [`as_mut_slices`] methods will return the entire contents of the
@@ -2430,6 +2430,154 @@ impl<T> VecDeque<T> {
24302430
self.wrap_copy(self.tail, self.head, k);
24312431
}
24322432
}
2433+
2434+
/// Binary searches this sorted `VecDeque` for a given element.
2435+
///
2436+
/// If the value is found then [`Result::Ok`] is returned, containing the
2437+
/// index of the matching element. If there are multiple matches, then any
2438+
/// one of the matches could be returned. If the value is not found then
2439+
/// [`Result::Err`] is returned, containing the index where a matching
2440+
/// element could be inserted while maintaining sorted order.
2441+
///
2442+
/// # Examples
2443+
///
2444+
/// Looks up a series of four elements. The first is found, with a
2445+
/// uniquely determined position; the second and third are not
2446+
/// found; the fourth could match any position in `[1, 4]`.
2447+
///
2448+
/// ```
2449+
/// #![feature(vecdeque_binary_search)]
2450+
/// use std::collections::VecDeque;
2451+
///
2452+
/// let deque: VecDeque<_> = vec![0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55].into();
2453+
///
2454+
/// assert_eq!(deque.binary_search(&13), Ok(9));
2455+
/// assert_eq!(deque.binary_search(&4), Err(7));
2456+
/// assert_eq!(deque.binary_search(&100), Err(13));
2457+
/// let r = deque.binary_search(&1);
2458+
/// assert!(matches!(r, Ok(1..=4)));
2459+
/// ```
2460+
///
2461+
/// If you want to insert an item to a sorted `VecDeque`, while maintaining
2462+
/// sort order:
2463+
///
2464+
/// ```
2465+
/// #![feature(vecdeque_binary_search)]
2466+
/// use std::collections::VecDeque;
2467+
///
2468+
/// let mut deque: VecDeque<_> = vec![0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55].into();
2469+
/// let num = 42;
2470+
/// let idx = deque.binary_search(&num).unwrap_or_else(|x| x);
2471+
/// deque.insert(idx, num);
2472+
/// assert_eq!(deque, &[0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 42, 55]);
2473+
/// ```
2474+
#[unstable(feature = "vecdeque_binary_search", issue = "1")]
2475+
#[inline]
2476+
pub fn binary_search(&self, x: &T) -> Result<usize, usize>
2477+
where
2478+
T: Ord,
2479+
{
2480+
self.binary_search_by(|e| e.cmp(x))
2481+
}
2482+
2483+
/// Binary searches this sorted `VecDeque` with a comparator function.
2484+
///
2485+
/// The comparator function should implement an order consistent
2486+
/// with the sort order of the underlying `VecDeque`, returning an
2487+
/// order code that indicates whether its argument is `Less`,
2488+
/// `Equal` or `Greater` than the desired target.
2489+
///
2490+
/// If the value is found then [`Result::Ok`] is returned, containing the
2491+
/// index of the matching element. If there are multiple matches, then any
2492+
/// one of the matches could be returned. If the value is not found then
2493+
/// [`Result::Err`] is returned, containing the index where a matching
2494+
/// element could be inserted while maintaining sorted order.
2495+
///
2496+
/// # Examples
2497+
///
2498+
/// Looks up a series of four elements. The first is found, with a
2499+
/// uniquely determined position; the second and third are not
2500+
/// found; the fourth could match any position in `[1, 4]`.
2501+
///
2502+
/// ```
2503+
/// #![feature(vecdeque_binary_search)]
2504+
/// use std::collections::VecDeque;
2505+
///
2506+
/// let deque: VecDeque<_> = vec![0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55].into();
2507+
///
2508+
/// assert_eq!(deque.binary_search_by(|x| x.cmp(&13)), Ok(9));
2509+
/// assert_eq!(deque.binary_search_by(|x| x.cmp(&4)), Err(7));
2510+
/// assert_eq!(deque.binary_search_by(|x| x.cmp(&100)), Err(13));
2511+
/// let r = deque.binary_search_by(|x| x.cmp(&1));
2512+
/// assert!(matches!(r, Ok(1..=4)));
2513+
/// ```
2514+
#[unstable(feature = "vecdeque_binary_search", issue = "1")]
2515+
pub fn binary_search_by<'a, F>(&'a self, mut f: F) -> Result<usize, usize>
2516+
where
2517+
F: FnMut(&'a T) -> Ordering,
2518+
{
2519+
if self.is_empty() {
2520+
return Err(0);
2521+
}
2522+
2523+
let (front, back) = self.as_slices();
2524+
2525+
match back.first().map(|elem| f(elem)) {
2526+
Some(Ordering::Equal) => return Ok(front.len()),
2527+
Some(Ordering::Less) => {
2528+
return back[1..]
2529+
.binary_search_by(f)
2530+
.map(|idx| idx + front.len() + 1)
2531+
.map_err(|idx| idx + front.len() + 1);
2532+
}
2533+
_ => {}
2534+
}
2535+
2536+
front.binary_search_by(f)
2537+
}
2538+
2539+
/// Binary searches this sorted `VecDeque` with a key extraction function.
2540+
///
2541+
/// Assumes that the `VecDeque` is sorted by the key, for instance with
2542+
/// [`make_contiguous().sort_by_key()`](#method.make_contiguous) using the same
2543+
/// key extraction function.
2544+
///
2545+
/// If the value is found then [`Result::Ok`] is returned, containing the
2546+
/// index of the matching element. If there are multiple matches, then any
2547+
/// one of the matches could be returned. If the value is not found then
2548+
/// [`Result::Err`] is returned, containing the index where a matching
2549+
/// element could be inserted while maintaining sorted order.
2550+
///
2551+
/// # Examples
2552+
///
2553+
/// Looks up a series of four elements in a slice of pairs sorted by
2554+
/// their second elements. The first is found, with a uniquely
2555+
/// determined position; the second and third are not found; the
2556+
/// fourth could match any position in `[1, 4]`.
2557+
///
2558+
/// ```
2559+
/// #![feature(vecdeque_binary_search)]
2560+
/// use std::collections::VecDeque;
2561+
///
2562+
/// let deque: VecDeque<_> = vec![(0, 0), (2, 1), (4, 1), (5, 1),
2563+
/// (3, 1), (1, 2), (2, 3), (4, 5), (5, 8), (3, 13),
2564+
/// (1, 21), (2, 34), (4, 55)].into();
2565+
///
2566+
/// assert_eq!(deque.binary_search_by_key(&13, |&(a,b)| b), Ok(9));
2567+
/// assert_eq!(deque.binary_search_by_key(&4, |&(a,b)| b), Err(7));
2568+
/// assert_eq!(deque.binary_search_by_key(&100, |&(a,b)| b), Err(13));
2569+
/// let r = deque.binary_search_by_key(&1, |&(a,b)| b);
2570+
/// assert!(matches!(r, Ok(1..=4)));
2571+
/// ```
2572+
#[unstable(feature = "vecdeque_binary_search", issue = "1")]
2573+
#[inline]
2574+
pub fn binary_search_by_key<'a, B, F>(&'a self, b: &B, mut f: F) -> Result<usize, usize>
2575+
where
2576+
F: FnMut(&'a T) -> B,
2577+
B: Ord,
2578+
{
2579+
self.binary_search_by(|k| f(k).cmp(b))
2580+
}
24332581
}
24342582

24352583
impl<T: Clone> VecDeque<T> {

library/alloc/tests/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#![feature(inplace_iteration)]
2121
#![feature(iter_map_while)]
2222
#![feature(int_bits_const)]
23+
#![feature(vecdeque_binary_search)]
2324

2425
use std::collections::hash_map::DefaultHasher;
2526
use std::hash::{Hash, Hasher};

library/alloc/tests/vec_deque.rs

+39
Original file line numberDiff line numberDiff line change
@@ -1659,3 +1659,42 @@ fn test_drain_leak() {
16591659
drop(v);
16601660
assert_eq!(unsafe { DROPS }, 7);
16611661
}
1662+
1663+
#[test]
1664+
fn test_binary_search() {
1665+
// Contiguous (front only) search:
1666+
let deque: VecDeque<_> = vec![1, 2, 3, 5, 6].into();
1667+
assert!(deque.as_slices().1.is_empty());
1668+
assert_eq!(deque.binary_search(&3), Ok(2));
1669+
assert_eq!(deque.binary_search(&4), Err(3));
1670+
1671+
// Split search (both front & back non-empty):
1672+
let mut deque: VecDeque<_> = vec![5, 6].into();
1673+
deque.push_front(3);
1674+
deque.push_front(2);
1675+
deque.push_front(1);
1676+
deque.push_back(10);
1677+
assert!(!deque.as_slices().0.is_empty());
1678+
assert!(!deque.as_slices().1.is_empty());
1679+
assert_eq!(deque.binary_search(&0), Err(0));
1680+
assert_eq!(deque.binary_search(&1), Ok(0));
1681+
assert_eq!(deque.binary_search(&5), Ok(3));
1682+
assert_eq!(deque.binary_search(&7), Err(5));
1683+
assert_eq!(deque.binary_search(&20), Err(6));
1684+
}
1685+
1686+
#[test]
1687+
fn test_binary_search_by() {
1688+
let deque: VecDeque<_> = vec![(1,), (2,), (3,), (5,), (6,)].into();
1689+
1690+
assert_eq!(deque.binary_search_by(|&(v,)| v.cmp(&3)), Ok(2));
1691+
assert_eq!(deque.binary_search_by(|&(v,)| v.cmp(&4)), Err(3));
1692+
}
1693+
1694+
#[test]
1695+
fn test_binary_search_by_key() {
1696+
let deque: VecDeque<_> = vec![(1,), (2,), (3,), (5,), (6,)].into();
1697+
1698+
assert_eq!(deque.binary_search_by_key(&3, |&(v,)| v), Ok(2));
1699+
assert_eq!(deque.binary_search_by_key(&4, |&(v,)| v), Err(3));
1700+
}

0 commit comments

Comments
 (0)