-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathskiplist.go
176 lines (161 loc) · 3.71 KB
/
skiplist.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
package skiplist
import (
"math/rand"
"sync"
)
const (
// ListMaxLevel is the Skiplist can have
ListMaxLevel = 32
// ListP is the P value for the SkipList
ListP = 0.5
)
// SkipList interface defining the methods
// needed for a skip list
type SkipList interface {
Search(key int) *Node
Delete(key int) bool
Insert(key int, val interface{}) *Node
Iterator() Iterator
}
// List is a basic skip list implementation
// with search, delete, and insert functionality
// and uses a mutex to allow for multi-threaded interaction
type List struct {
sync.RWMutex
MaxLevel int
level int
length int
header *Node
footer *Node
}
var _ SkipList = (*List)(nil)
// Returns a random level used during inserting nodes
func randomLevel(maxLevel int) int {
newLevel := 1
for rand.Float64() >= ListP && newLevel < maxLevel && newLevel < ListMaxLevel-1 {
newLevel++
}
return newLevel
}
// NewList initializes a new skiplist with
// max level of 32 or 2^32 elements
func NewList() *List {
return NewListWithLevel(ListMaxLevel)
}
// NewListWithLevel initializes a new skiplist with a custom
// max level. Level is defaulted to 32 to allow
// for 2^32 max elements
func NewListWithLevel(level int) *List {
return &List{
MaxLevel: level,
header: &Node{forward: make([]*Node, level)},
level: 0,
}
}
// Iterator returns an iterable from the current
// head of the skiplist.
func (l *List) Iterator() Iterator {
return &iterable{curr: l.header}
}
// Size returns the length of the list
func (l *List) Size() int {
return l.length
}
// Search for a node in the skip list by the key
// will return a Node if found or nil if not found
func (l *List) Search(key int) *Node {
l.RLock()
defer l.RUnlock()
x := l.header
for i := l.level; i >= 0; i-- {
for x.forward[i] != nil && x.forward[i].key < key {
x = x.forward[i]
}
}
x = x.forward[0]
if x != nil && x.key == key {
return x
}
return nil
}
// Insert a new node into the skip list providing a
// integer key and a byte array value. Will return
// the inserted Node
func (l *List) Insert(key int, val interface{}) *Node {
update := make([]*Node, l.MaxLevel)
x := l.header
var alreadyChecked *Node
l.Lock()
defer l.Unlock()
for i := l.level; i >= 0; i-- {
for x.forward[i] != nil &&
alreadyChecked != x.forward[i] &&
x.forward[i].key < key {
x = x.forward[i]
}
alreadyChecked = x.forward[i]
update[i] = x
}
x = x.forward[0]
if x != nil && x.key == key {
x.val = val
return x
}
newLevel := randomLevel(l.MaxLevel)
if newLevel > l.level {
for i := l.level + 1; i < newLevel; i++ {
update[i] = l.header
}
l.level = newLevel
}
x = NewNode(newLevel, key, val)
for i := 0; i < newLevel; i++ {
x.forward[i] = update[i].forward[i]
update[i].forward[i] = x
}
x.backward = nil
if update[0] != l.header {
x.backward = update[0]
}
if x.forward[0] != nil {
x.forward[0].backward = x
}
if l.footer == nil || l.footer.key < key {
l.footer = x
}
l.length++
return x
}
// Delete will delete a node for the provided key
// will return a true/false if Node was deleted or not
func (l *List) Delete(key int) bool {
update := make([]*Node, l.MaxLevel)
x := l.header
var alreadyChecked *Node
l.Lock()
defer l.Unlock()
for i := l.level; i >= 0; i-- {
for x.forward[i] != nil &&
alreadyChecked != x.forward[i] &&
x.forward[i].key < key {
x = x.forward[i]
}
alreadyChecked = x.forward[i]
update[i] = x
}
x = x.forward[0]
if x != nil && x.key == key {
for i := 0; i < l.level; i++ {
if update[i].forward[i] != x {
break
}
update[i].forward[i] = x.forward[i]
}
for l.level > 1 && len(l.header.forward) > l.level && l.header.forward[l.level-1] == nil {
l.level--
}
l.length--
return true
}
return false
}