添加skiptable
This commit is contained in:
parent
9e4a26aac6
commit
58f3bda481
|
@ -0,0 +1,133 @@
|
|||
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 // 上层已
|
||||
|
Loading…
Reference in New Issue