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