From 193d5e0fbfade5d9570d204b0c7ecfbc833a99d2 Mon Sep 17 00:00:00 2001 From: redhat <2292650292@qq.com> Date: Tue, 15 Apr 2025 11:49:22 +0800 Subject: [PATCH] first commit --- go.mod | 3 + skiplist.go | 187 +++++++++++++++++++++++++++++++++++++++++++++++ skiplist_test.go | 29 ++++++++ 3 files changed, 219 insertions(+) create mode 100644 go.mod create mode 100644 skiplist.go create mode 100644 skiplist_test.go diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..17e0b7e --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module goSkipList + +go 1.21.3 diff --git a/skiplist.go b/skiplist.go new file mode 100644 index 0000000..def53a3 --- /dev/null +++ b/skiplist.go @@ -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{} +} diff --git a/skiplist_test.go b/skiplist_test.go new file mode 100644 index 0000000..87836b6 --- /dev/null +++ b/skiplist_test.go @@ -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)) +}