commit 8a2d12d7075fe5eb68e12ccb2b662981b71ae677 (tree)
parent d44486b274a916823fcf6045a6400ef51e07d544
Author: Andrew Kelley <andrew@ziglang.org>
Date: Fri, 16 Oct 2020 21:26:04 -0400
Merge pull request #6393 from onebsv1/priority-queue-update
Adding a function to update the priority of an element
Diffstat:
1 file changed, 81 insertions(+), 2 deletions(-)
diff --git a/lib/std/priority_queue.zig b/lib/std/priority_queue.zig
@@ -49,7 +49,12 @@ pub fn PriorityQueue(comptime T: type) type {
fn addUnchecked(self: *Self, elem: T) void {
self.items[self.len] = elem;
- var child_index = self.len;
+ siftUp(self, self.len);
+ self.len += 1;
+ }
+
+ fn siftUp(self: *Self, start_index: usize) void {
+ var child_index = start_index;
while (child_index > 0) {
var parent_index = ((child_index - 1) >> 1);
const child = self.items[child_index];
@@ -61,7 +66,6 @@ pub fn PriorityQueue(comptime T: type) type {
self.items[child_index] = parent;
child_index = parent_index;
}
- self.len += 1;
}
/// Add each element in `items` to the queue.
@@ -190,6 +194,17 @@ pub fn PriorityQueue(comptime T: type) type {
self.len = new_len;
}
+ pub fn update(self: *Self, elem: T, new_elem: T) !void {
+ var update_index: usize = std.mem.indexOfScalar(T, self.items, elem) orelse return error.ElementNotFound;
+ const old_elem: T = self.items[update_index];
+ self.items[update_index] = new_elem;
+ if (self.compareFn(new_elem, old_elem)) {
+ siftUp(self, update_index);
+ } else {
+ siftDown(self, update_index);
+ }
+ }
+
pub const Iterator = struct {
queue: *PriorityQueue(T),
count: usize,
@@ -437,3 +452,66 @@ test "std.PriorityQueue: iterator while empty" {
expectEqual(it.next(), null);
}
+
+test "std.PriorityQueue: update min heap" {
+ var queue = PQ.init(testing.allocator, lessThan);
+ defer queue.deinit();
+
+ try queue.add(55);
+ try queue.add(44);
+ try queue.add(11);
+ try queue.update(55, 5);
+ try queue.update(44, 4);
+ try queue.update(11, 1);
+ expectEqual(@as(u32, 1), queue.remove());
+ expectEqual(@as(u32, 4), queue.remove());
+ expectEqual(@as(u32, 5), queue.remove());
+}
+
+
+test "std.PriorityQueue: update same min heap" {
+ var queue = PQ.init(testing.allocator, lessThan);
+ defer queue.deinit();
+
+ try queue.add(1);
+ try queue.add(1);
+ try queue.add(2);
+ try queue.add(2);
+ try queue.update(1, 5);
+ try queue.update(2, 4);
+ expectEqual(@as(u32, 1), queue.remove());
+ expectEqual(@as(u32, 2), queue.remove());
+ expectEqual(@as(u32, 4), queue.remove());
+ expectEqual(@as(u32, 5), queue.remove());
+}
+
+test "std.PriorityQueue: update max heap" {
+ var queue = PQ.init(testing.allocator, greaterThan);
+ defer queue.deinit();
+
+ try queue.add(55);
+ try queue.add(44);
+ try queue.add(11);
+ try queue.update(55, 5);
+ try queue.update(44, 1);
+ try queue.update(11, 4);
+ expectEqual(@as(u32, 5), queue.remove());
+ expectEqual(@as(u32, 4), queue.remove());
+ expectEqual(@as(u32, 1), queue.remove());
+}
+
+test "std.PriorityQueue: update same max heap" {
+ var queue = PQ.init(testing.allocator, greaterThan);
+ defer queue.deinit();
+
+ try queue.add(1);
+ try queue.add(1);
+ try queue.add(2);
+ try queue.add(2);
+ try queue.update(1, 5);
+ try queue.update(2, 4);
+ expectEqual(@as(u32, 5), queue.remove());
+ expectEqual(@as(u32, 4), queue.remove());
+ expectEqual(@as(u32, 2), queue.remove());
+ expectEqual(@as(u32, 1), queue.remove());
+}
+\ No newline at end of file