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 {
 | 
					    fn insert(self: *Self, value: u32) !void {
 | 
				
			||||||
        if (self.root) |*root| {
 | 
					        if (self.get_root()) |*root| {
 | 
				
			||||||
            const search = root.find_key(value);
 | 
					            const search = root.find_key(value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            switch (search) {
 | 
					            switch (search) {
 | 
				
			||||||
| 
						 | 
					@ -192,7 +204,7 @@ const BTree = struct {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn remove(self: *Self, key: u32) void {
 | 
					    fn remove(self: *Self, key: u32) void {
 | 
				
			||||||
        if (self.root) |*root| {
 | 
					        if (self.get_root()) |*root| {
 | 
				
			||||||
            const search = root.find_key(key);
 | 
					            const search = root.find_key(key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            switch (search) {
 | 
					            switch (search) {
 | 
				
			||||||
| 
						 | 
					@ -205,7 +217,7 @@ const BTree = struct {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn find_key(self: *Self, key: u32) ?u32 {
 | 
					    fn find_key(self: *Self, key: u32) ?u32 {
 | 
				
			||||||
        switch (self.root.?.find_key(key)) {
 | 
					        switch (self.get_root().?.find_key(key)) {
 | 
				
			||||||
            .Leaf => |leaf| {
 | 
					            .Leaf => |leaf| {
 | 
				
			||||||
                return leaf.leaf.get_values()[leaf.idx];
 | 
					                return leaf.leaf.get_values()[leaf.idx];
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
| 
						 | 
					@ -216,14 +228,14 @@ const BTree = struct {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn dbg(self: *Self) void {
 | 
					    fn dbg(self: *Self) void {
 | 
				
			||||||
        if (self.root) |root| {
 | 
					        if (self.get_root()) |root| {
 | 
				
			||||||
            root.dbg();
 | 
					            root.dbg();
 | 
				
			||||||
            std.debug.print("\n", .{});
 | 
					            std.debug.print("\n", .{});
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn destroy(self: *Self) void {
 | 
					    fn destroy(self: *Self) void {
 | 
				
			||||||
        if (self.root) |*root| {
 | 
					        if (self.get_root()) |*root| {
 | 
				
			||||||
            root.destroy();
 | 
					            root.destroy();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -360,7 +372,6 @@ const BTree = struct {
 | 
				
			||||||
        fn remove_key_from_node(self: NodeOrLeaf, key: u32) void {
 | 
					        fn remove_key_from_node(self: NodeOrLeaf, key: u32) void {
 | 
				
			||||||
            switch (self.force()) {
 | 
					            switch (self.force()) {
 | 
				
			||||||
                .internal => |node| {
 | 
					                .internal => |node| {
 | 
				
			||||||
                    //const Option = Optional.Option;
 | 
					 | 
				
			||||||
                    // need to check if the edges to the left and right of the to-be-removed key exist,
 | 
					                    // 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
 | 
					                    // and if both exist, find the immediate neighbors of the key and promote
 | 
				
			||||||
                    // the one in the bigger leaf up as a replacement.
 | 
					                    // the one in the bigger leaf up as a replacement.
 | 
				
			||||||
| 
						 | 
					@ -644,6 +655,7 @@ const BTree = struct {
 | 
				
			||||||
                    if (edg) |edge| {
 | 
					                    if (edg) |edge| {
 | 
				
			||||||
                        edge.as_leaf().set_parent(self, @intCast(u16, i - count));
 | 
					                        edge.as_leaf().set_parent(self, @intCast(u16, i - count));
 | 
				
			||||||
                        self.edges[i - count] = edge;
 | 
					                        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 {
 | 
					        fn set_parent(self: *Leaf, parent: *Node, idx: u16) void {
 | 
				
			||||||
            if (idx < 0 or idx > parent.leaf.len or idx > CAPACITY) {
 | 
					            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 };
 | 
					            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 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: {
 | 
					                    const sibling: struct { node: NodeOrLeaf, side: Side } = blk: {
 | 
				
			||||||
                        switch (left_sib) {
 | 
					                        switch (left_sib) {
 | 
				
			||||||
| 
						 | 
					@ -851,24 +883,28 @@ const BTree = struct {
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    };
 | 
					                    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    const offset = @intCast(i32, sibling.node.as_leaf().parent.?.idx) - @intCast(i32, parent.idx);
 | 
					                    if (parent.parent != sibling.node.as_leaf().parent.?.parent) {
 | 
				
			||||||
                    std.debug.print("{any} {} {} {}\n", .{ sibling.node.as_leaf().parent, sibling.node.as_leaf().parent.?.idx, parent.idx, offset });
 | 
					                        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) {
 | 
					                    if (sibling.node.as_leaf().len > MIN_AFTER_SPLIT) {
 | 
				
			||||||
                        // rotate
 | 
					                        // rotate value from sibling -> parent -> self
 | 
				
			||||||
                        const index = @intCast(usize, @max(0, parent.idx + offset));
 | 
					                        const index = @intCast(usize, sibling.side.parent_seperator_idx(parent.idx));
 | 
				
			||||||
                        std.debug.print("{} {} {}\n", .{ parent.idx, offset, index });
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        NodeOrLeaf.from_leaf(self).push_value(parent.parent.leaf.values[index]);
 | 
					                        NodeOrLeaf.from_leaf(self).push_value(parent.parent.leaf.values[index]);
 | 
				
			||||||
                        parent.parent.leaf.values[index] = blk: {
 | 
					                        parent.parent.leaf.values[index] = blk: {
 | 
				
			||||||
                            if (offset < 0) {
 | 
					                            switch (sibling.side) {
 | 
				
			||||||
 | 
					                                .Left => {
 | 
				
			||||||
                                    const value = sibling.node.get_most_significant_value();
 | 
					                                    const value = sibling.node.get_most_significant_value();
 | 
				
			||||||
                                    sibling.node.as_leaf().remove_key(value);
 | 
					                                    sibling.node.as_leaf().remove_key(value);
 | 
				
			||||||
                                    break :blk value;
 | 
					                                    break :blk value;
 | 
				
			||||||
                            } else {
 | 
					                                },
 | 
				
			||||||
 | 
					                                .Right => {
 | 
				
			||||||
                                    const value = sibling.node.get_least_significant_value();
 | 
					                                    const value = sibling.node.get_least_significant_value();
 | 
				
			||||||
                                    sibling.node.as_leaf().remove_key(value);
 | 
					                                    sibling.node.as_leaf().remove_key(value);
 | 
				
			||||||
                                    break :blk value;
 | 
					                                    break :blk value;
 | 
				
			||||||
 | 
					                                },
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
                        };
 | 
					                        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -876,11 +912,23 @@ const BTree = struct {
 | 
				
			||||||
                        switch (NodeOrLeaf.from_leaf(self)) {
 | 
					                        switch (NodeOrLeaf.from_leaf(self)) {
 | 
				
			||||||
                            .internal => |iself| {
 | 
					                            .internal => |iself| {
 | 
				
			||||||
                                const isibling = sibling.node.internal;
 | 
					                                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 => {},
 | 
					                            .leaf => {},
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
| 
						 | 
					@ -897,14 +945,14 @@ const BTree = struct {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        defer right.destroy();
 | 
					                        defer right.destroy();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        // remove superfluous parent edge to right
 | 
				
			||||||
 | 
					                        _ = parent.parent.remove_edge(right.parent.?.idx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        // merge parent seperator into left
 | 
					                        // merge parent seperator into left
 | 
				
			||||||
                        const key = parent.parent.leaf.get_value(left.parent.?.idx);
 | 
					                        const key = parent.parent.leaf.get_value(left.parent.?.idx);
 | 
				
			||||||
                        parent.parent.leaf.remove_key(key);
 | 
					                        parent.parent.leaf.remove_key(key);
 | 
				
			||||||
                        NodeOrLeaf.from_leaf(left).push_value(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
 | 
					                        // copy values from right to left
 | 
				
			||||||
                        std.mem.copy(u32, left.values[left.len..], right.values[0..right.len]);
 | 
					                        std.mem.copy(u32, left.values[left.len..], right.values[0..right.len]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -913,7 +961,7 @@ const BTree = struct {
 | 
				
			||||||
                            .internal => |ileft| {
 | 
					                            .internal => |ileft| {
 | 
				
			||||||
                                const iright = @ptrCast(*Node, right);
 | 
					                                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| {
 | 
					                                for (ileft.get_edges(), 0..) |e, i| {
 | 
				
			||||||
                                    if (e) |ee| {
 | 
					                                    if (e) |ee| {
 | 
				
			||||||
| 
						 | 
					@ -938,6 +986,7 @@ const BTree = struct {
 | 
				
			||||||
                                    // copy values
 | 
					                                    // copy values
 | 
				
			||||||
                                    root.as_leaf().len = edge.as_leaf().len;
 | 
					                                    root.as_leaf().len = edge.as_leaf().len;
 | 
				
			||||||
                                    root.as_leaf().level = edge.as_leaf().level;
 | 
					                                    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..]);
 | 
					                                    std.mem.copy(u32, root.leaf.values[0..], edge.as_leaf().values[0..]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                                    switch (edge.force()) {
 | 
					                                    switch (edge.force()) {
 | 
				
			||||||
| 
						 | 
					@ -1129,7 +1178,7 @@ test "btree rand insert" {
 | 
				
			||||||
    tree.dbg();
 | 
					    tree.dbg();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
test "ref removal" {
 | 
					test "ref removal left" {
 | 
				
			||||||
    std.debug.print("remove keys\n", .{});
 | 
					    std.debug.print("remove keys\n", .{});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    var tree = BTree.create(std.testing.allocator);
 | 
					    var tree = BTree.create(std.testing.allocator);
 | 
				
			||||||
| 
						 | 
					@ -1144,6 +1193,51 @@ test "ref removal" {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (0..15) |i| {
 | 
					    for (0..15) |i| {
 | 
				
			||||||
        tree.remove(@intCast(u32, 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();
 | 
					    tree.dbg();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue