inserting shoudl work now
This commit is contained in:
parent
94f42f24c5
commit
a627d4b1f7
165
src/main.zig
165
src/main.zig
|
@ -35,7 +35,7 @@ const BTree = struct {
|
||||||
// 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);
|
||||||
parent.leaf.level = split.left.level + 1;
|
parent.leaf.level = split.left.level + 1;
|
||||||
parent.leaf.push_value(split.middle);
|
NodeOrLeaf.from_leaf(parent.as_leaf()).push_value(split.middle);
|
||||||
parent.insert_node(NodeOrLeaf.from_leaf(split.left));
|
parent.insert_node(NodeOrLeaf.from_leaf(split.left));
|
||||||
parent.insert_node(NodeOrLeaf.from_leaf(split.right));
|
parent.insert_node(NodeOrLeaf.from_leaf(split.right));
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ const BTree = struct {
|
||||||
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);
|
||||||
leaf.init(self.ally);
|
leaf.init(self.ally);
|
||||||
leaf.push_value(value);
|
NodeOrLeaf.from_leaf(leaf).push_value(value);
|
||||||
self.root = NodeOrLeaf{ .leaf = leaf };
|
self.root = NodeOrLeaf{ .leaf = leaf };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -104,6 +104,87 @@ const BTree = struct {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn split_at(self: NodeOrLeaf, value: u32) !Leaf.SplitResult {
|
||||||
|
const leaf = self.as_leaf();
|
||||||
|
|
||||||
|
var idx: u16 = 0;
|
||||||
|
for (leaf.get_values(), 0..) |v, i| {
|
||||||
|
idx = @intCast(u16, i);
|
||||||
|
if (v > value) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std.debug.assert(leaf.len == CAPACITY);
|
||||||
|
//std.debug.assert(idx > 0 and idx < CAPACITY - 1);
|
||||||
|
|
||||||
|
var new: *Leaf = undefined;
|
||||||
|
switch (self) {
|
||||||
|
.internal => |internal| {
|
||||||
|
const node = try Node.create(leaf.ally);
|
||||||
|
std.mem.copy(?NodeOrLeaf, &node.edges, internal.edges[B..]);
|
||||||
|
|
||||||
|
new = node.as_leaf();
|
||||||
|
},
|
||||||
|
.leaf => {
|
||||||
|
const node = try Leaf.create(leaf.ally);
|
||||||
|
new = node;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
new.level = leaf.level;
|
||||||
|
|
||||||
|
new.len = B - 1;
|
||||||
|
std.mem.copy(u32, &new.values, leaf.values[B..]);
|
||||||
|
const middle = leaf.values[B - 1];
|
||||||
|
leaf.len = B - 1;
|
||||||
|
|
||||||
|
// take from right half
|
||||||
|
if (idx >= B) {
|
||||||
|
NodeOrLeaf.from_leaf(new).push_value(value);
|
||||||
|
} else {
|
||||||
|
NodeOrLeaf.from_leaf(leaf).push_value(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return .{ .left = leaf, .middle = middle, .right = new };
|
||||||
|
}
|
||||||
|
|
||||||
|
fn push_value(self: NodeOrLeaf, value: u32) void {
|
||||||
|
const leaf = self.as_leaf();
|
||||||
|
|
||||||
|
std.debug.assert(leaf.len < CAPACITY);
|
||||||
|
|
||||||
|
var n = leaf.len;
|
||||||
|
for (leaf.get_values(), 0..) |val, i| {
|
||||||
|
if (val >= value) {
|
||||||
|
n = @intCast(u16, i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var tmp = value;
|
||||||
|
for (leaf.get_values()[n..]) |*val| {
|
||||||
|
const t = val.*;
|
||||||
|
val.* = tmp;
|
||||||
|
tmp = t;
|
||||||
|
}
|
||||||
|
leaf.values[leaf.len] = tmp;
|
||||||
|
|
||||||
|
switch (self) {
|
||||||
|
.internal => |node| {
|
||||||
|
var tmp2: ?NodeOrLeaf = null;
|
||||||
|
for (node.get_edges()[n + 1 ..]) |*edge| {
|
||||||
|
const t = edge.*;
|
||||||
|
edge.* = tmp2;
|
||||||
|
tmp2 = t;
|
||||||
|
}
|
||||||
|
node.edges[leaf.len + 1] = tmp2;
|
||||||
|
},
|
||||||
|
else => {},
|
||||||
|
}
|
||||||
|
|
||||||
|
leaf.len = leaf.len + 1;
|
||||||
|
}
|
||||||
|
|
||||||
fn find_key(self: NodeOrLeaf, key: u32) Leaf.SearchResult {
|
fn find_key(self: NodeOrLeaf, key: u32) Leaf.SearchResult {
|
||||||
var leaf = self.as_leaf();
|
var leaf = self.as_leaf();
|
||||||
while (true) {
|
while (true) {
|
||||||
|
@ -183,9 +264,11 @@ const BTree = struct {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self.get_edges()[idx]) |_| {
|
if (self.get_edges()[idx]) |edge| {
|
||||||
std.debug.print("edge already present?:", .{});
|
std.debug.print("edge already present?:", .{});
|
||||||
child.dbg();
|
child.dbg();
|
||||||
|
std.debug.print(" - ", .{});
|
||||||
|
edge.dbg();
|
||||||
std.debug.print("\n", .{});
|
std.debug.print("\n", .{});
|
||||||
} else {
|
} else {
|
||||||
child.as_leaf().parent = .{ .parent = self, .idx = idx };
|
child.as_leaf().parent = .{ .parent = self, .idx = idx };
|
||||||
|
@ -280,37 +363,31 @@ const BTree = struct {
|
||||||
middle: u32,
|
middle: u32,
|
||||||
// new, free floating leaf, must be attached
|
// new, free floating leaf, must be attached
|
||||||
right: *Leaf,
|
right: *Leaf,
|
||||||
|
|
||||||
|
fn concat(parent: SplitResult, child: SplitResult) SplitResult {
|
||||||
|
const middle = parent.middle;
|
||||||
|
|
||||||
|
// safety: we know parent left and right are nodes because
|
||||||
|
// they originated from childs parent
|
||||||
|
if (child.left.get_values()[0] < middle) {
|
||||||
|
// the left node is already attached to the tree in the correct place
|
||||||
|
|
||||||
|
if (child.right.get_values()[child.right.len - 1] < middle) {
|
||||||
|
@ptrCast(*Node, parent.left).insert_node(NodeOrLeaf.from_leaf(child.right));
|
||||||
|
} else {
|
||||||
|
@ptrCast(*Node, parent.right).insert_node(NodeOrLeaf.from_leaf(child.right));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// if the child left component is in the parent right, so must the child right
|
||||||
|
@ptrCast(*Node, parent.right).insert_node(NodeOrLeaf.from_leaf(child.right));
|
||||||
|
}
|
||||||
|
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
fn split_at(self: *Leaf, value: u32) !SplitResult {
|
fn split_at(self: *Leaf, value: u32) !SplitResult {
|
||||||
var idx: u16 = 0;
|
return NodeOrLeaf.from_leaf(self).split_at(value);
|
||||||
for (self.get_values(), 0..) |v, i| {
|
|
||||||
idx = @intCast(u16, i);
|
|
||||||
if (v > value) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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.push_value(value);
|
|
||||||
} else {
|
|
||||||
self.push_value(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
return .{ .left = self, .middle = middle, .right = new };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const SearchResultTag = enum { Edge, Leaf };
|
const SearchResultTag = enum { Edge, Leaf };
|
||||||
|
@ -346,11 +423,11 @@ const BTree = struct {
|
||||||
self.dbg();
|
self.dbg();
|
||||||
std.debug.print("\n", .{});
|
std.debug.print("\n", .{});
|
||||||
|
|
||||||
leaf.push_value(value);
|
NodeOrLeaf.from_leaf(leaf).push_value(value);
|
||||||
} else {
|
} else {
|
||||||
const split = try leaf.split_at(value);
|
|
||||||
std.debug.print("splitting node ", .{});
|
std.debug.print("splitting node ", .{});
|
||||||
self.dbg();
|
self.dbg();
|
||||||
|
const split = try leaf.split_at(value);
|
||||||
std.debug.print("into [", .{});
|
std.debug.print("into [", .{});
|
||||||
split.left.dbg();
|
split.left.dbg();
|
||||||
std.debug.print(", {}, ", .{split.middle});
|
std.debug.print(", {}, ", .{split.middle});
|
||||||
|
@ -360,11 +437,14 @@ const BTree = struct {
|
||||||
if (leaf.parent) |parent| {
|
if (leaf.parent) |parent| {
|
||||||
// parent can only throw split if it has no parent, so we just pass it back along to the top?
|
// parent can only throw split if it has no parent, so we just pass it back along to the top?
|
||||||
const result = try parent.parent.as_leaf().insert_value(split.middle);
|
const result = try parent.parent.as_leaf().insert_value(split.middle);
|
||||||
parent.parent.insert_node(NodeOrLeaf.from_leaf(split.right));
|
|
||||||
|
|
||||||
if (result) |for_root| {
|
if (result) |for_root| {
|
||||||
return for_root;
|
std.debug.print("double split\n", .{});
|
||||||
|
|
||||||
|
return SplitResult.concat(for_root, split);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
parent.parent.insert_node(NodeOrLeaf.from_leaf(split.right));
|
||||||
} else {
|
} else {
|
||||||
return split;
|
return split;
|
||||||
}
|
}
|
||||||
|
@ -456,6 +536,21 @@ test "btree insert" {
|
||||||
try tree.insert(0);
|
try tree.insert(0);
|
||||||
try tree.insert(5);
|
try tree.insert(5);
|
||||||
tree.dbg();
|
tree.dbg();
|
||||||
|
try tree.insert(25);
|
||||||
|
try tree.insert(43);
|
||||||
|
try tree.insert(40);
|
||||||
|
try tree.insert(42);
|
||||||
|
tree.dbg();
|
||||||
|
try tree.insert(22);
|
||||||
|
try tree.insert(44);
|
||||||
|
try tree.insert(60);
|
||||||
|
try tree.insert(52);
|
||||||
|
tree.dbg();
|
||||||
|
try tree.insert(71);
|
||||||
|
try tree.insert(72);
|
||||||
|
try tree.insert(73);
|
||||||
|
try tree.insert(74);
|
||||||
|
tree.dbg();
|
||||||
}
|
}
|
||||||
|
|
||||||
test "btree new" {
|
test "btree new" {
|
||||||
|
|
Loading…
Reference in a new issue