github.com/zhiqiangxu/util@v0.0.0-20230112053021-0a7aee056cd5/skl/skl.go (about)

     1  package skl
     2  
     3  import (
     4  	"math"
     5  
     6  	"github.com/zhiqiangxu/util"
     7  )
     8  
     9  const (
    10  	// DefaultMaxLevel for skl
    11  	DefaultMaxLevel int = 18
    12  	// DefaultProbability for skl
    13  	DefaultProbability float64 = 1 / math.E
    14  )
    15  
    16  type link struct {
    17  	next *element
    18  }
    19  
    20  type element struct {
    21  	links []link
    22  	key   int64
    23  	value interface{}
    24  }
    25  
    26  type skl struct {
    27  	links          []link
    28  	maxLevel       int
    29  	length         int
    30  	probability    float64
    31  	probTable      []uint32
    32  	prevLinksCache []*link
    33  }
    34  
    35  // NewSkipList creates a new SkipList
    36  func NewSkipList() SkipList {
    37  	return NewSkipListWithMaxLevel(DefaultMaxLevel)
    38  }
    39  
    40  // NewSkipListWithMaxLevel creates a new SkipList with specified maxLevel
    41  func NewSkipListWithMaxLevel(maxLevel int) SkipList {
    42  	return &skl{
    43  		links:          make([]link, maxLevel),
    44  		maxLevel:       maxLevel,
    45  		probability:    DefaultProbability,
    46  		probTable:      probabilityTable(DefaultProbability, maxLevel),
    47  		prevLinksCache: make([]*link, maxLevel),
    48  	}
    49  }
    50  
    51  func probabilityTable(probability float64, maxLevel int) (table []uint32) {
    52  	for i := 0; i < maxLevel; i++ {
    53  		prob := math.Pow(probability, float64(i))
    54  		table = append(table, uint32(prob*math.MaxUint32))
    55  	}
    56  	return table
    57  }
    58  
    59  func (s *skl) Add(key int64, value interface{}) {
    60  	// prev := s.links
    61  	// for i := s.maxLevel - 1; i >= 0; i-- {
    62  	// 	s.findSpliceForLevel(key, prev, i)
    63  	// }
    64  
    65  	prevs := s.getPrevLinks(key)
    66  	ele := prevs[0].next
    67  	if ele != nil && ele.key <= key {
    68  		ele.value = value
    69  		return
    70  	}
    71  
    72  	ele = &element{
    73  		links: make([]link, s.randLevel()),
    74  		key:   key,
    75  		value: value,
    76  	}
    77  
    78  	for i := range ele.links {
    79  		ele.links[i].next = prevs[i].next
    80  		prevs[i].next = ele
    81  	}
    82  
    83  	s.length++
    84  }
    85  
    86  func (s *skl) Length() int {
    87  	return s.length
    88  }
    89  
    90  func (s *skl) randLevel() (level int) {
    91  
    92  	r := util.FastRand()
    93  
    94  	level = 1
    95  	for level < s.maxLevel && r < s.probTable[level] {
    96  		level++
    97  	}
    98  	return
    99  }
   100  
   101  // 找到每一层上毗邻于该key对应元素之前的links
   102  // 返回的是*link,所以可以原地更新
   103  func (s *skl) getPrevLinks(key int64) []*link {
   104  	var prev = s.links
   105  	var current *element
   106  
   107  	prevs := s.prevLinksCache
   108  	for i := s.maxLevel - 1; i >= 0; i-- {
   109  		current = prev[i].next
   110  
   111  		for current != nil && current.key < key {
   112  			prev = current.links
   113  			current = prev[i].next
   114  		}
   115  
   116  		prevs[i] = &prev[i]
   117  	}
   118  
   119  	return prevs
   120  }
   121  
   122  // func (s *skl) findSpliceForLevel(key int64, prev []link, level0based int) (before, next *element) {
   123  
   124  // 	current := prev[level0based].next
   125  // 	for current != nil && current.key < key {
   126  // 		prev = current.links
   127  // 		current = prev[level0based].next
   128  // 	}
   129  
   130  // 	before = &prev[level0based]
   131  
   132  // 	if current != nil {
   133  // 		if current.key == key {
   134  // 			next = before
   135  // 		} else {
   136  // 			next = &current.links[level0based]
   137  // 		}
   138  // 	}
   139  
   140  // 	return
   141  // }
   142  
   143  func (s *skl) Get(key int64) (value interface{}, ok bool) {
   144  	prev := s.links
   145  	var current *element
   146  	for i := s.maxLevel - 1; i >= 0; i-- {
   147  		current = prev[i].next
   148  		for current != nil && current.key < key {
   149  			prev = current.links
   150  			current = current.links[i].next
   151  		}
   152  	}
   153  
   154  	if current != nil && current.key <= key {
   155  		return current.value, true
   156  	}
   157  
   158  	return nil, false
   159  }
   160  
   161  func (s *skl) Remove(key int64) {
   162  	prevs := s.getPrevLinks(key)
   163  	if ele := prevs[0].next; ele != nil && ele.key <= key {
   164  
   165  		for i, l := range ele.links {
   166  			prevs[i].next = l.next
   167  		}
   168  		s.length--
   169  	}
   170  }
   171  
   172  func (s *skl) Head() (key int64, value interface{}, ok bool) {
   173  	nele := s.links[0].next
   174  	if nele != nil {
   175  		key = nele.key
   176  		value = nele.value
   177  		ok = true
   178  	}
   179  	return
   180  }
   181  
   182  func (s *skl) NewIterator() SkipListIterator {
   183  	return &sklIter{s: s}
   184  }