| ... | @@ -4,6 +4,7 @@ const debug = std.debug; | ... | @@ -4,6 +4,7 @@ const debug = std.debug; |
| 4 | const expect = std.testing.expect; | 4 | const expect = std.testing.expect; |
| 5 | const expectEqual = std.testing.expectEqual; | 5 | const expectEqual = std.testing.expectEqual; |
| 6 | | 6 | |
| | 7 | /// Priority queue for storing generic data. Initialize with `init`. |
| 7 | pub fn PriorityQueue(comptime T: type) type { | 8 | pub fn PriorityQueue(comptime T: type) type { |
| 8 | return struct { | 9 | return struct { |
| 9 | const Self = @This(); | 10 | const Self = @This(); |
| ... | @@ -13,6 +14,12 @@ pub fn PriorityQueue(comptime T: type) type { | ... | @@ -13,6 +14,12 @@ pub fn PriorityQueue(comptime T: type) type { |
| 13 | allocator: *Allocator, | 14 | allocator: *Allocator, |
| 14 | compareFn: fn (a: T, b: T) bool, | 15 | compareFn: fn (a: T, b: T) bool, |
| 15 | | 16 | |
| | 17 | /// Initialize and return a priority queue. Provide |
| | 18 | /// `compareFn` that returns `true` when its first argument |
| | 19 | /// should get popped before its second argument. For example, |
| | 20 | /// to make `pop` return the minimum value, provide |
| | 21 | /// |
| | 22 | /// `fn lessThan(a: T, b: T) bool { return a < b; }` |
| 16 | pub fn init(allocator: *Allocator, compareFn: fn (a: T, b: T) bool) Self { | 23 | pub fn init(allocator: *Allocator, compareFn: fn (a: T, b: T) bool) Self { |
| 17 | return Self{ | 24 | return Self{ |
| 18 | .items = [_]T{}, | 25 | .items = [_]T{}, |
| ... | @@ -22,10 +29,12 @@ pub fn PriorityQueue(comptime T: type) type { | ... | @@ -22,10 +29,12 @@ pub fn PriorityQueue(comptime T: type) type { |
| 22 | }; | 29 | }; |
| 23 | } | 30 | } |
| 24 | | 31 | |
| | 32 | /// Free memory used by the queue. |
| 25 | pub fn deinit(self: Self) void { | 33 | pub fn deinit(self: Self) void { |
| 26 | self.allocator.free(self.items); | 34 | self.allocator.free(self.items); |
| 27 | } | 35 | } |
| 28 | | 36 | |
| | 37 | /// Insert a new element, maintaining priority. |
| 29 | pub fn add(self: *Self, elem: T) !void { | 38 | pub fn add(self: *Self, elem: T) !void { |
| 30 | try ensureCapacity(self, self.len + 1); | 39 | try ensureCapacity(self, self.len + 1); |
| 31 | addUnchecked(self, elem); | 40 | addUnchecked(self, elem); |
| ... | @@ -48,6 +57,7 @@ pub fn PriorityQueue(comptime T: type) type { | ... | @@ -48,6 +57,7 @@ pub fn PriorityQueue(comptime T: type) type { |
| 48 | self.len += 1; | 57 | self.len += 1; |
| 49 | } | 58 | } |
| 50 | | 59 | |
| | 60 | /// Add each element in `items` to the queue. |
| 51 | pub fn addSlice(self: *Self, items: []const T) !void { | 61 | pub fn addSlice(self: *Self, items: []const T) !void { |
| 52 | try self.ensureCapacity(self.len + items.len); | 62 | try self.ensureCapacity(self.len + items.len); |
| 53 | for (items) |e| { | 63 | for (items) |e| { |
| ... | @@ -55,10 +65,14 @@ pub fn PriorityQueue(comptime T: type) type { | ... | @@ -55,10 +65,14 @@ pub fn PriorityQueue(comptime T: type) type { |
| 55 | } | 65 | } |
| 56 | } | 66 | } |
| 57 | | 67 | |
| | 68 | /// Look at the highest priority element in the queue. Returns |
| | 69 | /// `null` if empty. |
| 58 | pub fn peek(self: *Self) ?T { | 70 | pub fn peek(self: *Self) ?T { |
| 59 | return if (self.len > 0) self.items[0] else null; | 71 | return if (self.len > 0) self.items[0] else null; |
| 60 | } | 72 | } |
| 61 | | 73 | |
| | 74 | /// Pop the highest priority element from the queue. Returns |
| | 75 | /// `null` if empty. |
| 62 | pub fn removeOrNull(self: *Self) ?T { | 76 | pub fn removeOrNull(self: *Self) ?T { |
| 63 | return if (self.len > 0) self.remove() else null; | 77 | return if (self.len > 0) self.remove() else null; |
| 64 | } | 78 | } |
| ... | @@ -72,10 +86,14 @@ pub fn PriorityQueue(comptime T: type) type { | ... | @@ -72,10 +86,14 @@ pub fn PriorityQueue(comptime T: type) type { |
| 72 | return first; | 86 | return first; |
| 73 | } | 87 | } |
| 74 | | 88 | |
| | 89 | /// Return the number of elements remaining in the priority |
| | 90 | /// queue. |
| 75 | pub fn count(self: Self) usize { | 91 | pub fn count(self: Self) usize { |
| 76 | return self.len; | 92 | return self.len; |
| 77 | } | 93 | } |
| 78 | | 94 | |
| | 95 | /// Return the number of elements that can be added to the |
| | 96 | /// queue before more memory is allocated. |
| 79 | pub fn capacity(self: Self) usize { | 97 | pub fn capacity(self: Self) usize { |
| 80 | return self.items.len; | 98 | return self.items.len; |
| 81 | } | 99 | } |
| ... | @@ -171,6 +189,8 @@ pub fn PriorityQueue(comptime T: type) type { | ... | @@ -171,6 +189,8 @@ pub fn PriorityQueue(comptime T: type) type { |
| 171 | } | 189 | } |
| 172 | }; | 190 | }; |
| 173 | | 191 | |
| | 192 | /// Return an iterator that walks the queue without consuming |
| | 193 | /// it. Invalidated if the heap is modified. |
| 174 | pub fn iterator(self: *Self) Iterator { | 194 | pub fn iterator(self: *Self) Iterator { |
| 175 | return Iterator{ | 195 | return Iterator{ |
| 176 | .queue = self, | 196 | .queue = self, |