when insert forces persistent-vector.sml to split, distribute half of nodes to left side and half of nodes to right side. (We avoid repeated tiny vectors this way, which reduces tree height and maintains balance.)

This commit is contained in:
2025-12-01 14:24:41 +00:00
parent 328a4e76f1
commit 6fba536f6f

View File

@@ -363,7 +363,7 @@ struct
val rightSize = VectorSlice.full #[getMaxSize right] val rightSize = VectorSlice.full #[getMaxSize right]
val leftLen = SOME idx val leftLen = SOME idx
val rightLen = SOME (idx - Vector.length nodes - 1) val rightLen = SOME (Vector.length nodes - idx - 1)
val leftSizeSlice = VectorSlice.slice (sizes, 0, leftLen) val leftSizeSlice = VectorSlice.slice (sizes, 0, leftLen)
val rightSizeSlice = VectorSlice.slice (sizes, idx + 1, rightLen) val rightSizeSlice = VectorSlice.slice (sizes, idx + 1, rightLen)
@@ -426,11 +426,28 @@ struct
if Vector.length sizes = maxSize then if Vector.length sizes = maxSize then
(* have to split *) (* have to split *)
let let
val rightItems = #[{start = start, finish = finish}] val startLen = SOME halfSize
val rightSize = #[finish] val midLen = SOME (Vector.length items - halfSize)
val right = LEAF (rightItems, rightSize)
val leftSizes = VectorSlice.slice (sizes, 0, startLen)
val leftItems = VectorSlice.slice (items, 0, startLen)
val midSizes = VectorSlice.slice (sizes, halfSize, midLen)
val midItems = VectorSlice.slice (items, halfSize, midLen)
val rightSizes = VectorSlice.full #[finish]
val rightItems = VectorSlice.full #[{start = start, finish = finish}]
val rightItems = VectorSlice.concat [midItems, rightItems]
val leftItems = VectorSlice.vector leftItems
val rightSizes = VectorSlice.concat [midSizes, rightSizes]
val leftSizes = VectorSlice.vector leftSizes
val left = LEAF (leftItems, leftSizes)
val right = LEAF (rightItems, rightSizes)
in in
INSERT_SPLIT (tree, right) INSERT_SPLIT (left, right)
end end
else else
(* can just append *) (* can just append *)
@@ -446,11 +463,28 @@ struct
if Vector.length sizes = maxSize then if Vector.length sizes = maxSize then
(* have to split *) (* have to split *)
let let
val leftItems = #[{start = start, finish = finish}] val leftSizes = VectorSlice.full #[finish]
val leftSize = #[finish] val leftItems = VectorSlice.full #[{start = start, finish = finish}]
val left = LEAF (leftItems, leftSize)
val midLen = SOME halfSize
val rightLen = SOME (Vector.length items - halfSize)
val midSizes = VectorSlice.slice (sizes, 0, midLen)
val midItems = VectorSlice.slice (items, 0, midLen)
val rightSizes = VectorSlice.slice (sizes, halfSize, rightLen)
val rightItems = VectorSlice.slice (items, halfSize, rightLen)
val leftSizes = VectorSlice.concat [leftSizes, midSizes]
val rightSizes = VectorSlice.vector rightSizes
val leftItems = VectorSlice.concat [leftItems, midItems]
val rightItems = VectorSlice.vector rightItems
val left = LEAF (leftItems, leftSizes)
val right = LEAF (rightItems, rightSizes)
in in
INSERT_SPLIT (left, tree) INSERT_SPLIT (left, right)
end end
else else
(* just prepend *) (* just prepend *)
@@ -466,7 +500,7 @@ struct
let let
val idx = BinSearch.equalOrMore (finish, sizes) val idx = BinSearch.equalOrMore (finish, sizes)
val leftLen = SOME idx val leftLen = SOME idx
val rightLen = SOME (idx - Vector.length sizes) val rightLen = SOME (Vector.length sizes - idx)
val leftSizes = VectorSlice.slice (sizes, 0, leftLen) val leftSizes = VectorSlice.slice (sizes, 0, leftLen)
val rightSizes = VectorSlice.slice (sizes, idx, rightLen) val rightSizes = VectorSlice.slice (sizes, idx, rightLen)