first commit
This commit is contained in:
commit
3c0e1a83cc
3
go.mod
Normal file
3
go.mod
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
module git.zhangshuocauc.cn/redhat/goSkipList
|
||||||
|
|
||||||
|
go 1.21.3
|
187
skiplist.go
Normal file
187
skiplist.go
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
package goSkipList
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SkipList struct {
|
||||||
|
head *node
|
||||||
|
}
|
||||||
|
|
||||||
|
type node struct {
|
||||||
|
nexts []*node
|
||||||
|
key, value int
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSkipList() *SkipList {
|
||||||
|
return &SkipList{
|
||||||
|
head: new(node),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SkipList) roll() int {
|
||||||
|
level := 0
|
||||||
|
for rand.Intn(2) > 0 {
|
||||||
|
level++
|
||||||
|
}
|
||||||
|
|
||||||
|
return level
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SkipList) search(key int) *node {
|
||||||
|
move := s.head
|
||||||
|
|
||||||
|
for leve := len(s.head.nexts) - 1; leve >= 0; leve-- {
|
||||||
|
for move.nexts[leve] != nil && move.nexts[leve].key < key {
|
||||||
|
move = move.nexts[leve]
|
||||||
|
}
|
||||||
|
|
||||||
|
if move.nexts[leve] != nil && move.nexts[leve].key == key {
|
||||||
|
return move.nexts[leve]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SkipList) floor(key int) *node {
|
||||||
|
move := s.head
|
||||||
|
|
||||||
|
for leve := len(s.head.nexts) - 1; leve >= 0; leve-- {
|
||||||
|
for move.nexts[leve] != nil && move.nexts[leve].key < key {
|
||||||
|
move = move.nexts[leve]
|
||||||
|
}
|
||||||
|
|
||||||
|
if move.nexts[leve] != nil && move.nexts[leve].key == key {
|
||||||
|
return move.nexts[leve]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return move
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SkipList) ceiling(key int) *node {
|
||||||
|
move := s.head
|
||||||
|
|
||||||
|
for leve := len(s.head.nexts) - 1; leve >= 0; leve-- {
|
||||||
|
for move.nexts[leve] != nil && move.nexts[leve].key < key {
|
||||||
|
move = move.nexts[leve]
|
||||||
|
}
|
||||||
|
|
||||||
|
if move.nexts[leve] != nil && move.nexts[leve].key == key {
|
||||||
|
return move.nexts[leve]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return move.nexts[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SkipList) Get(key int) (int, bool) {
|
||||||
|
if _node := s.search(key); _node != nil {
|
||||||
|
return _node.value, true
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SkipList) Put(key, value int) {
|
||||||
|
if _node := s.search(key); _node != nil {
|
||||||
|
_node.value = value
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
levels := s.roll()
|
||||||
|
for len(s.head.nexts)-1 < levels {
|
||||||
|
s.head.nexts = append(s.head.nexts, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
newNode := &node{
|
||||||
|
key: key,
|
||||||
|
value: value,
|
||||||
|
nexts: make([]*node, levels+1),
|
||||||
|
}
|
||||||
|
|
||||||
|
move := s.head
|
||||||
|
for level := len(s.head.nexts) - 1; level >= 0; level-- {
|
||||||
|
for move.nexts[level] != nil && move.nexts[level].key < key {
|
||||||
|
move = move.nexts[level]
|
||||||
|
}
|
||||||
|
|
||||||
|
if level > levels {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
newNode.nexts[level] = move.nexts[level]
|
||||||
|
move.nexts[level] = newNode
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SkipList) Delete(key int) {
|
||||||
|
if _node := s.search(key); _node == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
move := s.head
|
||||||
|
for level := len(s.head.nexts) - 1; level >= 0; level-- {
|
||||||
|
for move.nexts[level] != nil && move.nexts[level].key < key {
|
||||||
|
move = move.nexts[level]
|
||||||
|
}
|
||||||
|
|
||||||
|
if move.nexts[level] != nil && move.nexts[level].key > key {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
move.nexts[level] = move.nexts[level].nexts[level]
|
||||||
|
}
|
||||||
|
|
||||||
|
diff := 0
|
||||||
|
for level := len(s.head.nexts) - 1; level >= 0 && s.head.nexts[level] == nil; level-- {
|
||||||
|
diff++
|
||||||
|
}
|
||||||
|
s.head.nexts = s.head.nexts[:len(s.head.nexts)-diff]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SkipList) Print() {
|
||||||
|
move := s.head
|
||||||
|
|
||||||
|
for level := len(s.head.nexts) - 1; level >= 0; level-- {
|
||||||
|
fmt.Printf("level:%d ", level)
|
||||||
|
for move.nexts[level] != nil {
|
||||||
|
fmt.Printf("{key:%d,value:%d }", move.nexts[level].key, move.nexts[level].value)
|
||||||
|
move = move.nexts[level]
|
||||||
|
}
|
||||||
|
move = s.head
|
||||||
|
fmt.Println()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SkipList) Range(start, end int) [][2]int {
|
||||||
|
_node := s.floor(start)
|
||||||
|
if _node == nil {
|
||||||
|
return [][2]int{}
|
||||||
|
}
|
||||||
|
|
||||||
|
var res [][2]int
|
||||||
|
for move := _node; move != nil && move.key < end; move = move.nexts[0] {
|
||||||
|
res = append(res, [2]int{move.key, move.value})
|
||||||
|
}
|
||||||
|
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SkipList) Floor(key int) [2]int {
|
||||||
|
if _node := s.floor(key); _node != nil {
|
||||||
|
return [2]int{_node.key, _node.value}
|
||||||
|
}
|
||||||
|
|
||||||
|
return [2]int{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SkipList) Ceiling(key int) [2]int {
|
||||||
|
if _node := s.ceiling(key); _node != nil {
|
||||||
|
return [2]int{_node.key, _node.value}
|
||||||
|
}
|
||||||
|
|
||||||
|
return [2]int{}
|
||||||
|
}
|
29
skiplist_test.go
Normal file
29
skiplist_test.go
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
package goSkipList
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func Test_skiplist(t *testing.T) {
|
||||||
|
list := NewSkipList()
|
||||||
|
|
||||||
|
list.Put(1, 1)
|
||||||
|
list.Put(2, 2)
|
||||||
|
|
||||||
|
list.Print()
|
||||||
|
|
||||||
|
list.Delete(1)
|
||||||
|
list.Delete(2)
|
||||||
|
|
||||||
|
list.Put(1, 1)
|
||||||
|
list.Put(2, 2)
|
||||||
|
list.Put(3, 1)
|
||||||
|
list.Put(4, 2)
|
||||||
|
list.Put(5, 1)
|
||||||
|
list.Put(6, 2)
|
||||||
|
|
||||||
|
list.Print()
|
||||||
|
|
||||||
|
t.Error(list.Get(1))
|
||||||
|
t.Error(list.Get(2))
|
||||||
|
|
||||||
|
t.Error(list.Range(1,6))
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user