github.com/andy2046/gopie@v0.7.0/pkg/skiplist/skiplist.go (about) 1 // Package skiplist provides a Skip List implementation. 2 package skiplist 3 4 import ( 5 "math" 6 "math/rand" 7 "time" 8 ) 9 10 const ( 11 defaultMaxLevel int = 16 12 13 defaultProbability float64 = 1 / math.E 14 ) 15 16 // New creates a new skip list with provided maxLevel or defaultMaxLevel. 17 func New(maxLevel ...int) *SkipList { 18 level := defaultMaxLevel 19 if len(maxLevel) > 0 && maxLevel[0] >= 1 && maxLevel[0] <= 64 { 20 level = maxLevel[0] 21 } 22 23 return &SkipList{ 24 elementNode: elementNode{forward: make([]*Element, level)}, 25 searchNodesCache: make([]*elementNode, level), 26 maxLevel: level, 27 randSource: rand.New(rand.NewSource(time.Now().UnixNano())), 28 probability: defaultProbability, 29 probTable: probabilityTable(defaultProbability, level), 30 } 31 } 32 33 // Front returns the first element in the list. 34 func (list *SkipList) Front() *Element { 35 return list.forward[0] 36 } 37 38 // Len returns the list length. 39 func (list *SkipList) Len() int { 40 list.mutex.RLock() 41 defer list.mutex.RUnlock() 42 return list.length 43 } 44 45 // MaxLevel sets current max level of skip list and returns the previous max level. 46 // If `level` < 1, it does not set current max level. 47 func (list *SkipList) MaxLevel(level int) int { 48 if level < 1 || list.maxLevel == level { 49 return list.maxLevel 50 } 51 52 list.mutex.Lock() 53 defer list.mutex.Unlock() 54 prev := list.maxLevel 55 list.maxLevel = level 56 57 switch { 58 case prev > level: 59 for k, n := level, len(list.forward); k < n; k++ { 60 list.forward[k] = nil // avoid mem leak 61 } 62 list.forward = list.forward[:level] 63 for k, n := level, len(list.searchNodesCache); k < n; k++ { 64 list.searchNodesCache[k] = nil // avoid mem leak 65 } 66 list.searchNodesCache = list.searchNodesCache[:level] 67 list.probTable = list.probTable[:level] 68 case prev < level: 69 f := make([]*Element, level) 70 copy(f, list.forward) 71 for i := range list.forward { 72 list.forward[i] = nil // avoid mem leak 73 } 74 list.forward = f 75 for i := range list.searchNodesCache { 76 list.searchNodesCache[i] = nil // avoid mem leak 77 } 78 list.searchNodesCache = make([]*elementNode, level) 79 list.probTable = probabilityTable(list.probability, level) 80 } 81 82 return prev 83 } 84 85 // Set upserts the value with provided key into the list and returns the element. 86 func (list *SkipList) Set(key string, value int64) *Element { 87 list.mutex.Lock() 88 defer list.mutex.Unlock() 89 90 var element *Element 91 fingerSearches := list.fingerSearchNodes(key) 92 93 if element = fingerSearches[0].forward[0]; element != nil && element.key <= key { 94 element.value = value 95 return element 96 } 97 98 element = &Element{ 99 elementNode: elementNode{ 100 forward: make([]*Element, list.randLevel()), 101 }, 102 key: key, 103 value: value, 104 } 105 106 for i := range element.forward { 107 element.forward[i] = fingerSearches[i].forward[i] 108 fingerSearches[i].forward[i] = element 109 } 110 111 list.length++ 112 return element 113 } 114 115 // Get searches element by provided key and returns the element if found or nil otherwise. 116 func (list *SkipList) Get(key string) *Element { 117 list.mutex.Lock() 118 defer list.mutex.Unlock() 119 120 var next *Element 121 prev := &list.elementNode 122 123 for i := list.maxLevel - 1; i >= 0; i-- { 124 next = prev.forward[i] 125 126 for next != nil && key > next.key { 127 prev = &next.elementNode 128 next = next.forward[i] 129 } 130 } 131 132 if next != nil && next.key <= key { 133 return next 134 } 135 136 return nil 137 } 138 139 // Remove deletes the element with provided key from the list, 140 // and returns the removed element if found or nil otherwise. 141 func (list *SkipList) Remove(key string) *Element { 142 list.mutex.Lock() 143 defer list.mutex.Unlock() 144 145 fingerSearches := list.fingerSearchNodes(key) 146 147 if element := fingerSearches[0].forward[0]; element != nil && element.key <= key { 148 for k, v := range element.forward { 149 fingerSearches[k].forward[k] = v 150 } 151 152 list.length-- 153 return element 154 } 155 156 return nil 157 } 158 159 // fingerSearchNodes returns a list of nodes, where nodes[i] contains a pointer to the rightmost node 160 // of level i or higher that is to the left of the location of the `key`. 161 func (list *SkipList) fingerSearchNodes(key string) []*elementNode { 162 var next *Element 163 prev := &list.elementNode 164 fingerSearches := list.searchNodesCache 165 166 for i := list.maxLevel - 1; i >= 0; i-- { 167 next = prev.forward[i] 168 169 for next != nil && key > next.key { 170 prev = &next.elementNode 171 next = next.forward[i] 172 } 173 174 fingerSearches[i] = prev 175 } 176 177 return fingerSearches 178 } 179 180 func (list *SkipList) randLevel() int { 181 r := float64(list.randSource.Int63()) / (1 << 63) 182 level := 1 183 for level < list.maxLevel && r < list.probTable[level] { 184 level++ 185 } 186 return level 187 } 188 189 // Probability sets the P value of skip list and returns the previous P. 190 // If `newProbability` < 0, it does not set current P. 191 func (list *SkipList) Probability(newProbability float64) float64 { 192 p := list.probability 193 if newProbability >= 0 { 194 list.mutex.Lock() 195 defer list.mutex.Unlock() 196 list.probability = newProbability 197 list.probTable = probabilityTable(newProbability, list.maxLevel) 198 } 199 return p 200 } 201 202 // probabilityTable stores the probability for a new node appearing in a given level, 203 // probability is in [0, 1], maxLevel is in (0, 64]. 204 func probabilityTable(probability float64, maxLevel int) []float64 { 205 t := make([]float64, 0, maxLevel) 206 for i := 1; i <= maxLevel; i++ { 207 t = append(t, math.Pow(probability, float64(i-1))) 208 } 209 return t 210 }