| ... | @@ -51,18 +51,16 @@ pub fn PriorityQueue(comptime T: type, comptime Context: type, comptime compareF | ... | @@ -51,18 +51,16 @@ pub fn PriorityQueue(comptime T: type, comptime Context: type, comptime compareF |
| 51 | } | 51 | } |
| 52 | | 52 | |
| 53 | fn siftUp(self: *Self, start_index: usize) void { | 53 | fn siftUp(self: *Self, start_index: usize) void { |
| | 54 | const child = self.items[start_index]; |
| 54 | var child_index = start_index; | 55 | var child_index = start_index; |
| 55 | while (child_index > 0) { | 56 | while (child_index > 0) { |
| 56 | var parent_index = ((child_index - 1) >> 1); | 57 | const parent_index = ((child_index - 1) >> 1); |
| 57 | const child = self.items[child_index]; | | |
| 58 | const parent = self.items[parent_index]; | 58 | const parent = self.items[parent_index]; |
| 59 | | | |
| 60 | if (compareFn(self.context, child, parent) != .lt) break; | 59 | if (compareFn(self.context, child, parent) != .lt) break; |
| 61 | | | |
| 62 | self.items[parent_index] = child; | | |
| 63 | self.items[child_index] = parent; | 60 | self.items[child_index] = parent; |
| 64 | child_index = parent_index; | 61 | child_index = parent_index; |
| 65 | } | 62 | } |
| | 63 | self.items[child_index] = child; |
| 66 | } | 64 | } |
| 67 | | 65 | |
| 68 | /// Add each element in `items` to the queue. | 66 | /// Add each element in `items` to the queue. |
| ... | @@ -128,61 +126,43 @@ pub fn PriorityQueue(comptime T: type, comptime Context: type, comptime compareF | ... | @@ -128,61 +126,43 @@ pub fn PriorityQueue(comptime T: type, comptime Context: type, comptime compareF |
| 128 | return self.items.len; | 126 | return self.items.len; |
| 129 | } | 127 | } |
| 130 | | 128 | |
| 131 | fn siftDown(self: *Self, start_index: usize) void { | 129 | fn siftDown(self: *Self, target_index: usize) void { |
| 132 | var index = start_index; | 130 | const target_element = self.items[target_index]; |
| 133 | const half = self.len >> 1; | 131 | var index = target_index; |
| 134 | while (true) { | 132 | while (true) { |
| 135 | var left_index = (index << 1) + 1; | 133 | var lesser_child_i = (std.math.mul(usize, index, 2) catch break) | 1; |
| 136 | var right_index = left_index + 1; | 134 | if (!(lesser_child_i < self.len)) break; |
| 137 | var left = if (left_index < self.len) self.items[left_index] else null; | | |
| 138 | var right = if (right_index < self.len) self.items[right_index] else null; | | |
| 139 | | | |
| 140 | var smallest_index = index; | | |
| 141 | var smallest = self.items[index]; | | |
| 142 | | | |
| 143 | if (left) |e| { | | |
| 144 | if (compareFn(self.context, e, smallest) == .lt) { | | |
| 145 | smallest_index = left_index; | | |
| 146 | smallest = e; | | |
| 147 | } | | |
| 148 | } | | |
| 149 | | 135 | |
| 150 | if (right) |e| { | 136 | const next_child_i = lesser_child_i + 1; |
| 151 | if (compareFn(self.context, e, smallest) == .lt) { | 137 | if (next_child_i < self.len and compareFn(self.context, self.items[next_child_i], self.items[lesser_child_i]) == .lt) { |
| 152 | smallest_index = right_index; | 138 | lesser_child_i = next_child_i; |
| 153 | smallest = e; | | |
| 154 | } | | |
| 155 | } | 139 | } |
| 156 | | 140 | |
| 157 | if (smallest_index == index) return; | 141 | if (compareFn(self.context, target_element, self.items[lesser_child_i]) == .lt) break; |
| 158 | | 142 | |
| 159 | self.items[smallest_index] = self.items[index]; | 143 | self.items[index] = self.items[lesser_child_i]; |
| 160 | self.items[index] = smallest; | 144 | index = lesser_child_i; |
| 161 | index = smallest_index; | | |
| 162 | | | |
| 163 | if (index >= half) return; | | |
| 164 | } | 145 | } |
| | 146 | self.items[index] = target_element; |
| 165 | } | 147 | } |
| 166 | | 148 | |
| 167 | /// PriorityQueue takes ownership of the passed in slice. The slice must have been | 149 | /// PriorityQueue takes ownership of the passed in slice. The slice must have been |
| 168 | /// allocated with `allocator`. | 150 | /// allocated with `allocator`. |
| 169 | /// Deinitialize with `deinit`. | 151 | /// Deinitialize with `deinit`. |
| 170 | pub fn fromOwnedSlice(allocator: Allocator, items: []T, context: Context) Self { | 152 | pub fn fromOwnedSlice(allocator: Allocator, items: []T, context: Context) Self { |
| 171 | var queue = Self{ | 153 | var self = Self{ |
| 172 | .items = items, | 154 | .items = items, |
| 173 | .len = items.len, | 155 | .len = items.len, |
| 174 | .allocator = allocator, | 156 | .allocator = allocator, |
| 175 | .context = context, | 157 | .context = context, |
| 176 | }; | 158 | }; |
| 177 | | 159 | |
| 178 | if (queue.len <= 1) return queue; | 160 | var i = self.len >> 1; |
| 179 | | 161 | while (i > 0) { |
| 180 | const half = (queue.len >> 1) - 1; | 162 | i -= 1; |
| 181 | var i: usize = 0; | 163 | self.siftDown(i); |
| 182 | while (i <= half) : (i += 1) { | | |
| 183 | queue.siftDown(half - i); | | |
| 184 | } | 164 | } |
| 185 | return queue; | 165 | return self; |
| 186 | } | 166 | } |
| 187 | | 167 | |
| 188 | /// Ensure that the queue can fit at least `new_capacity` items. | 168 | /// Ensure that the queue can fit at least `new_capacity` items. |