跳表SkipList(go语言实现)

本文介绍了一个开源的Go语言实现的并发跳表(ConcurrentSkipList)。跳表由多个skipList组成,每个skipList包含头结点、尾节点、高度和长度,并使用读写锁确保并发安全性。每个节点包含索引值、值和指向下一个节点的指针。
摘要由CSDN通过智能技术生成

网上找到一个开源的代码

https://github.com/AceDarkknight/ConcurrentSkipList

数据结构

我们用 ConcurrentSkipList 这个数据结构代表整个 skip list,可以看到里面是一个包含多个 skipList 的切片。

// ConcurrentSkipList is a struct contains a slice of concurrent skip list.
type ConcurrentSkipList struct {
	skipLists []*skipList
	level     int
}

skipList 的结构如下, 每个 skipList 除了有头结点、尾节点、高度、长度外都有一把读写锁,负责保证并发安全。

type skipList struct {
	level  int
	length int32
	head   *Node
	tail   *Node
	mutex  sync.RWMutex
}

其中我们把每个节点称为一个 Node,Node 的结构如下,index 代表节点的索引值,value 代表节点的值,nextNodes 记录了该节点指向的下个节点。

type Node struct {
	index     uint64
	value     interface{}
	nextNodes []*Node
}

concurrentSkipList.go源文件

/*
Package ConcurrentSkipList provide an implementation of skip list. It's thread-safe in concurrency and high performance.
*/
package ConcurrentSkipList

import (
	"errors"
	"math"
	"sync/atomic"

	"github.com/OneOfOne/xxhash"
)

// Comes from redis's implementation.
// Also you can see more detail in William Pugh's paper <Skip Lists: A Probabilistic Alternative to Balanced Trees>.
// The paper is in ftp://ftp.cs.umd.edu/pub/skipLists/skiplists.pdf
const (
	MAX_LEVEL   = 32
	PROBABILITY = 0.25
	SHARDS      = 32
)

// shardIndex is used to indicate which shard a given index belong to.
var shardIndexes = make([]uint64, SHARDS)

// init will initialize the shardIndexes.
func init() {
	var step uint64 = 1 << 59 // 2^64/SHARDS
	var t uint64 = math.MaxUint64

	for i := SHARDS - 1; i >= 0; i-- {
		shardIndexes[i] = t
		t -= step
	}
}

// ConcurrentSkipList is a struct contains a slice of concurrent skip list.
type ConcurrentSkipList struct {
	skipLists []*skipList
	level     int
}

// NewConcurrentSkipList will create a new concurrent skip list with given level.
// Level must between 1 to 32. If not, will return an error.
// To determine the level, you can see the paper ftp://ftp.cs.umd.edu/pub/skipLists/skiplists.pdf.
// A simple way to determine the level is L(N) = log(1/PROBABILITY)(N).
// N is the count of the skip list which you can estimate. PROBABILITY is 0.25 in this case.
// For example, if you expect the skip list contains 10000000 elements, then N = 10000000, L(N) ≈ 12.
// After initialization, the head field's level equal to level parameter and point to tail field.
func NewConcurren
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值