From 2e8d20b9100abcd0f646c023fa0d414aaa3eaf9e Mon Sep 17 00:00:00 2001 From: Christoforus Yoga Haryanto Date: Sat, 22 Jul 2023 01:33:00 +1000 Subject: [PATCH 1/3] Add Iter Pos method. --- btreeg.go | 30 +++++++++++++++++++++++++++++- btreeg_test.go | 23 +++++++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/btreeg.go b/btreeg.go index 86b8990..d8dbec9 100644 --- a/btreeg.go +++ b/btreeg.go @@ -3,7 +3,9 @@ // license that can be found in the LICENSE file. package btree -import "sync" +import ( + "sync" +) type BTreeG[T any] struct { isoid uint64 @@ -1323,6 +1325,32 @@ func (iter *IterG[T]) Item() T { return iter.item } +// Pos returns the position of the current iterator item. Returns -1 +// if the tree is empty or the iterator is at the beginning of the tree. +func (iter *IterG[T]) Pos() int { + if iter.tr == nil { + return -1 + } + if !iter.seeked { + return -1 + } + count := 0 + for i, s := range iter.stack { + count += s.i + if !s.n.leaf() { + c := *s.n.children + t := s.i + if i == len(iter.stack)-1 { + t++ + } + for j := 0; j < t; j++ { + count += c[j].count + } + } + } + return count +} + // Items returns all the items in order. func (tr *BTreeG[T]) Items() []T { return tr.items(false) diff --git a/btreeg_test.go b/btreeg_test.go index cf61aa9..55e9033 100644 --- a/btreeg_test.go +++ b/btreeg_test.go @@ -1343,3 +1343,26 @@ func TestGenericIterSeekPrefix(t *testing.T) { iter.Release() } } + +func TestGenericPos(t *testing.T) { + tr := NewBTreeG(func(a, b int) bool { + return a < b + }) + count := 10_000 + for i := 0; i < count; i++ { + tr.Set(i * 2) + } + iter := tr.Iter() + lastPos := iter.Pos() + assert(lastPos == -1) + iter.Release() + for i := 0; i < count; i++ { + iter = tr.Iter() + ret := iter.Seek(i*2 - 1) + assert(ret == true) + pos := iter.Pos() + assert(pos-lastPos == 1) + lastPos = pos + iter.Release() + } +} From 67c445f2393a65d6be35dc8f170c28879da13b70 Mon Sep 17 00:00:00 2001 From: Christoforus Yoga Haryanto Date: Mon, 24 Jul 2023 14:23:31 +1000 Subject: [PATCH 2/3] Add note about the complexity in the comment. --- btreeg.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/btreeg.go b/btreeg.go index d8dbec9..65c7548 100644 --- a/btreeg.go +++ b/btreeg.go @@ -1327,6 +1327,8 @@ func (iter *IterG[T]) Item() T { // Pos returns the position of the current iterator item. Returns -1 // if the tree is empty or the iterator is at the beginning of the tree. +// Overall, the complexity will be O(log N⋅M) where stack height will +// follow the height of the btree, which is log N, and M as the degree. func (iter *IterG[T]) Pos() int { if iter.tr == nil { return -1 From a51eb06d20705bf28eea614918bd2699d22771a1 Mon Sep 17 00:00:00 2001 From: Christoforus Yoga Haryanto Date: Mon, 24 Jul 2023 14:26:28 +1000 Subject: [PATCH 3/3] Add Pos to non-type-parameterized version. --- btree.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/btree.go b/btree.go index 3483cc6..beac244 100644 --- a/btree.go +++ b/btree.go @@ -353,3 +353,11 @@ func (iter *Iter) Prev() bool { func (iter *Iter) Item() any { return iter.base.Item() } + +// Pos returns the position of the current iterator item. Returns -1 +// if the tree is empty or the iterator is at the beginning of the tree. +// Overall, the complexity will be O(log N⋅M) where stack height will +// follow the height of the btree, which is log N, and M as the degree. +func (iter *Iter) Pos() int { + return iter.base.Pos() +}