Skip to content

Commit

Permalink
feat: add support for gob serialization.
Browse files Browse the repository at this point in the history
  • Loading branch information
federicojasson authored and rdleal committed Apr 29, 2024
1 parent f110c7c commit 93fac80
Show file tree
Hide file tree
Showing 7 changed files with 839 additions and 195 deletions.
60 changes: 30 additions & 30 deletions interval/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ func (st *SearchTree[V, T]) Delete(start, end T) error {
}

intervl := interval[V, T]{
start: start,
end: end,
allowPoint: st.config.allowIntervalPoint,
Start: start,
End: end,
AllowPoint: st.config.allowIntervalPoint,
}

if intervl.isInvalid(st.cmp) {
Expand All @@ -24,7 +24,7 @@ func (st *SearchTree[V, T]) Delete(start, end T) error {

st.root = delete(st.root, intervl, st.cmp)
if st.root != nil {
st.root.color = black
st.root.Color = black
}

return nil
Expand All @@ -35,27 +35,27 @@ func delete[V, T any](n *node[V, T], intervl interval[V, T], cmp CmpFunc[T]) *no
return nil
}

if intervl.less(n.interval.start, n.interval.end, cmp) {
if n.left != nil && !isRed(n.left) && !isRed(n.left.left) {
if intervl.less(n.Interval.Start, n.Interval.End, cmp) {
if n.Left != nil && !isRed(n.Left) && !isRed(n.Left.Left) {
n = moveRedLeft(n, cmp)
}
n.left = delete(n.left, intervl, cmp)
n.Left = delete(n.Left, intervl, cmp)
} else {
if isRed(n.left) {
if isRed(n.Left) {
n = rotateRight(n, cmp)
}
if n.interval.equal(intervl.start, intervl.end, cmp) && n.right == nil {
if n.Interval.equal(intervl.Start, intervl.End, cmp) && n.Right == nil {
return nil
}
if n.right != nil && !isRed(n.right) && !isRed(n.right.left) {
if n.Right != nil && !isRed(n.Right) && !isRed(n.Right.Left) {
n = moveRedRight(n, cmp)
}
if n.interval.equal(intervl.start, intervl.end, cmp) {
minNode := min(n.right)
n.interval = minNode.interval
n.right = deleteMin(n.right, cmp)
if n.Interval.equal(intervl.Start, intervl.End, cmp) {
minNode := min(n.Right)
n.Interval = minNode.Interval
n.Right = deleteMin(n.Right, cmp)
} else {
n.right = delete(n.right, intervl, cmp)
n.Right = delete(n.Right, intervl, cmp)
}
}

Expand All @@ -65,15 +65,15 @@ func delete[V, T any](n *node[V, T], intervl interval[V, T], cmp CmpFunc[T]) *no
}

func deleteMin[V, T any](n *node[V, T], cmp CmpFunc[T]) *node[V, T] {
if n.left == nil {
if n.Left == nil {
return nil
}

if !isRed(n.left) && !isRed(n.left.left) {
if !isRed(n.Left) && !isRed(n.Left.Left) {
n = moveRedLeft(n, cmp)
}

n.left = deleteMin(n.left, cmp)
n.Left = deleteMin(n.Left, cmp)

updateSize(n)

Expand All @@ -91,7 +91,7 @@ func (st *SearchTree[V, T]) DeleteMin() {

st.root = deleteMin(st.root, st.cmp)
if st.root != nil {
st.root.color = black
st.root.Color = black
}
}

Expand All @@ -106,24 +106,24 @@ func (st *SearchTree[V, T]) DeleteMax() {

st.root = deleteMax(st.root, st.cmp)
if st.root != nil {
st.root.color = black
st.root.Color = black
}
}

func deleteMax[V, T any](n *node[V, T], cmp CmpFunc[T]) *node[V, T] {
if isRed(n.left) {
if isRed(n.Left) {
n = rotateRight(n, cmp)
}

if n.right == nil {
if n.Right == nil {
return nil
}

if !isRed(n.right) && !isRed(n.right.left) {
if !isRed(n.Right) && !isRed(n.Right.Left) {
n = moveRedRight(n, cmp)
}

n.right = deleteMax(n.right, cmp)
n.Right = deleteMax(n.Right, cmp)

updateSize(n)

Expand All @@ -143,9 +143,9 @@ func (st *MultiValueSearchTree[V, T]) Delete(start, end T) error {
}

intervl := interval[V, T]{
start: start,
end: end,
allowPoint: st.config.allowIntervalPoint,
Start: start,
End: end,
AllowPoint: st.config.allowIntervalPoint,
}

if intervl.isInvalid(st.cmp) {
Expand All @@ -154,7 +154,7 @@ func (st *MultiValueSearchTree[V, T]) Delete(start, end T) error {

st.root = delete(st.root, intervl, st.cmp)
if st.root != nil {
st.root.color = black
st.root.Color = black
}

return nil
Expand All @@ -171,7 +171,7 @@ func (st *MultiValueSearchTree[V, T]) DeleteMin() {

st.root = deleteMin(st.root, st.cmp)
if st.root != nil {
st.root.color = black
st.root.Color = black
}
}

Expand All @@ -186,6 +186,6 @@ func (st *MultiValueSearchTree[V, T]) DeleteMax() {

st.root = deleteMax(st.root, st.cmp)
if st.root != nil {
st.root.color = black
st.root.Color = black
}
}
60 changes: 30 additions & 30 deletions interval/insert.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,18 @@ func (st *SearchTree[V, T]) Insert(start, end T, val V) error {
defer st.mu.Unlock()

intervl := interval[V, T]{
start: start,
end: end,
val: val,
allowPoint: st.config.allowIntervalPoint,
Start: start,
End: end,
Val: val,
AllowPoint: st.config.allowIntervalPoint,
}

if intervl.isInvalid(st.cmp) {
return newInvalidIntervalError(intervl)
}

st.root = upsert(st.root, intervl, st.cmp)
st.root.color = black
st.root.Color = black

return nil
}
Expand All @@ -36,16 +36,16 @@ func upsert[V, T any](n *node[V, T], intervl interval[V, T], cmp CmpFunc[T]) *no
}

switch {
case intervl.equal(n.interval.start, n.interval.end, cmp):
n.interval = intervl
case intervl.less(n.interval.start, n.interval.end, cmp):
n.left = upsert(n.left, intervl, cmp)
case intervl.equal(n.Interval.Start, n.Interval.End, cmp):
n.Interval = intervl
case intervl.less(n.Interval.Start, n.Interval.End, cmp):
n.Left = upsert(n.Left, intervl, cmp)
default:
n.right = upsert(n.right, intervl, cmp)
n.Right = upsert(n.Right, intervl, cmp)
}

if cmp.gt(intervl.end, n.maxEnd) {
n.maxEnd = intervl.end
if cmp.gt(intervl.End, n.MaxEnd) {
n.MaxEnd = intervl.End
}

updateSize(n)
Expand All @@ -62,7 +62,7 @@ func (e EmptyValueListError) Error() string {
}

func newEmptyValueListError[V, T any](it interval[V, T], action string) error {
s := fmt.Sprintf("multi value interval search tree: cannot %s empty value list for interval (%v, %v)", action, it.start, it.end)
s := fmt.Sprintf("multi value interval search tree: cannot %s empty value list for interval (%v, %v)", action, it.Start, it.End)
return EmptyValueListError(s)
}

Expand All @@ -76,10 +76,10 @@ func (st *MultiValueSearchTree[V, T]) Insert(start, end T, vals ...V) error {
st.mu.Lock()
defer st.mu.Unlock()
intervl := interval[V, T]{
start: start,
end: end,
vals: vals,
allowPoint: st.config.allowIntervalPoint,
Start: start,
End: end,
Vals: vals,
AllowPoint: st.config.allowIntervalPoint,
}

if intervl.isInvalid(st.cmp) {
Expand All @@ -91,7 +91,7 @@ func (st *MultiValueSearchTree[V, T]) Insert(start, end T, vals ...V) error {
}

st.root = insert(st.root, intervl, st.cmp)
st.root.color = black
st.root.Color = black

return nil
}
Expand All @@ -102,16 +102,16 @@ func insert[V, T any](n *node[V, T], intervl interval[V, T], cmp CmpFunc[T]) *no
}

switch {
case intervl.equal(n.interval.start, n.interval.end, cmp):
n.interval.vals = append(n.interval.vals, intervl.vals...)
case intervl.less(n.interval.start, n.interval.end, cmp):
n.left = insert(n.left, intervl, cmp)
case intervl.equal(n.Interval.Start, n.Interval.End, cmp):
n.Interval.Vals = append(n.Interval.Vals, intervl.Vals...)
case intervl.less(n.Interval.Start, n.Interval.End, cmp):
n.Left = insert(n.Left, intervl, cmp)
default:
n.right = insert(n.right, intervl, cmp)
n.Right = insert(n.Right, intervl, cmp)
}

if cmp.gt(intervl.end, n.maxEnd) {
n.maxEnd = intervl.end
if cmp.gt(intervl.End, n.MaxEnd) {
n.MaxEnd = intervl.End
}

updateSize(n)
Expand All @@ -129,10 +129,10 @@ func (st *MultiValueSearchTree[V, T]) Upsert(start, end T, vals ...V) error {
st.mu.Lock()
defer st.mu.Unlock()
intervl := interval[V, T]{
start: start,
end: end,
vals: vals,
allowPoint: st.config.allowIntervalPoint,
Start: start,
End: end,
Vals: vals,
AllowPoint: st.config.allowIntervalPoint,
}

if intervl.isInvalid(st.cmp) {
Expand All @@ -144,7 +144,7 @@ func (st *MultiValueSearchTree[V, T]) Upsert(start, end T, vals ...V) error {
}

st.root = upsert(st.root, intervl, st.cmp)
st.root.color = black
st.root.Color = black

return nil
}
28 changes: 14 additions & 14 deletions interval/interval.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ func (s InvalidIntervalError) Error() string {

func newInvalidIntervalError[V, T any](it interval[V, T]) error {
var b strings.Builder
fmt.Fprintf(&b, "interval search tree invalid range: start value %v cannot be less than ", it.start)
if !it.allowPoint {
fmt.Fprintf(&b, "interval search tree invalid range: start value %v cannot be less than ", it.Start)
if !it.AllowPoint {
b.WriteString("or equal to ")
}
fmt.Fprintf(&b, "end value %v", it.end)
fmt.Fprintf(&b, "end value %v", it.End)
return InvalidIntervalError(b.String())
}

Expand Down Expand Up @@ -53,28 +53,28 @@ func (f CmpFunc[T]) gte(x, y T) bool {
}

type interval[V, T any] struct {
start T
end T
val V
vals []V
allowPoint bool
Start T
End T
Val V
Vals []V
AllowPoint bool
}

func (it interval[V, T]) isInvalid(cmp CmpFunc[T]) bool {
if it.allowPoint {
return cmp.lt(it.end, it.start)
if it.AllowPoint {
return cmp.lt(it.End, it.Start)
}
return cmp.lte(it.end, it.start)
return cmp.lte(it.End, it.Start)
}

func (it interval[V, T]) less(start, end T, cmp CmpFunc[T]) bool {
return cmp.lt(it.start, start) || cmp.eq(it.start, start) && cmp.lt(it.end, end)
return cmp.lt(it.Start, start) || cmp.eq(it.Start, start) && cmp.lt(it.End, end)
}

func (it interval[V, T]) intersects(start, end T, cmp CmpFunc[T]) bool {
return cmp.lte(it.start, end) && cmp.lte(start, it.end)
return cmp.lte(it.Start, end) && cmp.lte(start, it.End)
}

func (it interval[V, T]) equal(start, end T, cmp CmpFunc[T]) bool {
return cmp.eq(it.start, start) && cmp.eq(it.end, end)
return cmp.eq(it.Start, start) && cmp.eq(it.End, end)
}
Loading

0 comments on commit 93fac80

Please sign in to comment.