Implement hash table lookup logic
This commit is contained in:
parent
4e5883f384
commit
53a369952e
|
@ -2,23 +2,20 @@ const std = @import("std");
|
|||
|
||||
pub fn Dynamic(comptime Key: type, comptime Value: type, comptime key_context: KeyContext(Key)) type {
|
||||
return struct {
|
||||
load_maximum: f32,
|
||||
buckets_used: usize,
|
||||
bucket_map: []?Bucket,
|
||||
buckets: []Bucket,
|
||||
|
||||
///
|
||||
///
|
||||
///
|
||||
const Bucket = struct {
|
||||
key: Key,
|
||||
value: Value,
|
||||
next: ?usize,
|
||||
};
|
||||
|
||||
///
|
||||
///
|
||||
///
|
||||
pub const InsertError = error {
|
||||
maybe_entry: ?struct {
|
||||
key: Key,
|
||||
value: Value,
|
||||
},
|
||||
|
||||
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 {
|
||||
_ = value;
|
||||
pub fn delete(self: Self, key: Key) bool {
|
||||
_ = key;
|
||||
_ = 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 {
|
||||
var bucket = &(self.bucket_map[@mod(key_context.hash(
|
||||
key), self.bucket_map.len)] orelse return null);
|
||||
var bucket = &(self.buckets[@mod(key_context.hash(key), self.buckets.len)]);
|
||||
|
||||
while (bucket) {
|
||||
if (key_context.equals(bucket.key, key)) return &bucket.value;
|
||||
if (bucket.maybe_entry) |*entry|
|
||||
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;
|
||||
|
@ -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 {
|
||||
return struct {
|
||||
hash: fn (Key) usize,
|
||||
|
|
Loading…
Reference in New Issue