gocache/skiptable.go

133 lines
26 KiB
Go
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package main
import (
"fmt"
"math/rand"
"time"
)
const (
maxLevel = 32 // 最大层数
probability = 0.5 // 层数生成概率因子
)
// SkipNode 跳表节点结构
type SkipNode struct {
key int
value interface{}
forward []*SkipNode // 各层的前进指针
}
// NewSkipNode 创建新节点
func NewSkipNode(key int, value interface{}, level int) *SkipNode {
return &SkipNode{
key: key,
value: value,
forward: make([]*SkipNode, level),
}
}
// SkipList 跳表结构
type SkipList struct {
header *SkipNode // 头节点
level int // 当前最大层数
randSrc rand.Source // 随机数源
}
// NewSkipList 初始化跳表
func NewSkipList() *SkipList {
return &SkipList{
header: NewSkipNode(0, nil, maxLevel),
level: 1,
randSrc: rand.NewSource(time.Now().UnixNano()),
}
}
// randomLevel 生成随机层数 (抛硬币法)
func (sl *SkipList) randomLevel() int {
level := 1
for ; level < maxLevel && sl.randSrc.Int63()&0xFFFF < int64(probability*0xFFFF); level++ {
}
return level
}
// Search 查找键对应的值
func (sl *SkipList) Search(key int) (interface{}, bool) {
current := sl.header
// 从最高层开始查找
for i := sl.level - 1; i >= 0; i-- {
// 在当前层向右移动直到找到大于等于key的节点
for current.forward[i] != nil && current.forward[i].key < key {
current = current.forward[i]
}
}
// 移动到最底层(0层)的下一个节点
current = current.forward[0]
if current != nil && current.key == key {
return current.value, true
}
return nil, false
}
// Insert 插入键值对
func (sl *SkipList) Insert(key int, value interface{}) {
update := make([]*SkipNode, maxLevel) // 各层需要更新的前驱节点
current := sl.header
// 1. 查找各层的前驱节点
for i := sl.level - 1; i >= 0; i-- {
for current.forward[i] != nil && current.forward[i].key < key {
current = current.forward[i]
}
update[i] = current
}
// 2. 检查是否已存在相同key
current = current.forward[0]
if current != nil && current.key == key {
current.value = value // 更新值
return
}
// 3. 生成新节点的随机层数
newLevel := sl.randomLevel()
if newLevel > sl.level {
// 补充高层的前驱节点为header
for i := sl.level; i < newLevel; i++ {
update[i] = sl.header
}
sl.level = newLevel
}
// 4. 创建新节点并插入各层
newNode := NewSkipNode(key, value, newLevel)
for i := 0; i < newLevel; i++ {
newNode.forward[i] = update[i].forward[i]
update[i].forward[i] = newNode
}
}
// Delete 删除指定键的节点
func (sl *SkipList) Delete(key int) bool {
update := make([]*SkipNode, maxLevel)
current := sl.header
// 1. 查找各层的前驱节点
for i := sl.level - 1; i >= 0; i-- {
for current.forward[i] != nil && current.forward[i].key < key {
current = current.forward[i]
}
update[i] = current
}
// 2. 定位到目标节点
current = current.forward[0]
if current == nil || current.key != key {
return false // 未找到
}
// 3. 从各层链表中移除
for i := 0; i < sl.level; i++ {
if update[i].forward[i] != current {
break // 上层已