|
3 | 3 | //! Insertion and popping the largest element have *O*(log n) time complexity. |
4 | 4 | //! Checking the smallest/largest element is *O*(1). |
5 | 5 |
|
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 | | - |
11 | 6 | use core::{ |
12 | 7 | cmp::Ordering, |
13 | 8 | fmt, |
@@ -185,13 +180,74 @@ impl<T, K, const N: usize> BinaryHeap<T, K, N> { |
185 | 180 | data: Vec::new(), |
186 | 181 | } |
187 | 182 | } |
| 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 | + } |
188 | 214 | } |
189 | 215 |
|
190 | 216 | impl<T, K, const N: usize> BinaryHeap<T, K, N> { |
191 | 217 | /// Returns the underlying `Vec<T,N>`. Order is arbitrary and time is *O*(1). |
192 | 218 | pub fn into_vec(self) -> Vec<T, N, usize> { |
193 | 219 | self.data |
194 | 220 | } |
| 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 | + } |
195 | 251 | } |
196 | 252 |
|
197 | 253 | impl<T, K, S: VecStorage<T>> BinaryHeapInner<T, K, S> { |
@@ -419,7 +475,7 @@ where |
419 | 475 |
|
420 | 476 | if !self.is_empty() { |
421 | 477 | 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()); |
423 | 479 | } |
424 | 480 | item |
425 | 481 | } |
@@ -471,8 +527,7 @@ where |
471 | 527 | } |
472 | 528 |
|
473 | 529 | /* 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) { |
476 | 531 | let start = pos; |
477 | 532 | unsafe { |
478 | 533 | let mut hole = Hole::new(self.data.as_mut_slice(), pos); |
@@ -607,7 +662,7 @@ where |
607 | 662 | { |
608 | 663 | fn drop(&mut self) { |
609 | 664 | if self.sift { |
610 | | - self.heap.sift_down_to_bottom(0); |
| 665 | + self.heap.sift_down_to_bottom(0, self.heap.len()); |
611 | 666 | } |
612 | 667 | } |
613 | 668 | } |
@@ -916,4 +971,28 @@ mod tests { |
916 | 971 | ) -> &'c BinaryHeapView<&'b (), Max> { |
917 | 972 | x |
918 | 973 | } |
| 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 | + } |
919 | 998 | } |
0 commit comments