Skip to content

Commit 6b88073

Browse files
committed
Add .into_iter_sorted() and .drain_sorted()
* `.drain_sorted()` doc change suggested by @KodrAus
1 parent d54111a commit 6b88073

File tree

3 files changed

+219
-5
lines changed

3 files changed

+219
-5
lines changed

src/liballoc/collections/binary_heap.rs

+140-1
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@
146146
#![stable(feature = "rust1", since = "1.0.0")]
147147

148148
use core::ops::{Deref, DerefMut};
149-
use core::iter::{FromIterator, FusedIterator};
149+
use core::iter::{FromIterator, FusedIterator, TrustedLen};
150150
use core::mem::{swap, size_of, ManuallyDrop};
151151
use core::ptr;
152152
use core::fmt;
@@ -672,6 +672,27 @@ impl<T> BinaryHeap<T> {
672672
Iter { iter: self.data.iter() }
673673
}
674674

675+
/// Returns an iterator which retrieves elements in heap order.
676+
/// This method consumes the original heap.
677+
///
678+
/// # Examples
679+
///
680+
/// Basic usage:
681+
///
682+
/// ```
683+
/// #![feature(binary_heap_into_iter_sorted)]
684+
/// use std::collections::BinaryHeap;
685+
/// let heap = BinaryHeap::from(vec![1, 2, 3, 4, 5]);
686+
///
687+
/// assert_eq!(heap.into_iter_sorted().take(2).collect::<Vec<_>>(), vec![5, 4]);
688+
/// ```
689+
#[unstable(feature = "binary_heap_into_iter_sorted", issue = "59278")]
690+
pub fn into_iter_sorted(self) -> IntoIterSorted<T> {
691+
IntoIterSorted {
692+
inner: self,
693+
}
694+
}
695+
675696
/// Returns the greatest item in the binary heap, or `None` if it is empty.
676697
///
677698
/// # Examples
@@ -899,6 +920,47 @@ impl<T> BinaryHeap<T> {
899920
Drain { iter: self.data.drain(..) }
900921
}
901922

