i think it works!!!
This commit is contained in:
parent
0ee791db3c
commit
aca2c7241b
142
src/main.zig
142
src/main.zig
|
@ -160,8 +160,20 @@ const BTree = struct {
|
|||
};
|
||||
}
|
||||
|
||||
fn force_root(self: *Self) void {
|
||||
if (self.root) |root| {
|
||||
self.root = root.force();
|
||||
}
|
||||
}
|
||||
|
||||
fn get_root(self: *Self) ?NodeOrLeaf {
|
||||
self.force_root();
|
||||
|
||||
return self.root;
|
||||
}
|
||||
|
||||
fn insert(self: *Self, value: u32) !void {
|
||||
if (self.root) |*root| {
|
||||
if (self.get_root()) |*root| {
|
||||
const search = root.find_key(value);
|
||||
|
||||
switch (search) {
|
||||
|
@ -192,7 +204,7 @@ const BTree = struct {
|
|||
}
|
||||
|
||||
fn remove(self: *Self, key: u32) void {
|
||||
if (self.root) |*root| {
|
||||
if (self.get_root()) |*root| {
|
||||
const search = root.find_key(key);
|
||||
|
||||
switch (search) {
|
||||
|
@ -205,7 +217,7 @@ const BTree = struct {
|
|||
}
|
||||
|
||||
fn find_key(self: *Self, key: u32) ?u32 {
|
||||
switch (self.root.?.find_key(key)) {
|
||||
switch (self.get_root().?.find_key(key)) {
|
||||
.Leaf => |leaf| {
|
||||
return leaf.leaf.get_values()[leaf.idx];
|
||||
},
|
||||
|
@ -216,14 +228,14 @@ const BTree = struct {
|
|||
}
|
||||
|
||||
fn dbg(self: *Self) void {
|
||||
if (self.root) |root| {
|
||||
if (self.get_root()) |root| {
|
||||
root.dbg();
|
||||
std.debug.print("\n", .{});
|
||||
}
|
||||
}
|
||||
|
||||
fn destroy(self: *Self) void {
|
||||
if (self.root) |*root| {
|
||||
if (self.get_root()) |*root| {
|
||||
root.destroy();
|
||||
}
|
||||
}
|
||||
|
@ -360,7 +372,6 @@ const BTree = struct {
|
|||
fn remove_key_from_node(self: NodeOrLeaf, key: u32) void {
|
||||
switch (self.force()) {
|
||||
.internal => |node| {
|
||||
//const Option = Optional.Option;
|
||||
// need to check if the edges to the left and right of the to-be-removed key exist,
|
||||
// and if both exist, find the immediate neighbors of the key and promote
|
||||
// the one in the bigger leaf up as a replacement.
|
||||
|
@ -644,6 +655,7 @@ const BTree = struct {
|
|||
if (edg) |edge| {
|
||||
edge.as_leaf().set_parent(self, @intCast(u16, i - count));
|
||||
self.edges[i - count] = edge;
|
||||
self.edges[i] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -733,7 +745,7 @@ const BTree = struct {
|
|||
|
||||
fn set_parent(self: *Leaf, parent: *Node, idx: u16) void {
|
||||
if (idx < 0 or idx > parent.leaf.len or idx > CAPACITY) {
|
||||
std.debug.print("{}", .{idx});
|
||||
std.debug.print("out of bounds parent idx {}", .{idx});
|
||||
}
|
||||
|
||||
self.parent = .{ .parent = parent, .idx = idx };
|
||||
|
@ -822,7 +834,27 @@ const BTree = struct {
|
|||
|
||||
const right_sib = Optional.into_option(parent.parent.get_edge(parent.idx + 1));
|
||||
|
||||
const Side = enum { Left, Right };
|
||||
const Side = enum {
|
||||
Left,
|
||||
Right,
|
||||
fn to_offset(side: @This()) i32 {
|
||||
return switch (side) {
|
||||
.Left => -1,
|
||||
.Right => 1,
|
||||
};
|
||||
}
|
||||
|
||||
// returns the index of the seperator in the parent where parent_idx is
|
||||
// the index of the edge pointing to self, and side is the side on
|
||||
// which the sibling was found
|
||||
fn parent_seperator_idx(side: @This(), parent_idx: u16) u16 {
|
||||
const offset: u16 = switch (side) {
|
||||
.Left => 1,
|
||||
.Right => 0,
|
||||
};
|
||||
return parent_idx - offset;
|
||||
}
|
||||
};
|
||||
|
||||
const sibling: struct { node: NodeOrLeaf, side: Side } = blk: {
|
||||
switch (left_sib) {
|
||||
|
@ -851,24 +883,28 @@ const BTree = struct {
|
|||
}
|
||||
};
|
||||
|
||||
const offset = @intCast(i32, sibling.node.as_leaf().parent.?.idx) - @intCast(i32, parent.idx);
|
||||
std.debug.print("{any} {} {} {}\n", .{ sibling.node.as_leaf().parent, sibling.node.as_leaf().parent.?.idx, parent.idx, offset });
|
||||
if (parent.parent != sibling.node.as_leaf().parent.?.parent) {
|
||||
std.debug.print("ERROR parent: {}", .{parent.parent});
|
||||
std.debug.print("ERROR missmatching parents\n{}\n{}\n", .{ self, sibling.node.as_leaf() });
|
||||
}
|
||||
|
||||
if (sibling.node.as_leaf().len > MIN_AFTER_SPLIT) {
|
||||
// rotate
|
||||
const index = @intCast(usize, @max(0, parent.idx + offset));
|
||||
std.debug.print("{} {} {}\n", .{ parent.idx, offset, index });
|
||||
// rotate value from sibling -> parent -> self
|
||||
const index = @intCast(usize, sibling.side.parent_seperator_idx(parent.idx));
|
||||
|
||||
NodeOrLeaf.from_leaf(self).push_value(parent.parent.leaf.values[index]);
|
||||
parent.parent.leaf.values[index] = blk: {
|
||||
if (offset < 0) {
|
||||
switch (sibling.side) {
|
||||
.Left => {
|
||||
const value = sibling.node.get_most_significant_value();
|
||||
sibling.node.as_leaf().remove_key(value);
|
||||
break :blk value;
|
||||
} else {
|
||||
},
|
||||
.Right => {
|
||||
const value = sibling.node.get_least_significant_value();
|
||||
sibling.node.as_leaf().remove_key(value);
|
||||
break :blk value;
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -876,11 +912,23 @@ const BTree = struct {
|
|||
switch (NodeOrLeaf.from_leaf(self)) {
|
||||
.internal => |iself| {
|
||||
const isibling = sibling.node.internal;
|
||||
iself.shift_edges_right(0, 1);
|
||||
iself.edges[0] = isibling.edges[isibling.leaf.len];
|
||||
isibling.edges[isibling.leaf.len] = null;
|
||||
|
||||
iself.edges[0].?.as_leaf().set_parent(iself, 0);
|
||||
switch (sibling.side) {
|
||||
.Left => {
|
||||
// shift self edges to the left because we are inserting
|
||||
// siblings left most edge at self.edges[0]
|
||||
iself.shift_edges_right(0, 1);
|
||||
const edge = isibling.remove_edge(isibling.leaf.len);
|
||||
edge.?.as_leaf().set_parent(iself, 0);
|
||||
iself.edges[0] = edge;
|
||||
},
|
||||
.Right => {
|
||||
// here we simply append the edge to our own edges
|
||||
const edge = isibling.remove_edge(0);
|
||||
edge.?.as_leaf().set_parent(iself, iself.as_leaf().len);
|
||||
iself.edges[iself.as_leaf().len] = edge;
|
||||
},
|
||||
}
|
||||
},
|
||||
.leaf => {},
|
||||
}
|
||||
|
@ -897,14 +945,14 @@ const BTree = struct {
|
|||
|
||||
defer right.destroy();
|
||||
|
||||
// remove superfluous parent edge to right
|
||||
_ = parent.parent.remove_edge(right.parent.?.idx);
|
||||
|
||||
// merge parent seperator into left
|
||||
const key = parent.parent.leaf.get_value(left.parent.?.idx);
|
||||
parent.parent.leaf.remove_key(key);
|
||||
NodeOrLeaf.from_leaf(left).push_value(key);
|
||||
|
||||
// remove superfluous parent edge to right
|
||||
_ = parent.parent.remove_edge(right.parent.?.idx);
|
||||
|
||||
// copy values from right to left
|
||||
std.mem.copy(u32, left.values[left.len..], right.values[0..right.len]);
|
||||
|
||||
|
@ -913,7 +961,7 @@ const BTree = struct {
|
|||
.internal => |ileft| {
|
||||
const iright = @ptrCast(*Node, right);
|
||||
|
||||
std.mem.copy(?NodeOrLeaf, ileft.edges[0..], iright.edges[0..]);
|
||||
std.mem.copy(?NodeOrLeaf, ileft.edges[left.len + 1 ..], iright.edges[0 .. right.len + 1]);
|
||||
|
||||
for (ileft.get_edges(), 0..) |e, i| {
|
||||
if (e) |ee| {
|
||||
|
@ -938,6 +986,7 @@ const BTree = struct {
|
|||
// copy values
|
||||
root.as_leaf().len = edge.as_leaf().len;
|
||||
root.as_leaf().level = edge.as_leaf().level;
|
||||
root.as_leaf().parent = null;
|
||||
std.mem.copy(u32, root.leaf.values[0..], edge.as_leaf().values[0..]);
|
||||
|
||||
switch (edge.force()) {
|
||||
|
@ -1129,7 +1178,7 @@ test "btree rand insert" {
|
|||
tree.dbg();
|
||||
}
|
||||
|
||||
test "ref removal" {
|
||||
test "ref removal left" {
|
||||
std.debug.print("remove keys\n", .{});
|
||||
|
||||
var tree = BTree.create(std.testing.allocator);
|
||||
|
@ -1144,6 +1193,51 @@ test "ref removal" {
|
|||
|
||||
for (0..15) |i| {
|
||||
tree.remove(@intCast(u32, i));
|
||||
tree.dbg();
|
||||
}
|
||||
|
||||
tree.dbg();
|
||||
std.debug.print("\n", .{});
|
||||
}
|
||||
|
||||
test "ref removal right" {
|
||||
std.debug.print("remove keys\n", .{});
|
||||
|
||||
var tree = BTree.create(std.testing.allocator);
|
||||
defer tree.destroy();
|
||||
|
||||
for (0..20) |i| {
|
||||
_ = try tree.insert(@intCast(u32, i));
|
||||
}
|
||||
|
||||
tree.dbg();
|
||||
std.debug.print("\n", .{});
|
||||
|
||||
for (0..15) |i| {
|
||||
tree.remove(@intCast(u32, 20 - i));
|
||||
tree.dbg();
|
||||
}
|
||||
|
||||
tree.dbg();
|
||||
std.debug.print("\n", .{});
|
||||
}
|
||||
|
||||
test "ref removal middle" {
|
||||
std.debug.print("remove keys\n", .{});
|
||||
|
||||
var tree = BTree.create(std.testing.allocator);
|
||||
defer tree.destroy();
|
||||
|
||||
for (0..20) |i| {
|
||||
_ = try tree.insert(@intCast(u32, i));
|
||||
}
|
||||
|
||||
tree.dbg();
|
||||
std.debug.print("\n", .{});
|
||||
|
||||
for (0..10) |i| {
|
||||
tree.remove(@intCast(u32, 15 - i));
|
||||
tree.dbg();
|
||||
}
|
||||
|
||||
tree.dbg();
|
||||
|
|
Loading…
Reference in a new issue