diff --git a/src/main.zig b/src/main.zig index a4c3aed..f14c6a2 100644 --- a/src/main.zig +++ b/src/main.zig @@ -161,6 +161,8 @@ const BTree = struct { } } + std.debug.print("placing {} in {}/{}th position\n", .{ value, n, leaf.len }); + var tmp = value; for (leaf.get_values()[n..]) |*val| { const t = val.*; @@ -265,7 +267,10 @@ const BTree = struct { } if (self.get_edges()[idx]) |edge| { - std.debug.print("edge already present?:", .{}); + std.debug.print("edge already present between {} and {}\nedge already present:", .{ + self_leaf.get_values()[@max(idx - 1, 0)], + self_leaf.get_values()[@min(idx + 1, self_leaf.len - 1)], + }); child.dbg(); std.debug.print(" - ", .{}); edge.dbg(); @@ -350,26 +355,42 @@ const BTree = struct { right: *Leaf, fn concat(parent: SplitResult, child: SplitResult) SplitResult { - const middle = parent.middle; - - // safety: we know parent left and right are nodes because + // safety @ptrCast(): 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 - // check if the rightmost value of the right child is smaller than the parent middle - if (child.right.get_values()[child.right.len - 1] < middle) { - @ptrCast(*Node, parent.left).insert_node(NodeOrLeaf.from_leaf(child.right)); - } else if (child.right.get_values()[0] > middle) { - @ptrCast(*Node, parent.right).insert_node(NodeOrLeaf.from_leaf(child.right)); - } else { - std.debug.print("AAAAAAAAAAA something bad", .{}); - } - } else { - // if the child left component is in the parent right, so must the child right + std.debug.print("concatinating [", .{}); + parent.left.dbg(); + std.debug.print(", {}, ", .{parent.middle}); + parent.right.dbg(); + std.debug.print(" ]", .{}); + std.debug.print(" and [ ", .{}); + child.left.dbg(); + std.debug.print(", {}, ", .{child.middle}); + child.right.dbg(); + std.debug.print(" ]", .{}); + + // we only care about the childs middle and left, and since they are ordered we + // can learn about the right part from the middle part + if (child.middle < parent.middle) { + // I'm not sure if checking the childs right part is actually needed? + // I don't think so but can't think of a solid enough reason why + + // child is entirely between two values of the parent, so any relation between + // the childs mid point and any of the parents values is true for any of + // the childs values, right? + @ptrCast(*Node, parent.left).insert_node(NodeOrLeaf.from_leaf(child.right)); + } + // since they cant be equal, this must mean child is bigger than parent + else { @ptrCast(*Node, parent.right).insert_node(NodeOrLeaf.from_leaf(child.right)); } + std.debug.print(" into [", .{}); + parent.left.dbg(); + std.debug.print(", {}, ", .{parent.middle}); + parent.right.dbg(); + std.debug.print(" ]\n", .{}); + return parent; } }; @@ -408,34 +429,36 @@ const BTree = struct { if (leaf.len < CAPACITY) { std.debug.print("pushing value {} into ", .{value}); - NodeOrLeaf.from_leaf(self).dbg(); + self.dbg(); std.debug.print("\n", .{}); NodeOrLeaf.from_leaf(leaf).push_value(value); } else { std.debug.print("splitting node ", .{}); self.dbg(); - const split = try leaf.split_at(value); + var split = try leaf.split_at(value); std.debug.print(" into [ ", .{}); split.left.dbg(); std.debug.print(", {}, ", .{split.middle}); split.right.dbg(); std.debug.print("]\n", .{}); - if (leaf.parent) |parent| { - // 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); + // recursively solve splits + var prnt = leaf.parent; + while (prnt) |parent| { + const maybe_parent_split = try parent.parent.as_leaf().insert_value(split.middle); - if (result) |parent_split| { - std.debug.print("double split\n", .{}); - - return SplitResult.concat(parent_split, split); + if (maybe_parent_split) |parent_split| { + std.debug.print("concatinating splits\n", .{}); + split = SplitResult.concat(parent_split, split); + prnt = parent.parent.as_leaf().parent; } else { parent.parent.insert_node(NodeOrLeaf.from_leaf(split.right)); + return null; } - } else { - return split; } + + return split; } return null; @@ -541,24 +564,38 @@ test "btree insert" { tree.dbg(); } -test "btree rand insert" { - std.debug.print("random insertions\n", .{}); +test "btree seq insert" { + std.debug.print("sequential insertions\n", .{}); var tree = BTree.create(std.testing.allocator); defer tree.destroy(); - var rng = std.rand.DefaultPrng.init(0); - - for (0..100) |_| { - // const i = rng.random().intRangeAtMost(u32, 0, 512); - const i = rng.random().int(u32); - tree.insert(i) catch { + for (0..100) |i| { + tree.insert(@intCast(u32, i)) catch { std.debug.print("{} already present - ignoring\n", .{i}); }; } tree.dbg(); } +// test "btree rand insert" { +// std.debug.print("random insertions\n", .{}); + +// var tree = BTree.create(std.testing.allocator); +// defer tree.destroy(); + +// var rng = std.rand.DefaultPrng.init(0); + +// for (0..100) |_| { +// const i = rng.random().intRangeAtMost(u32, 0, 512); +// // const i = rng.random().int(u32); +// tree.insert(i) catch { +// std.debug.print("{} already present - ignoring\n", .{i}); +// }; +// } +// tree.dbg(); +// } + test "btree new" { std.debug.print("testing insertion\n", .{}); var tree = BTree.create(std.testing.allocator);