923+
/// Returns an iterator which retrieves elements in heap order.
924+
/// The retrieved elements will be removed from the original heap.
925+
///
926+
/// Note:
927+
/// * Unlike other `.drain()` methods, this method removes elements *lazily*.
928+
/// In order to remove elements in heap order, you need to retrieve elements explicitly.
929+
/// * The remaining elements are removed on drop in arbitrary order.
930+
///
931+
/// # Examples
932+
///
933+
/// Basic usage:
934+
///
935+
/// ```
936+
/// #![feature(binary_heap_drain_sorted)]
937+
/// use std::collections::BinaryHeap;
938+
///
939+
/// let mut heap = BinaryHeap::from(vec![1, 2, 3, 4, 5]);
940+
/// assert_eq!(heap.len(), 5);
941+
///
942+
/// let len = heap.len();
943+
/// let removed = heap.drain_sorted()
944+
/// .take(len).collect::<Vec<_>>(); // removes all elements in *heap* order
945+
/// assert_eq!(removed, vec![5, 4, 3, 2, 1]);
946+
/// assert_eq!(heap.len(), 0);
947+
///
948+
///
949+
/// let mut heap = BinaryHeap::from(vec![1, 2, 3, 4, 5]);
950+
/// assert_eq!(heap.len(), 5);
951+
///
952+
/// let drain_sorted = heap.drain_sorted();
953+
/// drop(drain_sorted); // removes all elements in *arbitrary* order
954+
/// assert_eq!(heap.len(), 0);
955+
/// ```
956+
#[inline]
957+
#[unstable(feature = "binary_heap_drain_sorted", issue = "59278")]
958+
pub fn drain_sorted(&mut self) -> DrainSorted<'_, T> {
959+
DrainSorted {
960+
inner: self,
961+
}
962+
}
963+
902964
/// Drops all items from the binary heap.
903965
///
904966
/// # Examples
@@ -1115,6 +1177,37 @@ impl<T> ExactSizeIterator for IntoIter<T> {
11151177
#[stable(feature = "fused", since = "1.26.0")]
11161178
impl<T> FusedIterator for IntoIter<T> {}
11171179

1180+
#[unstable(feature = "binary_heap_into_iter_sorted", issue = "59278")]
1181+
#[derive(Clone, Debug)]
1182+
pub struct IntoIterSorted<T> {
1183+
inner: BinaryHeap<T>,
1184+
}
1185+
1186+
#[unstable(feature = "binary_heap_into_iter_sorted", issue = "59278")]
1187+
impl<T: Ord> Iterator for IntoIterSorted<T> {
1188+
type Item = T;
1189+
1190+
#[inline]
1191+
fn next(&mut self) -> Option<T> {
1192+
self.inner.pop()
1193+
}
1194+
1195+
#[inline]
1196+
fn size_hint(&self) -> (usize, Option<usize>) {
1197+
let exact = self.inner.len();
1198+
(exact, Some(exact))
1199+
}
1200+
}
1201+
1202+
#[unstable(feature = "binary_heap_into_iter_sorted", issue = "59278")]
1203+
impl<T: Ord> ExactSizeIterator for IntoIterSorted<T> {}
1204+
1205+
#[unstable(feature = "binary_heap_into_iter_sorted", issue = "59278")]
1206+
impl<T: Ord> FusedIterator for IntoIterSorted<T> {}
1207+
1208+
#[unstable(feature = "trusted_len", issue = "37572")]
1209+
unsafe impl<T: Ord> TrustedLen for IntoIterSorted<T> {}
1210+
11181211
/// A draining iterator over the elements of a `BinaryHeap`.
11191212
///
11201213
/// This `struct` is created by the [`drain`] method on [`BinaryHeap`]. See its
@@ -1161,6 +1254,52 @@ impl<T> ExactSizeIterator for Drain<'_, T> {
11611254
#[stable(feature = "fused", since = "1.26.0")]
11621255
impl<T> FusedIterator for Drain<'_, T> {}
11631256

1257+
/// A draining iterator over the elements of a `BinaryHeap`.
1258+
///
1259+
/// This `struct` is created by the [`drain_sorted`] method on [`BinaryHeap`]. See its
1260+
/// documentation for more.
1261+
///
1262+
/// [`drain_sorted`]: struct.BinaryHeap.html#method.drain_sorted
1263+
/// [`BinaryHeap`]: struct.BinaryHeap.html
1264+
#[unstable(feature = "binary_heap_drain_sorted", issue = "59278")]
1265+
#[derive(Debug)]
1266+
pub struct DrainSorted<'a, T> {
1267+
inner: &'a mut BinaryHeap<T>,
1268+
}
1269+
1270+
#[unstable(feature = "binary_heap_drain_sorted", issue = "59278")]
1271+
impl<'a, T> Drop for DrainSorted<'a, T> {
1272+
/// Removes heap elements in arbitrary order for efficiency.
1273+
fn drop(&mut self) {
1274+
self.inner.drain();
1275+
}
1276+
}
1277+
1278+
#[unstable(feature = "binary_heap_drain_sorted", issue = "59278")]
1279+
impl<T: Ord> Iterator for DrainSorted<'_, T> {
1280+
type Item = T;
1281+
1282+
#[inline]
1283+
fn next(&mut self) -> Option<T> {
1284+
self.inner.pop()
1285+
}
1286+
1287+
#[inline]
1288+
fn size_hint(&self) -> (usize, Option<usize>) {
1289+
let exact = self.inner.len();
1290+
(exact, Some(exact))
1291+
}
1292+
}
1293+
1294+
#[unstable(feature = "binary_heap_drain_sorted", issue = "59278")]
1295+
impl<T: Ord> ExactSizeIterator for DrainSorted<'_, T> { }
1296+
1297+
#[unstable(feature = "binary_heap_drain_sorted", issue = "59278")]
1298+
impl<T: Ord> FusedIterator for DrainSorted<'_, T> {}
1299+
1300+
#[unstable(feature = "trusted_len", issue = "37572")]
1301+
unsafe impl<T: Ord> TrustedLen for DrainSorted<'_, T> {}
1302+
11641303
#[stable(feature = "binary_heap_extras_15", since = "1.5.0")]
11651304
impl<T: Ord> From<Vec<T>> for BinaryHeap<T> {
11661305
/// Converts a `Vec<T>` into a `BinaryHeap<T>`.

src/liballoc/tests/binary_heap.rs

+77-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
use std::collections::BinaryHeap;
22
use std::collections::binary_heap::{Drain, PeekMut};
3+
use std::panic::{self, AssertUnwindSafe};
4+
use std::sync::atomic::{AtomicUsize, Ordering};
5+
use std::iter::TrustedLen;
6+
7+
use rand::{thread_rng, seq::SliceRandom};
38

49
#[test]
510
fn test_iterator() {
@@ -14,7 +19,7 @@ fn test_iterator() {
1419
}
1520

1621
#[test]
17-
fn test_iterator_reverse() {
22+
fn test_iter_rev_cloned_collect() {
1823
let data = vec![5, 9, 3];
1924
let iterout = vec![3, 5, 9];
2025
let pq = BinaryHeap::from(data);
@@ -24,7 +29,7 @@ fn test_iterator_reverse() {
2429
}
2530

2631
#[test]
27-
fn test_move_iter() {
32+
fn test_into_iter_collect() {
2833
let data = vec![5, 9, 3];
2934
let iterout = vec![9, 5, 3];
3035
let pq = BinaryHeap::from(data);
@@ -34,7 +39,7 @@ fn test_move_iter() {
3439
}
3540

3641
#[test]
37-
fn test_move_iter_size_hint() {
42+
fn test_into_iter_size_hint() {
3843
let data = vec![5, 9];
3944
let pq = BinaryHeap::from(data);
4045

@@ -51,7 +56,7 @@ fn test_move_iter_size_hint() {
5156
}
5257

5358
#[test]
54-
fn test_move_iter_reverse() {
59+
fn test_into_iter_rev_collect() {
5560
let data = vec![5, 9, 3];
5661
let iterout = vec![3, 5, 9];
5762
let pq = BinaryHeap::from(data);
@@ -60,6 +65,65 @@ fn test_move_iter_reverse() {
6065
assert_eq!(v, iterout);
6166
}
6267

68+
#[test]
69+
fn test_into_iter_sorted_collect() {
70+
let heap = BinaryHeap::from(vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]);
71+
let it = heap.into_iter_sorted();
72+
let sorted = it.collect::<Vec<_>>();
73+
assert_eq!(sorted, vec![10, 9, 8, 7, 6, 5, 4, 3, 2, 2, 1, 1, 0]);
74+
}
75+
76+
#[test]
77+
fn test_drain_sorted_collect() {
78+
let mut heap = BinaryHeap::from(vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]);
79+
let it = heap.drain_sorted();
80+
let sorted = it.collect::<Vec<_>>();
81+
assert_eq!(sorted, vec![10, 9, 8, 7, 6, 5, 4, 3, 2, 2, 1, 1, 0]);
82+
}
83+
84+
fn check_exact_size_iterator<I: ExactSizeIterator>(len: usize, it: I) {
85+
let mut it = it;
86+
87+
for i in 0..it.len() {
88+
let (lower, upper) = it.size_hint();
89+
assert_eq!(Some(lower), upper);
90+
assert_eq!(lower, len - i);
91+
assert_eq!(it.len(), len - i);
92+
it.next();
93+
}
94+
assert_eq!(it.len(), 0);
95+
assert!(it.is_empty());
96+
}
97+
98+
#[test]
99+
fn test_exact_size_iterator() {
100+
let heap = BinaryHeap::from(vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]);
101+
check_exact_size_iterator(heap.len(), heap.iter());
102+
check_exact_size_iterator(heap.len(), heap.clone().into_iter());
103+
check_exact_size_iterator(heap.len(), heap.clone().into_iter_sorted());
104+
check_exact_size_iterator(heap.len(), heap.clone().drain());
105+
check_exact_size_iterator(heap.len(), heap.clone().drain_sorted());
106+
}
107+
108+
fn check_trusted_len<I: TrustedLen>(len: usize, it: I) {
109+
let mut it = it;
110+
for i in 0..len {
111+
let (lower, upper) = it.size_hint();
112+
if upper.is_some() {
113+
assert_eq!(Some(lower), upper);
114+
assert_eq!(lower, len - i);
115+
}
116+
it.next();
117+
}
118+
}
119+
120+
#[test]
121+
fn test_trusted_len() {
122+
let heap = BinaryHeap::from(vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]);
123+
check_trusted_len(heap.len(), heap.clone().into_iter_sorted());
124+
check_trusted_len(heap.len(), heap.clone().drain_sorted());
125+
}
126+
63127
#[test]
64128
fn test_peek_and_pop() {
65129
let data = vec![2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1];
@@ -206,6 +270,15 @@ fn test_drain() {
206270
assert!(q.is_empty());
207271
}
208272

273+
#[test]
274+
fn test_drain_sorted() {
275+
let mut q: BinaryHeap<_> = [9, 8, 7, 6, 5, 4, 3, 2, 1].iter().cloned().collect();
276+
277+
assert_eq!(q.drain_sorted().take(5).collect::<Vec<_>>(), vec![9, 8, 7, 6, 5]);
278+
279+
assert!(q.is_empty());
280+
}
281+
209282
#[test]
210283
fn test_extend_ref() {
211284
let mut a = BinaryHeap::new();

src/liballoc/tests/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
#![feature(try_reserve)]
1010
#![feature(unboxed_closures)]
1111
#![feature(associated_type_bounds)]
12+
#![feature(binary_heap_into_iter_sorted)]
13+
#![feature(binary_heap_drain_sorted)]
1214

1315
use std::hash::{Hash, Hasher};
1416
use std::collections::hash_map::DefaultHasher;

0 commit comments

Comments
 (0)