Implement hash table lookup logic
continuous-integration/drone/push Build is failing Details
continuous-integration/drone/pr Build is failing Details

This commit is contained in:
kayomn 2022-10-14 17:10:27 +01:00
parent 4e5883f384
commit 53a369952e
1 changed files with 49 additions and 17 deletions

View File

@ -2,23 +2,20 @@ const std = @import("std");
pub fn Dynamic(comptime Key: type, comptime Value: type, comptime key_context: KeyContext(Key)) type { pub fn Dynamic(comptime Key: type, comptime Value: type, comptime key_context: KeyContext(Key)) type {
return struct { return struct {
load_maximum: f32,
buckets_used: usize, buckets_used: usize,
bucket_map: []?Bucket, buckets: []Bucket,
/// ///
/// ///
/// ///
const Bucket = struct { const Bucket = struct {
key: Key, maybe_entry: ?struct {
value: Value, key: Key,
next: ?usize, value: Value,
}; },
///
///
///
pub const InsertError = error {
maybe_next_index: ?usize,
}; };
/// ///
@ -29,8 +26,7 @@ pub fn Dynamic(comptime Key: type, comptime Value: type, comptime key_context: K
/// ///
/// ///
/// ///
pub fn insert(self: Self, key: Key, value: Value) InsertError!void { pub fn delete(self: Self, key: Key) bool {
_ = value;
_ = key; _ = key;
_ = self; _ = self;
} }
@ -38,14 +34,43 @@ pub fn Dynamic(comptime Key: type, comptime Value: type, comptime key_context: K
/// ///
/// ///
/// ///
pub fn insert(self: Self, key: Key, value: Value) InsertError!void {
if ((@intToFloat(f32, self.buckets_used) / @intToFloat(
f32, self.buckets.len)) >= self.load_maximum) try self.rehash();
var hash = @mod(key_context.hash(key), self.buckets.len);
while (true) {
const bucket = &(self.buckets[hash]);
const entry = &(bucket.maybe_entry orelse {
bucket.maybe_entry = .{
.key = key,
.value = value
};
});
if (key_context.equals(entry.key, key)) return error.KeyExists;
hash = @mod(hashHash(hash), self.buckets.len);
}
}
///
/// Searches for a value indexed with `key` in `self`, returning it or `null` if no matching
/// entry was found.
///
pub fn lookup(self: Self, key: Key) ?*Value { pub fn lookup(self: Self, key: Key) ?*Value {
var bucket = &(self.bucket_map[@mod(key_context.hash( var bucket = &(self.buckets[@mod(key_context.hash(key), self.buckets.len)]);
key), self.bucket_map.len)] orelse return null);
while (bucket) { if (bucket.maybe_entry) |*entry|
if (key_context.equals(bucket.key, key)) return &bucket.value; if (key_context.equals(entry.key, key)) return &entry.value;
bucket = bucket.next; while (bucket.maybe_next_index) |index| {
bucket = &(self.buckets[index]);
if (bucket.maybe_entry) |*entry|
if (key_context.equals(entry.key, key)) return &entry.value;
} }
return null; return null;
@ -53,6 +78,13 @@ pub fn Dynamic(comptime Key: type, comptime Value: type, comptime key_context: K
}; };
} }
///
///
///
pub const InsertError = std.mem.Allocator || error {
KeyExists,
};
pub fn KeyContext(comptime Key: type) type { pub fn KeyContext(comptime Key: type) type {
return struct { return struct {
hash: fn (Key) usize, hash: fn (Key) usize,