first commit

This commit is contained in:
redhat 2025-04-15 12:00:38 +08:00
commit 3c0e1a83cc
3 changed files with 219 additions and 0 deletions

3
go.mod Normal file
View File

@ -0,0 +1,3 @@
module git.zhangshuocauc.cn/redhat/goSkipList
go 1.21.3

187
skiplist.go Normal file
View 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
View 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))
}