first commit
This commit is contained in:
commit
193d5e0fbf
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