github.com/qiuhoude/go-web@v0.0.0-20220223060959-ab545e78f20d/algorithm/datastructures/sikplist/sikplist.go (about)

     1  package sikplist
     2  
     3  import (
     4  	"fmt"
     5  	"math"
     6  	"math/rand"
     7  	"strings"
     8  )
     9  
    10  /*
    11  跳表
    12  时间复杂度
    13  
    14  1. 假设 每2个节点一个索引,最顶层索引是2, 有n个节点,每层最多遍历2+1=3个
    15  设 n 个节点 , h表示层数, m表示每层遍历的次数
    16  n/(2^h) = 2 => h = log2(n)-1
    17  所以复杂度是 O(m*(log2(n)-1)) m是个常数级别
    18  时间复杂度是 O(logn)
    19  
    20  每3个节点一个索引  O(m*(log3(n)-1)); m = 3+1
    21  
    22  空间复杂度
    23  2节点一索引: n/2 + n/4 + n/8 +... 等比数列 约等于  约等于 n
    24  所以空间复杂度 O(n)
    25  
    26  3节点一索引: n/3 + n/9 + n/27 +... 等比数列 约等于 约等于 n/2
    27  
    28  */
    29  const (
    30  	MaxLevel  = 16
    31  	SkiplistP = 0.5
    32  )
    33  
    34  //跳表节点结构体
    35  type skipListNode struct {
    36  	v        interface{}     // 数据
    37  	score    int             // 用于排序的分值
    38  	level    int             //层高
    39  	forwards []*skipListNode //每层前进指针
    40  }
    41  
    42  //新建跳表节点
    43  func newSkipListNode(v interface{}, score, level int) *skipListNode {
    44  	return &skipListNode{
    45  		v:        v,
    46  		score:    score,
    47  		forwards: make([]*skipListNode, level, level),
    48  		level:    level,
    49  	}
    50  }
    51  
    52  func (sln *skipListNode) String() string {
    53  	return fmt.Sprintf("[%v %v]", sln.v, sln.score)
    54  }
    55  
    56  // 跳表结构体
    57  type SkipList struct {
    58  	head   *skipListNode //跳表头结点
    59  	level  int           //跳表当前层数
    60  	length int           ///跳表长度
    61  }
    62  
    63  func NewSkipList() *SkipList {
    64  	// 头结点, 可以称为哨兵
    65  	head := newSkipListNode(nil, math.MinInt32, MaxLevel)
    66  	return &SkipList{head, 1, 0}
    67  }
    68  
    69  //获取跳表长度
    70  func (sl *SkipList) Length() int {
    71  	return sl.length
    72  }
    73  
    74  //获取跳表层级
    75  func (sl *SkipList) Level() int {
    76  	return sl.level
    77  }
    78  
    79  //插入节点到跳表中
    80  func (sl *SkipList) Insert(v interface{}, score int) int {
    81  	if v == nil {
    82  		return 1
    83  	}
    84  	//查找插入位置
    85  	cur := sl.head
    86  	//创建数组 记录每层的路径
    87  	update := [MaxLevel]*skipListNode{}
    88  	// 从最高层开始
    89  	for i := MaxLevel - 1; i >= 0; i-- {
    90  		for ; nil != cur.forwards[i]; cur = cur.forwards[i] { // 当前层进行查找
    91  			if cur.forwards[i].v == v || cur.v == v { // 插入的值相等
    92  				return 2
    93  			}
    94  			if cur.forwards[i].score > score { // 找到了
    95  				update[i] = cur
    96  				break
    97  			}
    98  		}
    99  		update[i] = cur
   100  	}
   101  
   102  	//通过随机算法获取该节点层数
   103  	level := sl.randomLevel()
   104  
   105  	//创建一个新的跳表节点
   106  	newNode := newSkipListNode(v, score, level)
   107  
   108  	//给每层插入新结点
   109  	for i := 0; i < level; i++ {
   110  		newNode.forwards[i] = update[i].forwards[i]
   111  		update[i].forwards[i] = newNode
   112  	}
   113  
   114  	//如果当前节点的层数大于之前跳表的层数
   115  	//更新当前跳表层数
   116  	if level > sl.level {
   117  		sl.level = level
   118  	}
   119  
   120  	//更新跳表长度
   121  	sl.length++
   122  	return 0
   123  }
   124  
   125  /*
   126  一级索引中元素个数应该占原始数据的 1/2,二级索引中元素个数占 1/4,三级索引 1/8 一直到最顶层。
   127   因为这里每一层的晋升概率是 50%。对于每一个新插入的节点,都需要调用 randomLevel 生成一个合理的层数。
   128  该 randomLevel 方法会随机生成 1~MAX_LEVEL 之间的数,
   129  	50%的概率返回 1
   130    	25%的概率返回 2
   131    	12.5%的概率返回 3 ...
   132  */
   133  func (sl *SkipList) randomLevel() int {
   134  	level := 1
   135  	for rand.Float32() < SkiplistP && level < MaxLevel {
   136  		level++
   137  	}
   138  	return level
   139  }
   140  
   141  //查找
   142  func (sl *SkipList) Find(v interface{}, score int) *skipListNode {
   143  	if nil == v || sl.length == 0 {
   144  		return nil
   145  	}
   146  	cur := sl.head
   147  	for i := sl.level - 1; i >= 0; i-- {
   148  		for ; nil != cur.forwards[i] && cur.forwards[i].score <= score; cur = cur.forwards[i] {
   149  			if cur.forwards[i].score == score && cur.forwards[i].v == v {
   150  				return cur.forwards[i]
   151  			}
   152  		}
   153  	}
   154  	return nil
   155  }
   156  
   157  // 范围查找
   158  func (sl *SkipList) FindRange(start, end int) []interface{} {
   159  	if sl.length == 0 || end < start {
   160  		return nil
   161  	}
   162  	cur := sl.head.forwards[sl.level-1]
   163  	for i := sl.level - 1; i >= 0; i-- {
   164  		for ; nil != cur; cur = cur.forwards[i] {
   165  			if cur.score >= start {
   166  				break
   167  			}
   168  		}
   169  	}
   170  	if cur != nil {
   171  		var ret []interface{}
   172  		for ; cur != nil && cur.score <= end; cur = cur.forwards[0] {
   173  			ret = append(ret, cur.v)
   174  		}
   175  		return ret
   176  	}
   177  	return nil
   178  }
   179  
   180  //删除节点
   181  func (sl *SkipList) Delete(v interface{}, score int) int {
   182  	if nil == v {
   183  		return 1
   184  	}
   185  	cur := sl.head
   186  	//记录前驱路径
   187  	update := [MaxLevel]*skipListNode{}
   188  	for i := sl.level - 1; i >= 0; i-- {
   189  		update[i] = sl.head // 默认是头结点开始
   190  		for ; nil != cur.forwards[i]; cur = cur.forwards[i] {
   191  			if cur.forwards[i].score == score && cur.forwards[i].v == v {
   192  				update[i] = cur
   193  				break
   194  			}
   195  		}
   196  	}
   197  
   198  	cur = update[0].forwards[0]
   199  	for i := cur.level - 1; i >= 0; i-- {
   200  		if update[i] == sl.head && cur.forwards[i] == nil { //当前层没有元素
   201  			sl.level = i
   202  		}
   203  
   204  		if nil == update[i].forwards[i] {
   205  			update[i].forwards[i] = nil
   206  		} else {
   207  			update[i].forwards[i] = update[i].forwards[i].forwards[i]
   208  		}
   209  	}
   210  
   211  	sl.length--
   212  	return 0
   213  }
   214  
   215  func (sl *SkipList) String() string {
   216  	var sb strings.Builder
   217  	sb.WriteString(fmt.Sprintf("level:%+v, length:%+v\n", sl.level, sl.length))
   218  	for i := MaxLevel - 1; i >= 0; i-- {
   219  		cur := sl.head.forwards[i]
   220  		if cur == nil {
   221  			continue
   222  		}
   223  		_, _ = fmt.Fprintf(&sb, "%v [head]->", i)
   224  		for ; cur != nil; cur = cur.forwards[i] {
   225  			_, _ = fmt.Fprintf(&sb, "[%v %v]->", cur.v, cur.score)
   226  		}
   227  		sb.WriteString("nil\n")
   228  	}
   229  	return sb.String()
   230  }