Skip to content

Commit

Permalink
skiplist TopMin接口满足api约束 #2
Browse files Browse the repository at this point in the history
  • Loading branch information
guonaihong committed Jun 12, 2022
1 parent 7bceadb commit ed7f0b3
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 7 deletions.
2 changes: 1 addition & 1 deletion btree/btree.go
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@ func (b *Btree[K, V]) Range(callback func(k K, v V) bool) *Btree[K, V] {
return b
}

// 返回最小的n个值, 升序返回
// 返回最小的n个值, 升序返回, 比如0,1,2,3
func (b *Btree[K, V]) TopMin(limit int, callback func(k K, v V) bool) *Btree[K, V] {
b.Range(func(k K, v V) bool {
if limit <= 0 {
Expand Down
30 changes: 28 additions & 2 deletions skiplist/skiplist.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ func New[T any](compare func(T, T) int) *SkipList[T] {

s.compare = compare
s.resetRand()
s.head = newNode[T](SKIPLIST_MAXLEVEL, 0, *new(T))
s.head = newNode(SKIPLIST_MAXLEVEL, 0, *new(T))
return s
}

Expand Down Expand Up @@ -161,7 +161,7 @@ func (s *SkipList[T]) Insert(score float64, elem T) *SkipList[T] {
}

// 创建新节点
x = newNode[T](level, score, elem)
x = newNode(level, score, elem)
for i := 0; i < level; i++ {
// x.NodeLevel[i]的节点假设等于a, 需要插入的节点x在a之后,
// a, x, a.forward三者的关系就是[a, x, a.forward]
Expand Down Expand Up @@ -263,6 +263,32 @@ func (s *SkipList[T]) Remove(score float64) *SkipList[T] {
return s
}

// 遍历
func (s *SkipList[T]) Range(callback func(score float64, v T) bool) *SkipList[T] {
if s.head == nil {
return s
}

for h := s.head.NodeLevel[0].forward; h != nil; h = h.NodeLevel[0].forward {
if !callback(h.score, h.elem) {
return s
}
}
return s
}

// 返回最小的n个值, 升序返回, 比如0,1,2,3
func (b *SkipList[T]) TopMin(limit int, callback func(score float64, v T) bool) *SkipList[T] {
b.Range(func(score float64, v T) bool {
if limit <= 0 {
return false
}
callback(score, v)
limit--
return true
})
return b
}
func (s *SkipList[T]) Len() int {
return s.length
}
2 changes: 1 addition & 1 deletion skiplist/skiplist_bench_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ func intCmp(a, b float64) int {
// 五百万数据的Get操作时间
func BenchmarkGet(b *testing.B) {
max := 1000000.0 * 5
set := New[float64](intCmp)
set := New(intCmp)
for i := 0.0; i < max; i++ {
set.Set(i, i)
}
Expand Down
63 changes: 60 additions & 3 deletions skiplist/skiplist_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ import (
)

func Test_New(t *testing.T) {
n := New[string](strings.Compare)
n := New(strings.Compare)
assert.NotNil(t, n)
}

func Test_SetGet(t *testing.T) {
zset := New[string](strings.Compare)
zset := New(strings.Compare)
max := 100.0
for i := 0.0; i < max; i++ {
zset.Set(i, fmt.Sprintf("%d", int(i)))
Expand All @@ -28,7 +28,7 @@ func Test_SetGet(t *testing.T) {
}

func Test_SetGetRemove(t *testing.T) {
zset := New[float64](cmp.Compare[float64])
zset := New(cmp.Compare[float64])

max := 100.0
for i := 0.0; i < max; i++ {
Expand All @@ -52,3 +52,60 @@ func Test_SetGetRemove(t *testing.T) {
zset.Set(i, i)
}
}

// 测试TopMin, 它返回最小的几个值
func Test_Skiplist_TopMin(t *testing.T) {

need := []int{}
count10 := 10
count100 := 100
count1000 := 1000

for i := 0; i < count1000; i++ {
need = append(need, i)
}

needCount := []int{count10, count100, count100}
for i, b := range []*SkipList[int]{
// btree里面元素 少于 TopMin 需要返回的值
func() *SkipList[int] {
b := New(cmp.Compare[int])
for i := 0; i < count10; i++ {
b.Set(float64(i), i)
}

assert.Equal(t, b.Len(), count10)
return b
}(),
// btree里面元素 等于 TopMin 需要返回的值
func() *SkipList[int] {

b := New(cmp.Compare[int])
for i := 0; i < count100; i++ {
b.Set(float64(i), i)
}
assert.Equal(t, b.Len(), count100)
return b
}(),
// btree里面元素 大于 TopMin 需要返回的值
func() *SkipList[int] {

b := New(cmp.Compare[int])
for i := 0; i < count1000; i++ {
b.Set(float64(i), i)
}
assert.Equal(t, b.Len(), count1000)
return b
}(),
} {
var key, val []int
b.TopMin(count100, func(k float64, v int) bool {
key = append(key, int(k))
val = append(val, v)
return true
})
assert.Equal(t, key, need[:needCount[i]])
assert.Equal(t, val, need[:needCount[i]])
}

}

0 comments on commit ed7f0b3

Please sign in to comment.