insert with lookup
3rd lvl is broken
This commit is contained in:
parent
29ebb53e8c
commit
94f42f24c5
104
src/main.zig
104
src/main.zig
|
@ -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" {
|
||||||
|
|
Loading…
Reference in a new issue