insert with lookup

3rd lvl is broken
This commit is contained in:
Janis 2023-03-17 20:08:51 +01:00
parent 29ebb53e8c
commit 94f42f24c5

View file

@ -22,7 +22,15 @@ const BTree = struct {
self.dbg(); self.dbg();
if (self.root) |*root| { if (self.root) |*root| {
const result = try root.as_leaf().insert_value(value); const search = root.find_key(value);
switch (search) {
.Leaf => |node| {
std.debug.print("key already present: {}", .{node});
return error.Occupied;
},
.Edge => |edge| {
const result = try edge.leaf.insert_value(value);
if (result) |split| { if (result) |split| {
// create new node which will replace self. // create new node which will replace self.
const parent = try Node.create(self.ally); const parent = try Node.create(self.ally);
@ -33,6 +41,8 @@ const BTree = struct {
self.root = .{ .internal = parent }; self.root = .{ .internal = parent };
} }
},
}
} else { } else {
var leaf: *Leaf = try self.ally.create(Leaf); var leaf: *Leaf = try self.ally.create(Leaf);
errdefer self.ally.destroy(leaf); errdefer self.ally.destroy(leaf);
@ -94,6 +104,32 @@ const BTree = struct {
} }
} }
fn find_key(self: NodeOrLeaf, key: u32) Leaf.SearchResult {
var leaf = self.as_leaf();
while (true) {
const search = leaf.find_key(key);
switch (search) {
.Leaf => {
return search;
},
.Edge => |edge| {
const node = NodeOrLeaf.from_leaf(edge.leaf);
switch (node) {
.internal => |internal| {
if (internal.get_edges()[edge.idx]) |child| {
leaf = child.as_leaf();
continue;
}
},
.leaf => {},
}
return search;
},
}
}
}
fn dbg(self: NodeOrLeaf) void { fn dbg(self: NodeOrLeaf) void {
switch (self) { switch (self) {
.internal => |node| { .internal => |node| {
@ -237,11 +273,12 @@ const BTree = struct {
} }
const SplitResult = struct { const SplitResult = struct {
// attached // attached, old node that may be modified
left: *Leaf, left: *Leaf,
// lose value, previously attacked, must be inserted // lose value, previously attacked, must be inserted
// if we go all the way to the top, the root node must have some value and this is it
middle: u32, middle: u32,
// free floating leaf, must be attached // new, free floating leaf, must be attached
right: *Leaf, right: *Leaf,
}; };
@ -254,36 +291,51 @@ const BTree = struct {
} }
} }
std.debug.assert(idx > 0 and idx < CAPACITY - 1); std.debug.assert(self.len == CAPACITY);
//std.debug.assert(idx > 0 and idx < CAPACITY - 1);
var new = try Leaf.create(self.ally); var new = try Leaf.create(self.ally);
new.level = self.level; new.level = self.level;
var middle: u32 = undefined; var middle: u32 = undefined;
new.len = B - 1;
std.mem.copy(u32, &new.values, self.values[B..]);
middle = self.values[B - 1];
self.len = B - 1;
// take from right half // take from right half
if (idx > B) { if (idx >= B) {
new.len = self.len - (idx + 1);
std.mem.copy(u32, &new.values, self.values[(idx + 1)..self.len]);
middle = self.values[idx];
self.len = idx;
self.push_value(value);
} else {
// take from left half
new.len = self.len - (idx);
std.mem.copy(u32, &new.values, self.values[idx..self.len]);
new.push_value(value); new.push_value(value);
} else {
middle = self.values[idx - 1]; self.push_value(value);
self.len = idx - 1;
} }
return .{ .left = self, .middle = middle, .right = new }; return .{ .left = self, .middle = middle, .right = new };
} }
const SearchResultTag = enum { Edge, Leaf };
const SearchResult = union(SearchResultTag) {
Edge: struct { leaf: *Leaf, idx: u16 },
Leaf: struct { leaf: *Leaf, idx: u16 },
};
fn find_key(self: *Leaf, key: u32) SearchResult {
std.debug.print("looking for {} in {any}\n", .{ key, self.get_values() });
for (self.get_values(), 0..) |v, i| {
if (key < v) {
std.debug.print("decending left of {}\n", .{v});
return .{ .Edge = .{ .leaf = self, .idx = @intCast(u16, i) } };
} else if (key == v) {
std.debug.print("located {} at {}\n", .{ key, v });
return .{ .Leaf = .{ .leaf = self, .idx = @intCast(u16, i) } };
}
}
std.debug.print("decending right of {}\n", .{self.get_values()[self.len - 1]});
return .{ .Edge = .{ .leaf = self, .idx = self.len } };
}
// returns null on success, or a split result which could not be merged // returns null on success, or a split result which could not be merged
// up because we are at the root node // up because we are at the root node
fn insert_value(self: *Leaf, value: u32) !?SplitResult { fn insert_value(self: *Leaf, value: u32) !?SplitResult {
@ -394,6 +446,16 @@ test "btree insert" {
try tree.insert(9); try tree.insert(9);
try tree.insert(8); try tree.insert(8);
tree.dbg(); tree.dbg();
try tree.insert(11);
tree.dbg();
try tree.insert(12);
try tree.insert(16);
tree.dbg();
try tree.insert(1);
try tree.insert(2);
try tree.insert(0);
try tree.insert(5);
tree.dbg();
} }
test "btree new" { test "btree new" {