1.levelDB 跳跃表
(图1)
每个节点包含 keyValue 与 对应的层高,每个hx 记录下一个节点的位置。在 levelDB 中,节点位置(nodeData)与数据(kvData)是分开存储的,所以 keyValue 实际存储的是该键值对在 kvData 中的偏移量 offset。
2.nodeData 数据结构
(图2)
offset: key-value在kvData的起始位置
klen: key字节长度
vlen::value字节长度
hlen:节点的高度
3.kvData 数据结构
(图3)
4.将图 (1) 转换为具体 nodeData 和 kvData
(图4)
5.代码实现
package main
import (
"bytes"
"errors"
"fmt"
"math/rand"
)
const (
nKV = iota
nKey
nVal
nHeight
nNext
)
const tMaxHeight = 12 //最大高度
type SkipList struct {
rnd *rand.Rand
kvData []byte
nodeData []int
prevNode [tMaxHeight]int
//用于在遍历skiplist的时候,保存每一层的前一个节点,用于插入很更新
//如果某层有元素 a,b,c,e。 当插入元素d是, 该层的prevNode 就是 c。
//插入数据时(d), d.next = c.next, c.next = d
//删除数据时(d), c.next = d.next
maxHeight int // skiplist的层高
}
func SimpleSkipList() {
//初始化
sk := &SkipList{
rnd: rand.New(rand.NewSource(0xdeadbeef)),
kvData: make([]byte,0),
nodeData: make([]int,nNext+tMaxHeight),
prevNode: [tMaxHeight]int{},
maxHeight: 1,
}
sk.nodeData[nKV] = 0 //offset
sk.nodeData[nKey] = 0 //keylen
sk.nodeData[nVal] = 0 //vallen
sk.nodeData[nHeight] = tMaxHeight //height
for n := 0; n < tMaxHeight; n++ {
sk.nodeData[nNext+n] = 0
sk.prevNode[n] = 0
}
//添加元素
sk.Put([]byte("a"),[]byte("a1"))
//获取key的value
//v,_ := sk.Get([]byte("a"))
//更新
sk.Put([]byte("a"),[]byte("a11"))
//添加
sk.Put([]byte("b"),[]byte("b1"))
sk.Put([]byte("c"),[]byte("c1"))
//删除
sk.Delete([]byte("a"))
}
//添加元素
func (sk *SkipList) Put(key []byte, value []byte) error {
node,exact := sk.findGE(key,true) //判断是否存在元素
if exact { //修改元素,只追加不修改
offset := len(sk.kvData)
sk.kvData = append(sk.kvData,key...)
sk.kvData = append(sk.kvData,value...)
sk.nodeData[node] = offset
sk.nodeData[node+nVal] = len(value)
return nil
}
h := sk.randHeight() //随机选择一个高度
if h>sk.maxHeight {
for i:=sk.maxHeight; i<h ;i++ {
sk.prevNode[i] = 0
}
sk.maxHeight = h
}
offset := len(sk.kvData)
sk.kvData = append(sk.kvData,key...)
sk.kvData = append(sk.kvData,value...)
node = len(sk.nodeData)
sk.nodeData = append(sk.nodeData,offset,len(key),len(value),h)
for i,n := range sk.prevNode[:h] {
m := n+nNext+i
sk.nodeData = append(sk.nodeData, sk.nodeData[m])
sk.nodeData[m] = node
}
return nil
}
func (sk *SkipList) Delete(key []byte) error {
node, exact := sk.findGE(key,true)
if !exact {
return errors.New("NOT FOUND")
}
h := sk.nodeData[node+nHeight]
for i:=0;i<h;i++ {
preNode := sk.prevNode[i]
sk.nodeData[preNode+nNext+i] = sk.nodeData[node+nNext+i]
}
return nil
}
func (sk *SkipList) findGE(key []byte, pre bool) (int, bool) {
node := 0
h := sk.maxHeight-1 //层高
for {
next := sk.nodeData[node+nNext+h]
cmp := 1
if next != 0 {
offset := sk.nodeData[next]
keyLen := sk.nodeData[next+nKey]
o := sk.kvData[offset:offset+keyLen]
cmp = bytes.Compare(o,key)
}
if cmp < 0 { //节点key<指定key 沿着当前层走到next节点
node = next
} else {
if pre {//对于插入或者删除而进行的搜索,即使遇到相同的也要继续往下层比较
sk.prevNode[h] = node //记录前一个节点
} else if cmp == 0 {
return next,true
}
if h == 0 {
return next, cmp == 0
}
h--
}
}
}
func (sk *SkipList) Get(key []byte) (value []byte, err error) {
node, exact := sk.findGE(key,true)
if !exact {
return nil, errors.New("NOT FOUND")
}
pos := sk.nodeData[node]
return sk.kvData[pos+nKey:pos+nKey+nVal],nil
}
func (sk *SkipList) randHeight() (h int) {
return rand.Intn(5)
const branching = 4
h = 1
for h < tMaxHeight && sk.rnd.Int()%branching == 0 {
h++
}
return
}