| ... | @@ -5,6 +5,67 @@ const mem = std.mem; | ... | @@ -5,6 +5,67 @@ const mem = std.mem; |
| 5 | const math = std.math; | 5 | const math = std.math; |
| 6 | const builtin = @import("builtin"); | 6 | const builtin = @import("builtin"); |
| 7 | | 7 | |
| | 8 | pub fn binarySearch(comptime T: type, items: []T, comptime compareFn: fn (val: T) math.Order) ?usize { |
| | 9 | if (items.len < 1) |
| | 10 | return null; |
| | 11 | |
| | 12 | var left: usize = 0; |
| | 13 | var right: usize = items.len - 1; |
| | 14 | |
| | 15 | while (left <= right) { |
| | 16 | // Avoid overflowing in the midpoint calculation |
| | 17 | const mid = left + (right - left) / 2; |
| | 18 | // Compare the midpoint element with the key |
| | 19 | switch (compareFn(items[mid])) { |
| | 20 | .eq => return mid, |
| | 21 | .lt => left = mid + 1, |
| | 22 | .gt => right = mid - 1, |
| | 23 | } |
| | 24 | } |
| | 25 | |
| | 26 | return null; |
| | 27 | } |
| | 28 | |
| | 29 | test "std.sort.binarySearch" { |
| | 30 | const S = struct { |
| | 31 | fn makeComparisonPred(comptime T: type, value: T) type { |
| | 32 | return struct { |
| | 33 | fn pred(v: T) math.Order { |
| | 34 | return math.order(v, value); |
| | 35 | } |
| | 36 | }; |
| | 37 | } |
| | 38 | }; |
| | 39 | testing.expectEqual( |
| | 40 | @as(?usize, null), |
| | 41 | binarySearch(u32, &[_]u32{}, S.makeComparisonPred(u32, 1).pred), |
| | 42 | ); |
| | 43 | testing.expectEqual( |
| | 44 | @as(?usize, 0), |
| | 45 | binarySearch(u32, &[_]u32{1}, S.makeComparisonPred(u32, 1).pred), |
| | 46 | ); |
| | 47 | testing.expectEqual( |
| | 48 | @as(?usize, null), |
| | 49 | binarySearch(u32, &[_]u32{0}, S.makeComparisonPred(u32, 1).pred), |
| | 50 | ); |
| | 51 | testing.expectEqual( |
| | 52 | @as(?usize, 4), |
| | 53 | binarySearch(u32, &[_]u32{ 1, 2, 3, 4, 5 }, S.makeComparisonPred(u32, 5).pred), |
| | 54 | ); |
| | 55 | testing.expectEqual( |
| | 56 | @as(?usize, 0), |
| | 57 | binarySearch(u32, &[_]u32{ 2, 4, 8, 16, 32, 64 }, S.makeComparisonPred(u32, 2).pred), |
| | 58 | ); |
| | 59 | testing.expectEqual( |
| | 60 | @as(?usize, 1), |
| | 61 | binarySearch(i32, &[_]i32{ -7, -4, 0, 9, 10 }, S.makeComparisonPred(i32, -4).pred), |
| | 62 | ); |
| | 63 | testing.expectEqual( |
| | 64 | @as(?usize, 3), |
| | 65 | binarySearch(i32, &[_]i32{ -100, -25, 2, 98, 99, 100 }, S.makeComparisonPred(i32, 98).pred), |
| | 66 | ); |
| | 67 | } |
| | 68 | |
| 8 | /// Stable in-place sort. O(n) best case, O(pow(n, 2)) worst case. O(1) memory (no allocator required). | 69 | /// Stable in-place sort. O(n) best case, O(pow(n, 2)) worst case. O(1) memory (no allocator required). |
| 9 | pub fn insertionSort(comptime T: type, items: []T, lessThan: fn (lhs: T, rhs: T) bool) void { | 70 | pub fn insertionSort(comptime T: type, items: []T, lessThan: fn (lhs: T, rhs: T) bool) void { |
| 10 | var i: usize = 1; | 71 | var i: usize = 1; |