Skip to content

Commit ff17a41

Browse files
committed
Implement from_vec and into_sorted_vec for BinaryHeap
1 parent fb6b0b1 commit ff17a41

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
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
77

88
## [Unreleased]
99

10+
### Added
11+
12+
- Added `from_vec` and `into_sorted_vec` implementations for `BinaryHeap`.
13+
1014
### Changed
1115

1216
- `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,
@@ -177,13 +172,74 @@ impl<T, K, const N: usize> BinaryHeap<T, K, N> {
177172
data: Vec::new(),
178173
}
179174
}
175+
176+
/// Creates a new `BinaryHeap` from a `Vec<T,N>`.
177+
/// The heap uses the vector as its backing storage, no additional space is required.
178+
/// The elements in the vector are rearranged to create the heap.
179+
/// The time complexity is *O*(n).
180+
///
181+
/// ```
182+
/// use heapless::binary_heap::{BinaryHeap, Max};
183+
/// use heapless::vec::Vec;
184+
///
185+
/// let vec = Vec::from_array([4, 1, 8, 7, 3, 0, 6, 9, 2, 5]);
186+
/// let heap: BinaryHeap<_, Max, 12> = BinaryHeap::from_vec(vec);
187+
/// assert_eq!(heap.len(), 10);
188+
/// assert_eq!(heap.capacity(), 12);
189+
/// assert_eq!(heap.peek(), Some(&9));
190+
/// ```
191+
pub fn from_vec(vec: Vec<T, N, usize>) -> Self
192+
where
193+
T: Ord,
194+
K: Kind
195+
{
196+
let mut heap = Self {
197+
_kind: PhantomData,
198+
data: vec,
199+
};
200+
let len = heap.len();
201+
for i in (0..len/2).rev() {
202+
heap.sift_down_to_bottom(i, len);
203+
}
204+
heap
205+
}
180206
}
181207

182208
impl<T, K, const N: usize> BinaryHeap<T, K, N> {
183209
/// Returns the underlying `Vec<T,N>`. Order is arbitrary and time is *O*(1).
184210
pub fn into_vec(self) -> Vec<T, N, usize> {
185211
self.data
186212
}
213+
214+
/// Returns the underlying `Vec<T,N>` sorted in ascending order.
215+
/// The time complexity is *O*(n log n).
216+
///
217+
/// ```
218+
/// use heapless::binary_heap::{BinaryHeap, Max};
219+
///
220+
/// let mut heap: BinaryHeap<_, Max, 4> = BinaryHeap::new();
221+
/// heap.push(4).unwrap();
222+
/// heap.push(2).unwrap();
223+
/// heap.push(8).unwrap();
224+
/// heap.push(1).unwrap();
225+
/// assert_eq!(heap.into_sorted_vec(), [1, 2, 4, 8]);
226+
/// ```
227+
pub fn into_sorted_vec(mut self) -> Vec<T, N, usize>
228+
where
229+
K: Kind,
230+
T: Ord,
231+
{
232+
let mut i = self.data.len();
233+
while i > 0 {
234+
i -= 1;
235+
unsafe {
236+
let p = self.data.as_mut_ptr();
237+
ptr::swap(p, p.add(i));
238+
}
239+
self.sift_down_to_bottom(0, i);
240+
}
241+
self.data
242+
}
187243
}
188244

189245
impl<T, K, S: VecStorage<T>> BinaryHeapInner<T, K, S> {
@@ -411,7 +467,7 @@ where
411467

412468
if !self.is_empty() {
413469
mem::swap(&mut item, self.data.as_mut_slice().get_unchecked_mut(0));
414-
self.sift_down_to_bottom(0);
470+
self.sift_down_to_bottom(0, self.len());
415471
}
416472
item
417473
}
@@ -463,8 +519,7 @@ where
463519
}
464520

465521
/* Private API */
466-
fn sift_down_to_bottom(&mut self, mut pos: usize) {
467-
let end = self.len();
522+
fn sift_down_to_bottom(&mut self, mut pos: usize, end: usize) {
468523
let start = pos;
469524
unsafe {
470525
let mut hole = Hole::new(self.data.as_mut_slice(), pos);
@@ -599,7 +654,7 @@ where
599654
{
600655
fn drop(&mut self) {
601656
if self.sift {
602-
self.heap.sift_down_to_bottom(0);
657+
self.heap.sift_down_to_bottom(0, self.heap.len());
603658
}
604659
}
605660
}
@@ -890,4 +945,28 @@ mod tests {
890945
) -> &'c BinaryHeapView<&'b (), Max> {
891946
x
892947
}
948+
949+
#[test]
950+
fn from_vec() {
951+
use crate::vec::Vec;
952+
953+
let src: Vec<_, 16, _> = Vec::from_array([4, 1, 12, 8, 7, 3, 0, 6, 9, 2, 5, 11, 10]);
954+
let heap: BinaryHeap<u8, Min, 16> = BinaryHeap::from_vec(src);
955+
assert_eq!(heap.len(), 13);
956+
assert_eq!(heap.capacity(), 16);
957+
assert_eq!(&heap.into_vec(), &[0, 1, 3, 6, 2, 4, 12, 8, 9, 7, 5, 11, 10]);
958+
}
959+
960+
#[test]
961+
fn into_sorted_vec() {
962+
use crate::vec::Vec;
963+
use core::array;
964+
965+
let src: Vec<_, 16, _> = Vec::from_array([4, 1, 12, 8, 7, 3, 0, 6, 9, 2, 5, 11, 10]);
966+
let heap: BinaryHeap<u8, Min, 16> = BinaryHeap::from_vec(src);
967+
let dst = heap.into_sorted_vec();
968+
assert_eq!(dst.len(), 13);
969+
assert_eq!(dst.capacity(), 16);
970+
assert_eq!(&dst, &array::from_fn::<u8, 13, _>(|x| 12 - x as u8));
971+
}
893972
}

0 commit comments

Comments
 (0)