实现 redis 跳表可以按照以下步骤:
- 定义数据结构
SkipList
,包含节点修建的Level
数组。
type SkipList struct {
Header *SkipListNode
Level int
}
type SkipListNode struct {
Key int
Value interface{}
Level []*SkipListNode
}
- 初始化跳表,将头节点和
Level
数组初始化。Level
数组用于记录每个节点在哪些层有后继节点。
func NewSkipListWithLevel(level int) *SkipList {
header := &SkipListNode{
Key: math.MinInt32,
Value: nil,
Level: make([]*SkipListNode, level),
}
return &SkipList{
Header: header,
Level: level,
}
}
- 插入节点,从最高层开始逐层寻找插入位置,将新节点插入其中。
func (list *SkipList) Insert(key int, value interface{}) {
node := &SkipListNode{
Key: key,
Value: value,
Level: make([]*SkipListNode, list.randomLevel()),
}
// 找到每层需要插入的位置
update := make([]*SkipListNode, list.Level)
x := list.Header
for i := list.Level - 1; i >= 0; i-- {
for x.Level[i] != nil && x.Level[i].Key < key {
x = x.Level[i]
}
update[i] = x
}
// 插入节点到每层
for i := 0; i < len(node.Level); i++ {
node.Level[i] = update[i].Level[i]
update[i].Level[i] = node
}
}
- 删除节点,和插入节点类似,先找到每层需要删除的位置,然后逐层删除。
func (list *SkipList) Delete(key int) bool {
// 找到每层需要删除的位置
update := make([]*SkipListNode, list.Level)
x := list.Header
for i := list.Level - 1; i >= 0; i-- {
for x.Level[i] != nil && x.Level[i].Key < key {
x = x.Level[i]
}
update[i] = x
}
// 删除节点
if x.Level[0] != nil && x.Level[0].Key == key {
for i := 0; i < list.Level; i++ {
if update[i].Level[i] != nil && update[i].Level[i].Key == key {
update[i].Level[i] = update[i].Level[i].Level[i]
}
}
return true
}
return false
}
- 搜索节点,从最高层开始逐层查找。
func (list *SkipList) Search(key int) interface{} {
x := list.Header
for i := list.Level - 1; i >= 0; i-- {
for x.Level[i] != nil && x.Level[i].Key < key {
x = x.Level[i]
}
}
if x.Level[0] != nil && x.Level[0].Key == key {
return x.Level[0].Value
}
return nil
}
完整实现代码如下:
package skiplist
import (
"math"
"math/rand"
)
type SkipList struct {
Header *SkipListNode
Level int
}
type SkipListNode struct {
Key int
Value interface{}
Level []*SkipListNode
}
func NewSkipListWithLevel(level int) *SkipList {
header := &SkipListNode{
Key: math.MinInt32,
Value: nil,
Level: make([]*SkipListNode, level),
}
return &SkipList{
Header: header,
Level: level,
}
}
func (list *SkipList) randomLevel() int {
level := 1
for rand.Float32() < 0.5 && level < list.Level {
level++
}
return level
}
func (list *SkipList) Insert(key int, value interface{}) {
node := &SkipListNode{
Key: key,
Value: value,
Level: make([]*SkipListNode, list.randomLevel()),
}
// 找到每层需要插入的位置
update := make([]*SkipListNode, list.Level)
x := list.Header
for i := list.Level - 1; i >= 0; i-- {
for x.Level[i] != nil && x.Level[i].Key < key {
x = x.Level[i]
}
update[i] = x
}
// 插入节点到每层
for i := 0; i < len(node.Level); i++ {
node.Level[i] = update[i].Level[i]
update[i].Level[i] = node
}
}
func (list *SkipList) Delete(key int) bool {
// 找到每层需要删除的位置
update := make([]*SkipListNode, list.Level)
x := list.Header
for i := list.Level - 1; i >= 0; i-- {
for x.Level[i] != nil && x.Level[i].Key < key {
x = x.Level[i]
}
update[i] = x
}
// 删除节点
if x.Level[0] != nil && x.Level[0].Key == key {
for i := 0; i < list.Level; i++ {
if update[i].Level[i] != nil && update[i].Level[i].Key == key {
update[i].Level[i] = update[i].Level[i].Level[i]
}
}
return true
}
return false
}
func (list *SkipList) Search(key int) interface{} {
x := list.Header
for i := list.Level - 1; i >= 0; i-- {
for x.Level[i] != nil && x.Level[i].Key < key {
x = x.Level[i]
}
}
if x.Level[0] != nil && x.Level[0].Key == key {
return x.Level[0].Value
}
return nil
}
使用跳表的示例:
package main
import (
"fmt"
"skiplist"
)
func main() {
list := skiplist.NewSkipListWithLevel(4)
list.Insert(1, "one")
list.Insert(2, "two")
list.Insert(3, "three")
list.Insert(4, "four")
list.Insert(5, "five")
fmt.Println(list.Search(3)) // output: three
fmt.Println(list.Search(6)) // output: nil
list.Delete(3)
fmt.Println(list.Search(3)) // output: nil
}