aboutsummaryrefslogtreecommitdiff
path: root/lib/std/sort.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2020-02-03 16:53:00 -0500
committerGitHub <noreply@github.com>2020-02-03 16:53:00 -0500
commit0fdcd5c4cb335fcb2d637b891e60094b7a34e2b5 (patch)
tree14a21f75dad026c7800bb9850e1618241f15b0b0 /lib/std/sort.zig
parent1658becb6221f9ffdbfd653c5e295501ac338794 (diff)
parentdb3aea3a0bfce6af04d941003c6a63e86cfdee1a (diff)
downloadzig-0fdcd5c4cb335fcb2d637b891e60094b7a34e2b5.tar.gz
zig-0fdcd5c4cb335fcb2d637b891e60094b7a34e2b5.zip
Merge pull request #4337 from LemonBoy/stdlib-bsearch
stdlib: Add binary search function
Diffstat (limited to 'lib/std/sort.zig')
-rw-r--r--lib/std/sort.zig60
1 files changed, 60 insertions, 0 deletions
diff --git a/lib/std/sort.zig b/lib/std/sort.zig
index 98bac0678d..df9702b325 100644
--- a/lib/std/sort.zig
+++ b/lib/std/sort.zig
@@ -5,6 +5,66 @@ const mem = std.mem;
const math = std.math;
const builtin = @import("builtin");
+pub fn binarySearch(comptime T: type, key: T, items: []const T, comptime compareFn: fn (lhs: T, rhs: T) math.Order) ?usize {
+ if (items.len < 1)
+ return null;
+
+ var left: usize = 0;
+ var right: usize = items.len - 1;
+
+ while (left <= right) {
+ // Avoid overflowing in the midpoint calculation
+ const mid = left + (right - left) / 2;
+ // Compare the key with the midpoint element
+ switch (compareFn(key, items[mid])) {
+ .eq => return mid,
+ .gt => left = mid + 1,
+ .lt => right = mid - 1,
+ }
+ }
+
+ return null;
+}
+
+test "std.sort.binarySearch" {
+ const S = struct {
+ fn order_u32(lhs: u32, rhs: u32) math.Order {
+ return math.order(lhs, rhs);
+ }
+ fn order_i32(lhs: i32, rhs: i32) math.Order {
+ return math.order(lhs, rhs);
+ }
+ };
+ testing.expectEqual(
+ @as(?usize, null),
+ binarySearch(u32, 1, &[_]u32{}, S.order_u32),
+ );
+ testing.expectEqual(
+ @as(?usize, 0),
+ binarySearch(u32, 1, &[_]u32{1}, S.order_u32),
+ );
+ testing.expectEqual(
+ @as(?usize, null),
+ binarySearch(u32, 1, &[_]u32{0}, S.order_u32),
+ );
+ testing.expectEqual(
+ @as(?usize, 4),
+ binarySearch(u32, 5, &[_]u32{ 1, 2, 3, 4, 5 }, S.order_u32),
+ );
+ testing.expectEqual(
+ @as(?usize, 0),
+ binarySearch(u32, 2, &[_]u32{ 2, 4, 8, 16, 32, 64 }, S.order_u32),
+ );
+ testing.expectEqual(
+ @as(?usize, 1),
+ binarySearch(i32, -4, &[_]i32{ -7, -4, 0, 9, 10 }, S.order_i32),
+ );
+ testing.expectEqual(
+ @as(?usize, 3),
+ binarySearch(i32, 98, &[_]i32{ -100, -25, 2, 98, 99, 100 }, S.order_i32),
+ );
+}
+
/// Stable in-place sort. O(n) best case, O(pow(n, 2)) worst case. O(1) memory (no allocator required).
pub fn insertionSort(comptime T: type, items: []T, lessThan: fn (lhs: T, rhs: T) bool) void {
var i: usize = 1;