Skip to content

Commit 20fe9f5

Browse files
silyevsksgued
authored andcommitted
Implement from_vec and into_sorted_vec for BinaryHeap
1 parent fba1da4 commit 20fe9f5

2 files changed

Lines changed: 92 additions & 9 deletions

File tree

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ of panicking drop implementations.
5050

5151
- Added optional `embedded_io::Write` impl for `Vec`.
5252

53+
### Added
54+
55+
- Added `from_vec` and `into_sorted_vec` implementations for `BinaryHeap`.
56+
5357
### Changed
5458

5559
- `bytes::BufMut` is now implemented on `VecInner`.

src/binary_heap.rs

Lines changed: 88 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,6 @@
33
//! Insertion and popping the largest element have *O*(log n) time complexity.
44
//! Checking the smallest/largest element is *O*(1).
55
6-
// TODO not yet implemented
7-
// Converting a vector to a binary heap can be done in-place, and has *O*(n) complexity. A binary
8-
// heap can also be converted to a sorted vector in-place, allowing it to be used for an
9-
// *O*(n log n) in-place heapsort.
10-
116
use core::{
127
cmp::Ordering,
138
fmt,
@@ -185,13 +180,74 @@ impl<T, K, const N: usize> BinaryHeap<T, K, N> {
185180
data: Vec::new(),
186181
}
187182
}
183+
184+
/// Creates a new `BinaryHeap` from a `Vec<T,N>`.
185+
/// The heap uses the vector as its backing storage, no additional space is required.
186+
/// The elements in the vector are rearranged to create the heap.
187+
/// The time complexity is *O*(n).
188+
///
189+
/// ```
190+
/// use heapless::binary_heap::{BinaryHeap, Max};
191+
/// use heapless::vec::Vec;
192+
///
193+
/// let vec = Vec::from_array([4, 1, 8, 7, 3, 0, 6, 9, 2, 5]);
194+
/// let heap: BinaryHeap<_, Max, 12> = BinaryHeap::from_vec(vec);
195+
/// assert_eq!(heap.len(), 10);
196+
/// assert_eq!(heap.capacity(), 12);
197+
/// assert_eq!(heap.peek(), Some(&9));
198+
/// ```
199+
pub fn from_vec(vec: Vec<T, N, usize>) -> Self
200+
where
201+
T: Ord,
202+
K: Kind
203+
{
204+
let mut heap = Self {
205+
_kind: PhantomData,
206+
data: vec,
207+
};
208+
let len = heap.len();
209+
for i in (0..len/2).rev() {
210+
heap.sift_down_to_bottom(i, len);
211+
}
212+
heap
213+
}
188214
}
189215

190216
impl<T, K, const N: usize> BinaryHeap<T, K, N> {
191217
/// Returns the underlying `Vec<T,N>`. Order is arbitrary and time is *O*(1).
192218
pub fn into_vec(self) -> Vec<T, N, usize> {
193219
self.data
194220
}
221+
222+
/// Returns the underlying `Vec<T,N>` sorted in ascending order.
223+
/// The time complexity is *O*(n log n).
224+
///
225+
/// ```
226+
/// use heapless::binary_heap::{BinaryHeap, Max};
227+
///
228+
/// let mut heap: BinaryHeap<_, Max, 4> = BinaryHeap::new();
229+
/// heap.push(4).unwrap();
230+
/// heap.push(2).unwrap();
231+
/// heap.push(8).unwrap();
232+
/// heap.push(1).unwrap();
233+
/// assert_eq!(heap.into_sorted_vec(), [1, 2, 4, 8]);
234+
/// ```
235+
pub fn into_sorted_vec(mut self) -> Vec<T, N, usize>
236+
where
237+
K: Kind,
238+
T: Ord,
239+
{
240+
let mut i = self.data.len();
241+
while i > 0 {
242+
i -= 1;
243+
unsafe {
244+
let p = self.data.as_mut_ptr();
245+
ptr::swap(p, p.add(i));
246+
}
247+
self.sift_down_to_bottom(0, i);
248+
}
249+
self.data
250+
}
195251
}
196252

197253
impl<T, K, S: VecStorage<T>> BinaryHeapInner<T, K, S> {
@@ -419,7 +475,7 @@ where
419475

420476
if !self.is_empty() {
421477
mem::swap(&mut item, self.data.as_mut_slice().get_unchecked_mut(0));
422-
self.sift_down_to_bottom(0);
478+
self.sift_down_to_bottom(0, self.len());
423479
}
424480
item
425481
}
@@ -471,8 +527,7 @@ where
471527
}
472528

473529
/* Private API */
474-
fn sift_down_to_bottom(&mut self, mut pos: usize) {
475-
let end = self.len();
530+
fn sift_down_to_bottom(&mut self, mut pos: usize, end: usize) {
476531
let start = pos;
477532
unsafe {
478533
let mut hole = Hole::new(self.data.as_mut_slice(), pos);
@@ -607,7 +662,7 @@ where
607662
{
608663
fn drop(&mut self) {
609664
if self.sift {
610-
self.heap.sift_down_to_bottom(0);
665+
self.heap.sift_down_to_bottom(0, self.heap.len());
611666
}
612667
}
613668
}
@@ -916,4 +971,28 @@ mod tests {
916971
) -> &'c BinaryHeapView<&'b (), Max> {
917972
x
918973
}
974+
975+
#[test]
976+
fn from_vec() {
977+
use crate::vec::Vec;
978+
979+
let src: Vec<_, 16, _> = Vec::from_array([4, 1, 12, 8, 7, 3, 0, 6, 9, 2, 5, 11, 10]);
980+
let heap: BinaryHeap<u8, Min, 16> = BinaryHeap::from_vec(src);
981+
assert_eq!(heap.len(), 13);
982+
assert_eq!(heap.capacity(), 16);
983+
assert_eq!(&heap.into_vec(), &[0, 1, 3, 6, 2, 4, 12, 8, 9, 7, 5, 11, 10]);
984+
}
985+
986+
#[test]
987+
fn into_sorted_vec() {
988+
use crate::vec::Vec;
989+
use core::array;
990+
991+
let src: Vec<_, 16, _> = Vec::from_array([4, 1, 12, 8, 7, 3, 0, 6, 9, 2, 5, 11, 10]);
992+
let heap: BinaryHeap<u8, Min, 16> = BinaryHeap::from_vec(src);
993+
let dst = heap.into_sorted_vec();
994+
assert_eq!(dst.len(), 13);
995+
assert_eq!(dst.capacity(), 16);
996+
assert_eq!(&dst, &array::from_fn::<u8, 13, _>(|x| 12 - x as u8));
997+
}
919998
}

0 commit comments

Comments
 (0)