aboutsummaryrefslogtreecommitdiff
path: root/lib/std/priority_queue.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2020-10-16 21:26:04 -0400
committerGitHub <noreply@github.com>2020-10-16 21:26:04 -0400
commit8a2d12d7075fe5eb68e12ccb2b662981b71ae677 (patch)
tree470a6a6f41677ac3302665b5aa9610b40eb8ae7c /lib/std/priority_queue.zig
parentd44486b274a916823fcf6045a6400ef51e07d544 (diff)
parent84406d98e4fd8032b544eba7b5f9d3ed78e67e6c (diff)
downloadzig-8a2d12d7075fe5eb68e12ccb2b662981b71ae677.tar.gz
zig-8a2d12d7075fe5eb68e12ccb2b662981b71ae677.zip
Merge pull request #6393 from onebsv1/priority-queue-update
Adding a function to update the priority of an element
Diffstat (limited to 'lib/std/priority_queue.zig')
-rw-r--r--lib/std/priority_queue.zig82
1 files changed, 80 insertions, 2 deletions
diff --git a/lib/std/priority_queue.zig b/lib/std/priority_queue.zig
index b9be9b70bf..f5ff4800e8 100644
--- 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