|
| 1 | +///| |
| 2 | +pub struct Heap[T] { |
| 3 | + items : Array[T] |
| 4 | + comparator : (T, T) -> Bool |
| 5 | +} |
| 6 | + |
| 7 | +///| |
| 8 | +/// Creates a new, empty heap with a custom comparator function. |
| 9 | +/// |
| 10 | +/// # Parameters |
| 11 | +/// - `comparator`: A function that defines the heap's ordering. |
| 12 | +/// |
| 13 | +/// # Returns |
| 14 | +/// A new `Heap` instance. |
| 15 | +pub fn[T] Heap::new(comparator : (T, T) -> Bool) -> Heap[T] { |
| 16 | + Heap::{ items: Array::new(), comparator } |
| 17 | +} |
| 18 | + |
| 19 | +///| |
| 20 | +/// Creates a heap from a vector and a custom comparator function. |
| 21 | +/// |
| 22 | +/// # Parameters |
| 23 | +/// - `items`: A vector of items to be turned into a heap. |
| 24 | +/// - `comparator`: A function that defines the heap's ordering. |
| 25 | +/// |
| 26 | +/// # Returns |
| 27 | +/// A `Heap` instance with the elements from the provided vector. |
| 28 | +pub fn[T] Heap::from_vec( |
| 29 | + items : Array[T], |
| 30 | + comparator : (T, T) -> Bool, |
| 31 | +) -> Heap[T] { |
| 32 | + let heap = Heap::{ items, comparator } |
| 33 | + heap.build_heap() |
| 34 | + heap |
| 35 | +} |
| 36 | + |
| 37 | +///| |
| 38 | +/// Constructs the heap from an unsorted vector by applying the heapify process. |
| 39 | +pub fn[T] Heap::build_heap(self : Heap[T]) -> Unit { |
| 40 | + let n = self.items.length() |
| 41 | + if n < 2 { |
| 42 | + return |
| 43 | + } |
| 44 | + let mut idx = n / 2 - 1 |
| 45 | + while true { |
| 46 | + self.heapify_down(idx) |
| 47 | + if idx == 0 { |
| 48 | + break |
| 49 | + } |
| 50 | + idx -= 1 |
| 51 | + } |
| 52 | +} |
| 53 | + |
| 54 | +///| |
| 55 | +/// Returns the number of elements in the heap. |
| 56 | +/// |
| 57 | +/// # Returns |
| 58 | +/// The number of elements in the heap. |
| 59 | +pub fn[T] Heap::len(self : Heap[T]) -> Int { |
| 60 | + self.items.length() |
| 61 | +} |
| 62 | + |
| 63 | +///| |
| 64 | +/// Checks if the heap is empty. |
| 65 | +/// |
| 66 | +/// # Returns |
| 67 | +/// `true` if the heap is empty, `false` otherwise. |
| 68 | +pub fn[T] Heap::is_empty(self : Heap[T]) -> Bool { |
| 69 | + self.len() == 0 |
| 70 | +} |
| 71 | + |
| 72 | +///| |
| 73 | +/// Adds a new element to the heap and maintains the heap property. |
| 74 | +/// |
| 75 | +/// # Parameters |
| 76 | +/// - `value`: The value to add to the heap. |
| 77 | +pub fn[T] Heap::add(self : Heap[T], value : T) -> Unit { |
| 78 | + self.items.push(value) |
| 79 | + self.heapify_up(self.len() - 1) |
| 80 | +} |
| 81 | + |
| 82 | +///| |
| 83 | +/// Removes and returns the root element from the heap. |
| 84 | +/// |
| 85 | +/// # Returns |
| 86 | +/// The root element if the heap is not empty, otherwise `None`. |
| 87 | +pub fn[T] Heap::pop(self : Heap[T]) -> T? { |
| 88 | + if self.is_empty() { |
| 89 | + return None |
| 90 | + } |
| 91 | + let next = if self.items.length() > 0 { |
| 92 | + let val = self.items[0] |
| 93 | + let last = self.items.pop().unwrap() |
| 94 | + if self.items.length() > 0 { |
| 95 | + self.items[0] = last |
| 96 | + } |
| 97 | + Some(val) |
| 98 | + } else { |
| 99 | + None |
| 100 | + } |
| 101 | + if !self.is_empty() { |
| 102 | + self.heapify_down(0) |
| 103 | + } |
| 104 | + next |
| 105 | +} |
| 106 | + |
| 107 | +///| |
| 108 | +/// Returns an iterator over the elements in the heap. |
| 109 | +/// |
| 110 | +/// # Returns |
| 111 | +/// An iterator over the elements in the heap, in their internal order. |
| 112 | +pub fn[T] Heap::iter(self : Heap[T]) -> Iter[T] { |
| 113 | + self.items.iter() |
| 114 | +} |
| 115 | + |
| 116 | +///| |
| 117 | +/// Moves an element upwards to restore the heap property. |
| 118 | +/// |
| 119 | +/// # Parameters |
| 120 | +/// - `idx`: The index of the element to heapify up. |
| 121 | +fn[T] Heap::heapify_up(self : Heap[T], idx : Int) -> Unit { |
| 122 | + let mut idx0 = idx |
| 123 | + while self.parent_idx(idx0) is Some(pdx) { // while-let 等价写法 |
| 124 | + if (self.comparator)(self.items[idx0], self.items[pdx]) { |
| 125 | + let tmp = self.items[idx0] |
| 126 | + self.items[idx0] = self.items[pdx] |
| 127 | + self.items[pdx] = tmp |
| 128 | + idx0 = pdx |
| 129 | + } else { |
| 130 | + break |
| 131 | + } |
| 132 | + } |
| 133 | +} |
| 134 | + |
| 135 | +///| |
| 136 | +/// Moves an element downwards to restore the heap property. |
| 137 | +/// |
| 138 | +/// # Parameters |
| 139 | +/// - `idx`: The index of the element to heapify down. |
| 140 | +fn[T] Heap::heapify_down(self : Heap[T], idx : Int) -> Unit { |
| 141 | + let mut idx0 = idx |
| 142 | + while self.children_present(idx0) { |
| 143 | + let cdx = if self.right_child_idx(idx0) >= self.len() { |
| 144 | + self.left_child_idx(idx0) |
| 145 | + } else { |
| 146 | + let ldx = self.left_child_idx(idx0) |
| 147 | + let rdx = self.right_child_idx(idx0) |
| 148 | + if (self.comparator)(self.items[ldx], self.items[rdx]) { |
| 149 | + ldx |
| 150 | + } else { |
| 151 | + rdx |
| 152 | + } |
| 153 | + } |
| 154 | + if (self.comparator)(self.items[cdx], self.items[idx0]) { |
| 155 | + self.items.swap(idx0, cdx) |
| 156 | + idx0 = cdx |
| 157 | + } else { |
| 158 | + break |
| 159 | + } |
| 160 | + } |
| 161 | +} |
| 162 | + |
| 163 | +///| |
| 164 | +/// Returns the index of the parent of the element at `idx`. |
| 165 | +/// |
| 166 | +/// # Parameters |
| 167 | +/// - `idx`: The index of the element. |
| 168 | +/// |
| 169 | +/// # Returns |
| 170 | +/// The index of the parent element if it exists, otherwise `None`. |
| 171 | +fn[T] Heap::parent_idx(self : Heap[T], idx : Int) -> Int? { |
| 172 | + if idx > 0 { |
| 173 | + Some((idx - 1) / 2) |
| 174 | + } else { |
| 175 | + None |
| 176 | + } |
| 177 | +} |
| 178 | + |
| 179 | +///| |
| 180 | +/// Checks if the element at `idx` has children. |
| 181 | +/// |
| 182 | +/// # Parameters |
| 183 | +/// - `idx`: The index of the element. |
| 184 | +/// |
| 185 | +/// # Returns |
| 186 | +/// `true` if the element has children, `false` otherwise. |
| 187 | +fn[T] Heap::children_present(self : Heap[T], idx : Int) -> Bool { |
| 188 | + self.left_child_idx(idx) < self.len() |
| 189 | +} |
| 190 | + |
| 191 | +///| |
| 192 | +/// Returns the index of the left child of the element at `idx`. |
| 193 | +/// |
| 194 | +/// # Parameters |
| 195 | +/// - `idx`: The index of the element. |
| 196 | +/// |
| 197 | +/// # Returns |
| 198 | +/// The index of the left child. |
| 199 | +fn[T] Heap::left_child_idx(self : Heap[T], idx : Int) -> Int { |
| 200 | + idx * 2 + 1 |
| 201 | +} |
| 202 | + |
| 203 | +///| |
| 204 | +/// Returns the index of the right child of the element at `idx`. |
| 205 | +/// |
| 206 | +/// # Parameters |
| 207 | +/// - `idx`: The index of the element. |
| 208 | +/// |
| 209 | +/// # Returns |
| 210 | +/// The index of the right child. |
| 211 | +fn[T] Heap::right_child_idx(self : Heap[T], idx : Int) -> Int { |
| 212 | + self.left_child_idx(idx) + 1 |
| 213 | +} |
0 commit comments