|
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, |
@@ -177,13 +172,74 @@ impl<T, K, const N: usize> BinaryHeap<T, K, N> { |
177 | 172 | data: Vec::new(), |
178 | 173 | } |
179 | 174 | } |
| 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 | + } |
180 | 206 | } |
181 | 207 |
|
182 | 208 | impl<T, K, const N: usize> BinaryHeap<T, K, N> { |
183 | 209 | /// Returns the underlying `Vec<T,N>`. Order is arbitrary and time is *O*(1). |
184 | 210 | pub fn into_vec(self) -> Vec<T, N, usize> { |
185 | 211 | self.data |
186 | 212 | } |
| 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 | + } |
187 | 243 | } |
188 | 244 |
|
189 | 245 | impl<T, K, S: VecStorage<T>> BinaryHeapInner<T, K, S> { |
@@ -411,7 +467,7 @@ where |
411 | 467 |
|
412 | 468 | if !self.is_empty() { |
413 | 469 | 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()); |
415 | 471 | } |
416 | 472 | item |
417 | 473 | } |
@@ -463,8 +519,7 @@ where |
463 | 519 | } |
464 | 520 |
|
465 | 521 | /* 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) { |
468 | 523 | let start = pos; |
469 | 524 | unsafe { |
470 | 525 | let mut hole = Hole::new(self.data.as_mut_slice(), pos); |
@@ -599,7 +654,7 @@ where |
599 | 654 | { |
600 | 655 | fn drop(&mut self) { |
601 | 656 | if self.sift { |
602 | | - self.heap.sift_down_to_bottom(0); |
| 657 | + self.heap.sift_down_to_bottom(0, self.heap.len()); |
603 | 658 | } |
604 | 659 | } |
605 | 660 | } |
@@ -890,4 +945,28 @@ mod tests { |
890 | 945 | ) -> &'c BinaryHeapView<&'b (), Max> { |
891 | 946 | x |
892 | 947 | } |
| 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 | + } |
893 | 972 | } |
0 commit comments