github.com/songzhibin97/go-baseutils@v0.0.2-0.20240302024150-487d8ce9c082/structure/sets/zset/skiplist.go (about)

     1  package zset
     2  
     3  import (
     4  	"math"
     5  	"unsafe"
     6  
     7  	"github.com/songzhibin97/go-baseutils/base/bcomparator"
     8  	"github.com/songzhibin97/go-baseutils/sys/fastrand"
     9  )
    10  
    11  //
    12  // Skip list implementation.
    13  //
    14  
    15  const (
    16  	maxLevel    = 32   // same to ZSKIPLIST_MAXLEVEL, should be enough for 2^64 elements
    17  	probability = 0.25 // same to ZSKIPLIST_P, 1/4
    18  )
    19  
    20  // listNode is node of list.
    21  type listNode[K comparable] struct {
    22  	score float64 // key for sorting, which is allowed to be repeated
    23  	value K
    24  	prev  *listNode[K] // back pointer that only available at level 1
    25  	level int          // the length of optionalArray
    26  	oparr optionalArray
    27  }
    28  
    29  func newListNode[K comparable](score float64, value K, level int) *listNode[K] {
    30  	node := &listNode[K]{
    31  		score: score,
    32  		value: value,
    33  		level: level,
    34  	}
    35  	node.oparr.init(level)
    36  	return node
    37  }
    38  
    39  func (n *listNode[K]) loadNext(i int) *listNode[K] {
    40  	return (*listNode[K])(n.oparr.loadNext(i))
    41  }
    42  
    43  func (n *listNode[K]) storeNext(i int, node *listNode[K]) {
    44  	n.oparr.storeNext(i, unsafe.Pointer(node))
    45  }
    46  
    47  func (n *listNode[K]) loadSpan(i int) int {
    48  	return n.oparr.loadSpan(i)
    49  }
    50  
    51  func (n *listNode[K]) storeSpan(i int, span int) {
    52  	n.oparr.storeSpan(i, span)
    53  }
    54  
    55  func (n *listNode[K]) loadNextAndSpan(i int) (*listNode[K], int) {
    56  	return n.loadNext(i), n.loadSpan(i)
    57  }
    58  
    59  func (n *listNode[K]) storeNextAndSpan(i int, next *listNode[K], span int) {
    60  	n.storeNext(i, next)
    61  	n.storeSpan(i, span)
    62  }
    63  
    64  func (n *listNode[K]) lessThan(score float64, value K, comparator bcomparator.Comparator[K]) bool {
    65  	if n.score < score {
    66  		return true
    67  	}
    68  	if n.score == score {
    69  		return comparator(n.value, value) < 0
    70  	}
    71  	return false
    72  }
    73  
    74  func (n *listNode[K]) lessEqual(score float64, value K, comparator bcomparator.Comparator[K]) bool {
    75  	if n.score < score {
    76  		return true
    77  	}
    78  	if n.score == score {
    79  		return comparator(n.value, value) <= 0
    80  	}
    81  	return false
    82  }
    83  
    84  func (n *listNode[K]) equal(score float64, value K) bool {
    85  	return n.value == value && n.score == score
    86  }
    87  
    88  // list is a specialized skip list implementation for sorted set.
    89  //
    90  // It is almost implement the original
    91  // algorithm described by William Pugh in " Lists: A Probabilistic
    92  // Alternative to Balanced Trees", modified in three ways:
    93  // a) this implementation allows for repeated scores.
    94  // b) the comparison is not just by key (our 'score') but by satellite data(?).
    95  // c) there is a back pointer, so it's a doubly linked list with the back
    96  // pointers being only at "level 1". This allows to traverse the list
    97  // from tail to head, useful for RevRange.
    98  type list[K comparable] struct {
    99  	header       *listNode[K]
   100  	tail         *listNode[K]
   101  	length       int
   102  	highestLevel int // highest level for now
   103  	comparator   bcomparator.Comparator[K]
   104  }
   105  
   106  func newList[K comparable](comparator bcomparator.Comparator[K]) *list[K] {
   107  	var zero K
   108  	l := &list[K]{
   109  		header:       newListNode[K](-math.MaxFloat64, zero, maxLevel), // FIXME:
   110  		highestLevel: 1,
   111  		comparator:   comparator,
   112  	}
   113  	return l
   114  }
   115  
   116  // Insert inserts a new node in the skiplist. Assumes the element does not already
   117  // exist (up to the caller to enforce that).
   118  func (l *list[K]) Insert(score float64, value K) *listNode[K] {
   119  	var (
   120  		update [maxLevel]*listNode[K]
   121  		rank   [maxLevel + 1]int // +1 for eliminating a boundary judgment
   122  	)
   123  
   124  	x := l.header
   125  	for i := l.highestLevel - 1; i >= 0; i-- {
   126  		rank[i] = rank[i+1] // also fine when i == maxLevel - 1
   127  		next := x.loadNext(i)
   128  		for next != nil && next.lessThan(score, value, l.comparator) {
   129  			rank[i] += x.loadSpan(i)
   130  			x = next
   131  			next = x.loadNext(i)
   132  		}
   133  		update[i] = x
   134  	}
   135  
   136  	// We assume the element is not already inside, since we allow duplicated
   137  	// scores, reinserting the same element should never happen since the
   138  	// caller of Add() should test in the hash table if the element is
   139  	// already inside or not.
   140  	level := l.randomLevel()
   141  	if level > l.highestLevel {
   142  		// Create higher levels.
   143  		for i := l.highestLevel; i < level; i++ {
   144  			rank[i] = 0
   145  			update[i] = l.header
   146  			update[i].storeSpan(i, l.length)
   147  		}
   148  		l.highestLevel = level
   149  	}
   150  	x = newListNode(score, value, level)
   151  	for i := 0; i < level; i++ {
   152  		// update --> x --> update.next
   153  		x.storeNext(i, update[i].loadNext(i))
   154  		update[i].storeNext(i, x)
   155  		// update[i].span is splitted to: new update[i].span and x.span
   156  		x.storeSpan(i, update[i].loadSpan(i)-(rank[0]-rank[i]))
   157  		update[i].storeSpan(i, (rank[0]-rank[i])+1)
   158  	}
   159  	// Increment span for untouched levels.
   160  	for i := level; i < l.highestLevel; i++ {
   161  		update[i].storeSpan(i, update[i].loadSpan(i)+1)
   162  	}
   163  
   164  	// Update back pointer.
   165  	if update[0] != l.header {
   166  		x.prev = update[0]
   167  	}
   168  
   169  	if next := x.loadNext(0); next != nil { // not tail of skiplist
   170  		next.prev = x
   171  	} else {
   172  		l.tail = x
   173  	}
   174  	l.length++
   175  
   176  	return x
   177  }
   178  
   179  // randomLevel returns a level between [1, maxLevel] for insertion.
   180  func (l *list[K]) randomLevel() int {
   181  	level := 1
   182  	for fastrand.Uint32n(1/probability) == 0 {
   183  		level++
   184  	}
   185  	if level > maxLevel {
   186  		return maxLevel
   187  	}
   188  	return level
   189  }
   190  
   191  // Rank finds the rank for an element by both score and value.
   192  // Returns 0 when the element cannot be found, rank otherwise.
   193  //
   194  // NOTE: the rank is 1-based due to the span of l->header to the
   195  // first element.
   196  func (l *list[K]) Rank(score float64, value K) int {
   197  	rank := 0
   198  	x := l.header
   199  	for i := l.highestLevel - 1; i >= 0; i-- {
   200  		next := x.loadNext(i)
   201  		for next != nil && next.lessEqual(score, value, l.comparator) {
   202  			rank += x.loadSpan(i)
   203  			x = next
   204  			next = x.loadNext(i)
   205  		}
   206  
   207  		// x might be equal to l->header, so test if obj is non-nil
   208  		// TODO: Why not use if x != l.header?
   209  		if x.equal(score, value) {
   210  			return rank
   211  		}
   212  	}
   213  	return 0
   214  }
   215  
   216  // deleteNode is a internal function for deleting node x in O(1) time by giving a
   217  // update position matrix.
   218  func (l *list[K]) deleteNode(x *listNode[K], update *[maxLevel]*listNode[K]) {
   219  	for i := 0; i < l.highestLevel; i++ {
   220  		if update[i].loadNext(i) == x {
   221  			// Remove x, updaet[i].span = updaet[i].span + x.span - 1 (x removed).
   222  			next, span := x.loadNextAndSpan(i)
   223  			span += update[i].loadSpan(i) - 1
   224  			update[i].storeNextAndSpan(i, next, span)
   225  		} else {
   226  			// x does not appear on this level, just update span.
   227  			update[i].storeSpan(i, update[i].loadSpan(i)-1)
   228  		}
   229  	}
   230  	if next := x.loadNext(0); next != nil { // not tail of skiplist
   231  		next.prev = x.prev
   232  	} else {
   233  		l.tail = x.prev
   234  	}
   235  	for l.highestLevel > 1 && l.header.loadNext(l.highestLevel-1) != nil {
   236  		// Clear the pointer and span for safety.
   237  		l.header.storeNextAndSpan(l.highestLevel-1, nil, 0)
   238  		l.highestLevel--
   239  	}
   240  	l.length--
   241  }
   242  
   243  // Delete deletes an element with matching score/element from the skiplist.
   244  // The deleted node is returned if the node was found, otherwise 0 is returned.
   245  func (l *list[K]) Delete(score float64, value K) *listNode[K] {
   246  	var update [maxLevel]*listNode[K]
   247  
   248  	x := l.header
   249  	for i := l.highestLevel - 1; i >= 0; i-- {
   250  		next := x.loadNext(i)
   251  		for next != nil && next.lessThan(score, value, l.comparator) {
   252  			x = next
   253  			next = x.loadNext(i)
   254  		}
   255  		update[i] = x
   256  	}
   257  	x = x.loadNext(0)
   258  	if x != nil && x.equal(score, value) {
   259  		l.deleteNode(x, &update)
   260  		return x
   261  	}
   262  	return nil // not found
   263  }
   264  
   265  // UpdateScore updates the score of an element inside the sorted set skiplist.
   266  //
   267  // NOTE: the element must exist and must match 'score'.
   268  // This function does not update the score in the hash table side, the
   269  // caller should take care of it.
   270  //
   271  // NOTE: this function attempts to just update the node, in case after
   272  // the score update, the node would be exactly at the same position.
   273  // Otherwise the skiplist is modified by removing and re-adding a new
   274  // element, which is more costly.
   275  //
   276  // The function returns the updated element skiplist node pointer.
   277  func (l *list[K]) UpdateScore(oldScore float64, value K, newScore float64) *listNode[K] {
   278  	var update [maxLevel]*listNode[K]
   279  
   280  	x := l.header
   281  	for i := l.highestLevel - 1; i >= 0; i-- {
   282  		next := x.loadNext(i)
   283  		for next != nil && next.lessThan(oldScore, value, l.comparator) {
   284  			x = next
   285  			next = x.loadNext(i)
   286  		}
   287  		update[i] = x
   288  	}
   289  
   290  	// Jump to our element: note that this function assumes that the
   291  	// element with the matching score exists.
   292  	x = x.loadNext(0)
   293  
   294  	// Fastpath: If the node, after the score update, would be still exactly
   295  	// at the same position, we can just update the score without
   296  	// actually removing and re-inserting the element in the skiplist.
   297  	if next := x.loadNext(0); (x.prev == nil || x.prev.score < newScore) &&
   298  		(next == nil || next.score > newScore) {
   299  		x.score = newScore
   300  		return x
   301  	}
   302  
   303  	// No way to reuse the old node: we need to remove and insert a new
   304  	// one at a different place.
   305  	v := x.value
   306  	l.deleteNode(x, &update)
   307  	newNode := l.Insert(newScore, v)
   308  	return newNode
   309  }
   310  
   311  func greaterThanMin(value float64, min float64, ex bool) bool {
   312  	if ex {
   313  		return value > min
   314  	}
   315  	return value >= min
   316  }
   317  
   318  func lessThanMax(value float64, max float64, ex bool) bool {
   319  	if ex {
   320  		return value < max
   321  	}
   322  	return value <= max
   323  }
   324  
   325  // DeleteRangeByScore deletes all the elements with score between min and max
   326  // from the skiplist.
   327  // Both min and max can be inclusive or exclusive (see RangeOpt).
   328  // When inclusive a score >= min && score <= max is deleted.
   329  //
   330  // This function returns count of deleted elements.
   331  func (l *list[K]) DeleteRangeByScore(min, max float64, opt RangeOpt, dict map[K]float64) []Node[K] {
   332  	var (
   333  		update  [maxLevel]*listNode[K]
   334  		removed []Node[K]
   335  	)
   336  
   337  	x := l.header
   338  	for i := l.highestLevel - 1; i >= 0; i-- {
   339  		next := x.loadNext(i)
   340  		for next != nil && !greaterThanMin(next.score, min, opt.ExcludeMin) {
   341  			x = next
   342  			next = x.loadNext(i)
   343  		}
   344  		update[i] = x
   345  	}
   346  
   347  	// Current node is the last with score not greater than min.
   348  	x = x.loadNext(0)
   349  
   350  	// Delete nodes in range.
   351  	for x != nil && lessThanMax(x.score, max, opt.ExcludeMax) {
   352  		next := x.loadNext(0)
   353  		l.deleteNode(x, &update)
   354  		delete(dict, x.value)
   355  		removed = append(removed, Node[K]{
   356  			Value: x.value,
   357  			Score: x.score,
   358  		})
   359  		x = next
   360  	}
   361  
   362  	return removed
   363  }
   364  
   365  // Delete all the elements with rank between start and end from the skiplist.
   366  // Start and end are inclusive.
   367  //
   368  // NOTE: start and end need to be 1-based
   369  func (l *list[K]) DeleteRangeByRank(start, end int, dict map[K]float64) []Node[K] {
   370  	var (
   371  		update    [maxLevel]*listNode[K]
   372  		removed   []Node[K]
   373  		traversed int
   374  	)
   375  
   376  	x := l.header
   377  	for i := l.highestLevel - 1; i >= 0; i-- {
   378  		next, span := x.loadNextAndSpan(i)
   379  		for next != nil && traversed+span < start {
   380  			traversed += span
   381  			x = next
   382  			next, span = x.loadNextAndSpan(i)
   383  		}
   384  		update[i] = x
   385  	}
   386  
   387  	traversed++
   388  	x = x.loadNext(0)
   389  	// Delete nodes in range.
   390  	for x != nil && traversed <= end {
   391  		next := x.loadNext(0)
   392  		l.deleteNode(x, &update)
   393  		delete(dict, x.value)
   394  		removed = append(removed, Node[K]{
   395  			Value: x.value,
   396  			Score: x.score,
   397  		})
   398  		traversed++
   399  		x = next
   400  	}
   401  	return removed
   402  }
   403  
   404  // GetNodeByRank finds an element by its rank. The rank argument needs to be 1-based.
   405  func (l *list[K]) GetNodeByRank(rank int) *listNode[K] {
   406  	var traversed int
   407  
   408  	x := l.header
   409  	for i := l.highestLevel - 1; i >= 0; i-- {
   410  		next, span := x.loadNextAndSpan(i)
   411  		for next != nil && traversed+span <= rank {
   412  			traversed += span
   413  			x = next
   414  			next, span = x.loadNextAndSpan(i)
   415  		}
   416  		if traversed == rank {
   417  			return x
   418  		}
   419  	}
   420  	return nil
   421  }
   422  
   423  // FirstInRange finds the first node that is contained in the specified range.
   424  func (l *list[K]) FirstInRange(min, max float64, opt RangeOpt) *listNode[K] {
   425  	if !l.IsInRange(min, max, opt) {
   426  		return nil
   427  	}
   428  
   429  	x := l.header
   430  	for i := l.highestLevel - 1; i >= 0; i-- {
   431  		next := x.loadNext(i)
   432  		for next != nil && !greaterThanMin(next.score, min, opt.ExcludeMin) {
   433  			x = next
   434  			next = x.loadNext(i)
   435  		}
   436  	}
   437  
   438  	// The next node MUST not be NULL (excluded by IsInRange).
   439  	x = x.loadNext(0)
   440  	if !lessThanMax(x.score, max, opt.ExcludeMax) {
   441  		return nil
   442  	}
   443  	return x
   444  }
   445  
   446  // LastInRange finds the last node that is contained in the specified range.
   447  func (l *list[K]) LastInRange(min, max float64, opt RangeOpt) *listNode[K] {
   448  	if !l.IsInRange(min, max, opt) {
   449  		return nil
   450  	}
   451  
   452  	x := l.header
   453  	for i := l.highestLevel - 1; i >= 0; i-- {
   454  		next := x.loadNext(i)
   455  		for next != nil && lessThanMax(next.score, max, opt.ExcludeMax) {
   456  			x = next
   457  			next = x.loadNext(i)
   458  		}
   459  	}
   460  
   461  	// The node x must not be NULL (excluded by IsInRange).
   462  	if !greaterThanMin(x.score, min, opt.ExcludeMin) {
   463  		return nil
   464  	}
   465  	return x
   466  }
   467  
   468  // IsInRange returns whether there is a port of sorted set in given range.
   469  func (l *list[K]) IsInRange(min, max float64, opt RangeOpt) bool {
   470  	// Test empty range.
   471  	if min > max || (min == max && (opt.ExcludeMin || opt.ExcludeMax)) {
   472  		return false
   473  	}
   474  	if l.tail == nil || !greaterThanMin(l.tail.score, min, opt.ExcludeMin) {
   475  		return false
   476  	}
   477  	if next := l.header.loadNext(0); next == nil || !lessThanMax(next.score, max, opt.ExcludeMax) {
   478  		return false
   479  	}
   480  	return true
   481  }