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,16 +22,26 @@ const BTree = struct {
self.dbg();
if (self.root) |*root| {
const result = try root.as_leaf().insert_value(value);
if (result) |split| {
// create new node which will replace self.
const parent = try Node.create(self.ally);
parent.leaf.level = split.left.level + 1;
parent.leaf.push_value(split.middle);
parent.insert_node(NodeOrLeaf.from_leaf(split.left));
parent.insert_node(NodeOrLeaf.from_leaf(split.right));
const search = root.find_key(value);
self.root = .{ .internal = parent };
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| {
// create new node which will replace self.
const parent = try Node.create(self.ally);
parent.leaf.level = split.left.level + 1;
parent.leaf.push_value(split.middle);
parent.insert_node(NodeOrLeaf.from_leaf(split.left));
parent.insert_node(NodeOrLeaf.from_leaf(split.right));
self.root = .{ .internal = parent };
}
},
}
} else {
var leaf: *Leaf = try self.ally.create(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 {
switch (self) {
.internal => |node| {
@ -237,11 +273,12 @@ const BTree = struct {
}
const SplitResult = struct {
// attached
// attached, old node that may be modified
left: *Leaf,
// 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,
// free floating leaf, must be attached
// new, free floating leaf, must be attached
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);
new.level = self.level;
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
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]);
if (idx >= B) {
new.push_value(value);
middle = self.values[idx - 1];
self.len = idx - 1;
} else {
self.push_value(value);
}
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
// up because we are at the root node
fn insert_value(self: *Leaf, value: u32) !?SplitResult {
@ -394,6 +446,16 @@ test "btree insert" {
try tree.insert(9);
try tree.insert(8);
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" {