github.com/hdt3213/godis@v1.2.9/datastruct/sortedset/skiplist.go (about)

     1  package sortedset
     2  
     3  import (
     4  	"math/bits"
     5  	"math/rand"
     6  )
     7  
     8  const (
     9  	maxLevel = 16
    10  )
    11  
    12  // Element is a key-score pair
    13  type Element struct {
    14  	Member string
    15  	Score  float64
    16  }
    17  
    18  // Level aspect of a node
    19  type Level struct {
    20  	forward *node // forward node has greater score
    21  	span    int64
    22  }
    23  
    24  type node struct {
    25  	Element
    26  	backward *node
    27  	level    []*Level // level[0] is base level
    28  }
    29  
    30  type skiplist struct {
    31  	header *node
    32  	tail   *node
    33  	length int64
    34  	level  int16
    35  }
    36  
    37  func makeNode(level int16, score float64, member string) *node {
    38  	n := &node{
    39  		Element: Element{
    40  			Score:  score,
    41  			Member: member,
    42  		},
    43  		level: make([]*Level, level),
    44  	}
    45  	for i := range n.level {
    46  		n.level[i] = new(Level)
    47  	}
    48  	return n
    49  }
    50  
    51  func makeSkiplist() *skiplist {
    52  	return &skiplist{
    53  		level:  1,
    54  		header: makeNode(maxLevel, 0, ""),
    55  	}
    56  }
    57  
    58  func randomLevel() int16 {
    59  	total := uint64(1)<<uint64(maxLevel) - 1
    60  	k := rand.Uint64() % total
    61  	return maxLevel - int16(bits.Len64(k+1)) + 1
    62  }
    63  
    64  func (skiplist *skiplist) insert(member string, score float64) *node {
    65  	update := make([]*node, maxLevel) // link new node with node in `update`
    66  	rank := make([]int64, maxLevel)
    67  
    68  	// find position to insert
    69  	node := skiplist.header
    70  	for i := skiplist.level - 1; i >= 0; i-- {
    71  		if i == skiplist.level-1 {
    72  			rank[i] = 0
    73  		} else {
    74  			rank[i] = rank[i+1] // store rank that is crossed to reach the insert position
    75  		}
    76  		if node.level[i] != nil {
    77  			// traverse the skip list
    78  			for node.level[i].forward != nil &&
    79  				(node.level[i].forward.Score < score ||
    80  					(node.level[i].forward.Score == score && node.level[i].forward.Member < member)) { // same score, different key
    81  				rank[i] += node.level[i].span
    82  				node = node.level[i].forward
    83  			}
    84  		}
    85  		update[i] = node
    86  	}
    87  
    88  	level := randomLevel()
    89  	// extend skiplist level
    90  	if level > skiplist.level {
    91  		for i := skiplist.level; i < level; i++ {
    92  			rank[i] = 0
    93  			update[i] = skiplist.header
    94  			update[i].level[i].span = skiplist.length
    95  		}
    96  		skiplist.level = level
    97  	}
    98  
    99  	// make node and link into skiplist
   100  	node = makeNode(level, score, member)
   101  	for i := int16(0); i < level; i++ {
   102  		node.level[i].forward = update[i].level[i].forward
   103  		update[i].level[i].forward = node
   104  
   105  		// update span covered by update[i] as node is inserted here
   106  		node.level[i].span = update[i].level[i].span - (rank[0] - rank[i])
   107  		update[i].level[i].span = (rank[0] - rank[i]) + 1
   108  	}
   109  
   110  	// increment span for untouched levels
   111  	for i := level; i < skiplist.level; i++ {
   112  		update[i].level[i].span++
   113  	}
   114  
   115  	// set backward node
   116  	if update[0] == skiplist.header {
   117  		node.backward = nil
   118  	} else {
   119  		node.backward = update[0]
   120  	}
   121  	if node.level[0].forward != nil {
   122  		node.level[0].forward.backward = node
   123  	} else {
   124  		skiplist.tail = node
   125  	}
   126  	skiplist.length++
   127  	return node
   128  }
   129  
   130  /*
   131   * param node: node to delete
   132   * param update: backward node (of target)
   133   */
   134  func (skiplist *skiplist) removeNode(node *node, update []*node) {
   135  	for i := int16(0); i < skiplist.level; i++ {
   136  		if update[i].level[i].forward == node {
   137  			update[i].level[i].span += node.level[i].span - 1
   138  			update[i].level[i].forward = node.level[i].forward
   139  		} else {
   140  			update[i].level[i].span--
   141  		}
   142  	}
   143  	if node.level[0].forward != nil {
   144  		node.level[0].forward.backward = node.backward
   145  	} else {
   146  		skiplist.tail = node.backward
   147  	}
   148  	for skiplist.level > 1 && skiplist.header.level[skiplist.level-1].forward == nil {
   149  		skiplist.level--
   150  	}
   151  	skiplist.length--
   152  }
   153  
   154  /*
   155   * return: has found and removed node
   156   */
   157  func (skiplist *skiplist) remove(member string, score float64) bool {
   158  	/*
   159  	 * find backward node (of target) or last node of each level
   160  	 * their forward need to be updated
   161  	 */
   162  	update := make([]*node, maxLevel)
   163  	node := skiplist.header
   164  	for i := skiplist.level - 1; i >= 0; i-- {
   165  		for node.level[i].forward != nil &&
   166  			(node.level[i].forward.Score < score ||
   167  				(node.level[i].forward.Score == score &&
   168  					node.level[i].forward.Member < member)) {
   169  			node = node.level[i].forward
   170  		}
   171  		update[i] = node
   172  	}
   173  	node = node.level[0].forward
   174  	if node != nil && score == node.Score && node.Member == member {
   175  		skiplist.removeNode(node, update)
   176  		// free x
   177  		return true
   178  	}
   179  	return false
   180  }
   181  
   182  /*
   183   * return: 1 based rank, 0 means member not found
   184   */
   185  func (skiplist *skiplist) getRank(member string, score float64) int64 {
   186  	var rank int64 = 0
   187  	x := skiplist.header
   188  	for i := skiplist.level - 1; i >= 0; i-- {
   189  		for x.level[i].forward != nil &&
   190  			(x.level[i].forward.Score < score ||
   191  				(x.level[i].forward.Score == score &&
   192  					x.level[i].forward.Member <= member)) {
   193  			rank += x.level[i].span
   194  			x = x.level[i].forward
   195  		}
   196  
   197  		/* x might be equal to zsl->header, so test if obj is non-NULL */
   198  		if x.Member == member {
   199  			return rank
   200  		}
   201  	}
   202  	return 0
   203  }
   204  
   205  /*
   206   * 1-based rank
   207   */
   208  func (skiplist *skiplist) getByRank(rank int64) *node {
   209  	var i int64 = 0
   210  	n := skiplist.header
   211  	// scan from top level
   212  	for level := skiplist.level - 1; level >= 0; level-- {
   213  		for n.level[level].forward != nil && (i+n.level[level].span) <= rank {
   214  			i += n.level[level].span
   215  			n = n.level[level].forward
   216  		}
   217  		if i == rank {
   218  			return n
   219  		}
   220  	}
   221  	return nil
   222  }
   223  
   224  func (skiplist *skiplist) hasInRange(min *ScoreBorder, max *ScoreBorder) bool {
   225  	// min & max = empty
   226  	if min.Value > max.Value || (min.Value == max.Value && (min.Exclude || max.Exclude)) {
   227  		return false
   228  	}
   229  	// min > tail
   230  	n := skiplist.tail
   231  	if n == nil || !min.less(n.Score) {
   232  		return false
   233  	}
   234  	// max < head
   235  	n = skiplist.header.level[0].forward
   236  	if n == nil || !max.greater(n.Score) {
   237  		return false
   238  	}
   239  	return true
   240  }
   241  
   242  func (skiplist *skiplist) getFirstInScoreRange(min *ScoreBorder, max *ScoreBorder) *node {
   243  	if !skiplist.hasInRange(min, max) {
   244  		return nil
   245  	}
   246  	n := skiplist.header
   247  	// scan from top level
   248  	for level := skiplist.level - 1; level >= 0; level-- {
   249  		// if forward is not in range than move forward
   250  		for n.level[level].forward != nil && !min.less(n.level[level].forward.Score) {
   251  			n = n.level[level].forward
   252  		}
   253  	}
   254  	/* This is an inner range, so the next node cannot be NULL. */
   255  	n = n.level[0].forward
   256  	if !max.greater(n.Score) {
   257  		return nil
   258  	}
   259  	return n
   260  }
   261  
   262  func (skiplist *skiplist) getLastInScoreRange(min *ScoreBorder, max *ScoreBorder) *node {
   263  	if !skiplist.hasInRange(min, max) {
   264  		return nil
   265  	}
   266  	n := skiplist.header
   267  	// scan from top level
   268  	for level := skiplist.level - 1; level >= 0; level-- {
   269  		for n.level[level].forward != nil && max.greater(n.level[level].forward.Score) {
   270  			n = n.level[level].forward
   271  		}
   272  	}
   273  	if !min.less(n.Score) {
   274  		return nil
   275  	}
   276  	return n
   277  }
   278  
   279  /*
   280   * return removed elements
   281   */
   282  func (skiplist *skiplist) RemoveRangeByScore(min *ScoreBorder, max *ScoreBorder, limit int) (removed []*Element) {
   283  	update := make([]*node, maxLevel)
   284  	removed = make([]*Element, 0)
   285  	// find backward nodes (of target range) or last node of each level
   286  	node := skiplist.header
   287  	for i := skiplist.level - 1; i >= 0; i-- {
   288  		for node.level[i].forward != nil {
   289  			if min.less(node.level[i].forward.Score) { // already in range
   290  				break
   291  			}
   292  			node = node.level[i].forward
   293  		}
   294  		update[i] = node
   295  	}
   296  
   297  	// node is the first one within range
   298  	node = node.level[0].forward
   299  
   300  	// remove nodes in range
   301  	for node != nil {
   302  		if !max.greater(node.Score) { // already out of range
   303  			break
   304  		}
   305  		next := node.level[0].forward
   306  		removedElement := node.Element
   307  		removed = append(removed, &removedElement)
   308  		skiplist.removeNode(node, update)
   309  		if limit > 0 && len(removed) == limit {
   310  			break
   311  		}
   312  		node = next
   313  	}
   314  	return removed
   315  }
   316  
   317  // 1-based rank, including start, exclude stop
   318  func (skiplist *skiplist) RemoveRangeByRank(start int64, stop int64) (removed []*Element) {
   319  	var i int64 = 0 // rank of iterator
   320  	update := make([]*node, maxLevel)
   321  	removed = make([]*Element, 0)
   322  
   323  	// scan from top level
   324  	node := skiplist.header
   325  	for level := skiplist.level - 1; level >= 0; level-- {
   326  		for node.level[level].forward != nil && (i+node.level[level].span) < start {
   327  			i += node.level[level].span
   328  			node = node.level[level].forward
   329  		}
   330  		update[level] = node
   331  	}
   332  
   333  	i++
   334  	node = node.level[0].forward // first node in range
   335  
   336  	// remove nodes in range
   337  	for node != nil && i < stop {
   338  		next := node.level[0].forward
   339  		removedElement := node.Element
   340  		removed = append(removed, &removedElement)
   341  		skiplist.removeNode(node, update)
   342  		node = next
   343  		i++
   344  	}
   345  	return removed
   346  }