From 20fe9f500df38e5cab67e1223ab68bb7bea0c418 Mon Sep 17 00:00:00 2001 From: Sergey Ilyevsky Date: Mon, 5 May 2025 10:59:25 +0300 Subject: [PATCH 1/3] Implement `from_vec` and `into_sorted_vec` for `BinaryHeap` --- CHANGELOG.md | 4 ++ src/binary_heap.rs | 97 +++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 92 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d21f26cbb7..57c8e7c853 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -50,6 +50,10 @@ of panicking drop implementations. - Added optional `embedded_io::Write` impl for `Vec`. +### Added + +- Added `from_vec` and `into_sorted_vec` implementations for `BinaryHeap`. + ### Changed - `bytes::BufMut` is now implemented on `VecInner`. diff --git a/src/binary_heap.rs b/src/binary_heap.rs index 452b84a13e..68465bb5fe 100644 --- a/src/binary_heap.rs +++ b/src/binary_heap.rs @@ -3,11 +3,6 @@ //! Insertion and popping the largest element have *O*(log n) time complexity. //! Checking the smallest/largest element is *O*(1). -// TODO not yet implemented -// Converting a vector to a binary heap can be done in-place, and has *O*(n) complexity. A binary -// heap can also be converted to a sorted vector in-place, allowing it to be used for an -// *O*(n log n) in-place heapsort. - use core::{ cmp::Ordering, fmt, @@ -185,6 +180,37 @@ impl BinaryHeap { data: Vec::new(), } } + + /// Creates a new `BinaryHeap` from a `Vec`. + /// The heap uses the vector as its backing storage, no additional space is required. + /// The elements in the vector are rearranged to create the heap. + /// The time complexity is *O*(n). + /// + /// ``` + /// use heapless::binary_heap::{BinaryHeap, Max}; + /// use heapless::vec::Vec; + /// + /// let vec = Vec::from_array([4, 1, 8, 7, 3, 0, 6, 9, 2, 5]); + /// let heap: BinaryHeap<_, Max, 12> = BinaryHeap::from_vec(vec); + /// assert_eq!(heap.len(), 10); + /// assert_eq!(heap.capacity(), 12); + /// assert_eq!(heap.peek(), Some(&9)); + /// ``` + pub fn from_vec(vec: Vec) -> Self + where + T: Ord, + K: Kind + { + let mut heap = Self { + _kind: PhantomData, + data: vec, + }; + let len = heap.len(); + for i in (0..len/2).rev() { + heap.sift_down_to_bottom(i, len); + } + heap + } } impl BinaryHeap { @@ -192,6 +218,36 @@ impl BinaryHeap { pub fn into_vec(self) -> Vec { self.data } + + /// Returns the underlying `Vec` sorted in ascending order. + /// The time complexity is *O*(n log n). + /// + /// ``` + /// use heapless::binary_heap::{BinaryHeap, Max}; + /// + /// let mut heap: BinaryHeap<_, Max, 4> = BinaryHeap::new(); + /// heap.push(4).unwrap(); + /// heap.push(2).unwrap(); + /// heap.push(8).unwrap(); + /// heap.push(1).unwrap(); + /// assert_eq!(heap.into_sorted_vec(), [1, 2, 4, 8]); + /// ``` + pub fn into_sorted_vec(mut self) -> Vec + where + K: Kind, + T: Ord, + { + let mut i = self.data.len(); + while i > 0 { + i -= 1; + unsafe { + let p = self.data.as_mut_ptr(); + ptr::swap(p, p.add(i)); + } + self.sift_down_to_bottom(0, i); + } + self.data + } } impl> BinaryHeapInner { @@ -419,7 +475,7 @@ where if !self.is_empty() { mem::swap(&mut item, self.data.as_mut_slice().get_unchecked_mut(0)); - self.sift_down_to_bottom(0); + self.sift_down_to_bottom(0, self.len()); } item } @@ -471,8 +527,7 @@ where } /* Private API */ - fn sift_down_to_bottom(&mut self, mut pos: usize) { - let end = self.len(); + fn sift_down_to_bottom(&mut self, mut pos: usize, end: usize) { let start = pos; unsafe { let mut hole = Hole::new(self.data.as_mut_slice(), pos); @@ -607,7 +662,7 @@ where { fn drop(&mut self) { if self.sift { - self.heap.sift_down_to_bottom(0); + self.heap.sift_down_to_bottom(0, self.heap.len()); } } } @@ -916,4 +971,28 @@ mod tests { ) -> &'c BinaryHeapView<&'b (), Max> { x } + + #[test] + fn from_vec() { + use crate::vec::Vec; + + let src: Vec<_, 16, _> = Vec::from_array([4, 1, 12, 8, 7, 3, 0, 6, 9, 2, 5, 11, 10]); + let heap: BinaryHeap = BinaryHeap::from_vec(src); + assert_eq!(heap.len(), 13); + assert_eq!(heap.capacity(), 16); + assert_eq!(&heap.into_vec(), &[0, 1, 3, 6, 2, 4, 12, 8, 9, 7, 5, 11, 10]); + } + + #[test] + fn into_sorted_vec() { + use crate::vec::Vec; + use core::array; + + let src: Vec<_, 16, _> = Vec::from_array([4, 1, 12, 8, 7, 3, 0, 6, 9, 2, 5, 11, 10]); + let heap: BinaryHeap = BinaryHeap::from_vec(src); + let dst = heap.into_sorted_vec(); + assert_eq!(dst.len(), 13); + assert_eq!(dst.capacity(), 16); + assert_eq!(&dst, &array::from_fn::(|x| 12 - x as u8)); + } } From 03fc8f4de354e9144088cda552d9a74257d0b3bb Mon Sep 17 00:00:00 2001 From: Sergey Ilyevsky Date: Mon, 5 May 2025 11:07:32 +0300 Subject: [PATCH 2/3] Fix style --- src/binary_heap.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/binary_heap.rs b/src/binary_heap.rs index 68465bb5fe..5242c6946c 100644 --- a/src/binary_heap.rs +++ b/src/binary_heap.rs @@ -199,14 +199,14 @@ impl BinaryHeap { pub fn from_vec(vec: Vec) -> Self where T: Ord, - K: Kind + K: Kind, { let mut heap = Self { _kind: PhantomData, data: vec, }; let len = heap.len(); - for i in (0..len/2).rev() { + for i in (0..len / 2).rev() { heap.sift_down_to_bottom(i, len); } heap @@ -980,7 +980,10 @@ mod tests { let heap: BinaryHeap = BinaryHeap::from_vec(src); assert_eq!(heap.len(), 13); assert_eq!(heap.capacity(), 16); - assert_eq!(&heap.into_vec(), &[0, 1, 3, 6, 2, 4, 12, 8, 9, 7, 5, 11, 10]); + assert_eq!( + &heap.into_vec(), + &[0, 1, 3, 6, 2, 4, 12, 8, 9, 7, 5, 11, 10] + ); } #[test] From fa1cabc010d3f028bf69d324576f5f963b51e3a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sosth=C3=A8ne=20Gu=C3=A9don?= Date: Tue, 14 Apr 2026 22:14:23 +0200 Subject: [PATCH 3/3] Replace from_vec with From> impl --- src/binary_heap.rs | 48 +++++++++++++++------------------------------- 1 file changed, 15 insertions(+), 33 deletions(-) diff --git a/src/binary_heap.rs b/src/binary_heap.rs index 5242c6946c..f3dcc43768 100644 --- a/src/binary_heap.rs +++ b/src/binary_heap.rs @@ -180,37 +180,6 @@ impl BinaryHeap { data: Vec::new(), } } - - /// Creates a new `BinaryHeap` from a `Vec`. - /// The heap uses the vector as its backing storage, no additional space is required. - /// The elements in the vector are rearranged to create the heap. - /// The time complexity is *O*(n). - /// - /// ``` - /// use heapless::binary_heap::{BinaryHeap, Max}; - /// use heapless::vec::Vec; - /// - /// let vec = Vec::from_array([4, 1, 8, 7, 3, 0, 6, 9, 2, 5]); - /// let heap: BinaryHeap<_, Max, 12> = BinaryHeap::from_vec(vec); - /// assert_eq!(heap.len(), 10); - /// assert_eq!(heap.capacity(), 12); - /// assert_eq!(heap.peek(), Some(&9)); - /// ``` - pub fn from_vec(vec: Vec) -> Self - where - T: Ord, - K: Kind, - { - let mut heap = Self { - _kind: PhantomData, - data: vec, - }; - let len = heap.len(); - for i in (0..len / 2).rev() { - heap.sift_down_to_bottom(i, len); - } - heap - } } impl BinaryHeap { @@ -742,6 +711,19 @@ where } } +impl From> for BinaryHeap { + fn from(vec: Vec) -> Self { + let mut heap = Self { + _kind: PhantomData, + data: vec, + }; + let len = heap.len(); + for i in (0..len / 2).rev() { + heap.sift_down_to_bottom(i, len); + } + heap + } +} impl fmt::Debug for BinaryHeapInner where K: Kind, @@ -977,7 +959,7 @@ mod tests { use crate::vec::Vec; let src: Vec<_, 16, _> = Vec::from_array([4, 1, 12, 8, 7, 3, 0, 6, 9, 2, 5, 11, 10]); - let heap: BinaryHeap = BinaryHeap::from_vec(src); + let heap: BinaryHeap = BinaryHeap::from(src); assert_eq!(heap.len(), 13); assert_eq!(heap.capacity(), 16); assert_eq!( @@ -992,7 +974,7 @@ mod tests { use core::array; let src: Vec<_, 16, _> = Vec::from_array([4, 1, 12, 8, 7, 3, 0, 6, 9, 2, 5, 11, 10]); - let heap: BinaryHeap = BinaryHeap::from_vec(src); + let heap: BinaryHeap = BinaryHeap::from(src); let dst = heap.into_sorted_vec(); assert_eq!(dst.len(), 13); assert_eq!(dst.capacity(), 16);