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