[Golang扩展]手写Golang跳表
package SkipList
import (
"fmt"
"math/rand"
)
const MaxLevel = 10
type Node struct {
score int
value string
next []*Node
}
func NewNode(score int, value string, level int) *Node {
node := Node{score: score, value: value, next: make([]*Node, level)}
return &node
}
type SkipList struct {
level int
len int
head Node
}
func NewSkipList() *SkipList {
sl := SkipList{}
sl.level = 1
sl.head.next = make([]*Node, MaxLevel)
return &sl
}
func (sl *SkipList) Show() {
fmt.Println("show skipList ----------------")
for i := sl.level - 1; i >= 0; i-- {
fmt.Printf("level %d: ", i+1)
cur := sl.head.next[i]
for cur != nil {
fmt.Print(cur.score, cur.value)
cur = cur.next[i]
if cur != nil {
fmt.Print("->")
}
}
fmt.Println()
}
}
func (sl *SkipList) Insert(score int, value string) {
fmt.Println("插入节点", score, value)
prev := &sl.head
breakPoints := make([]*Node, sl.level)
for i := sl.level - 1; i >= 0; i-- {
for cur := prev.next[i]; cur != nil; cur = cur.next[i] {
if cur.score == score {
cur.value = value
fmt.Println("有重复score,直接覆盖", score, value)
return
} else if cur.score > score {
break
} else {
prev = cur
}
}
breakPoints[i] = prev
}
// 生成新结点层级
randomLevel := MaxLevel
randomNumber := rand.Intn(1 << MaxLevel)
for i := 1; i <= MaxLevel; i++ {
if randomNumber >= 1<<(MaxLevel-i) {
randomLevel = i
break
}
}
if randomLevel > sl.level {
randomLevel = sl.level + 1
}
fmt.Println("新节点层级 = ", randomLevel)
newNode := NewNode(score, value, randomLevel)
if randomLevel > sl.level {
for i := 0; i < sl.level; i++ {
newNode.next[i] = breakPoints[i].next[i]
breakPoints[i].next[i] = newNode
}
sl.head.next[randomLevel-1] = newNode
sl.level += 1
} else {
for i := 0; i < randomLevel; i++ {
newNode.next[i] = breakPoints[i].next[i]
breakPoints[i].next[i] = newNode
}
}
}
func (sl *SkipList) FindByScore(score int) string {
prev := &sl.head
for i := sl.level - 1; i >= 0; i-- {
for cur := prev.next[i]; cur != nil; cur = cur.next[i] {
if cur.score == score {
return cur.value
} else if cur.score > score {
break
} else {
prev = cur
}
}
}
return ""
}
func (sl *SkipList) FindByValue(value string) int {
for cur := sl.head.next[0]; cur != nil; cur = cur.next[0] {
if cur.value == value {
return cur.score
}
}
return -1
}
func (sl *SkipList) RemoveByScore(score int) {
fmt.Println("删除节点score", score)
deletePoints := make([]*Node, sl.level)
prev := &sl.head
for i := sl.level - 1; i >= 0; i-- {
for cur := prev.next[i]; cur != nil; cur = cur.next[i] {
if cur.score < score {
prev = cur
}
}
deletePoints[i] = prev
}
for i := 0; i < sl.level; i++ {
if deletePoints[i].next[i] != nil && deletePoints[i].next[i].score == score {
deletePoints[i].next[i] = deletePoints[i].next[i].next[i]
}
}
}
func (sl *SkipList) RemoveByValue(value string) {
deletePoints := make([]*Node, sl.level)
for i := sl.level - 1; i >= 0; i-- {
for cur := sl.head.next[i]; cur.next[i] != nil; cur = cur.next[i] {
if cur.next[i].value == value {
deletePoints[i] = cur
}
}
}
for i := 0; i < sl.level; i++ {
if deletePoints[i] != nil {
deletePoints[i].next[i] = deletePoints[i].next[i].next[i]
}
}
}
func (sl *SkipList) RangeSearch(start, end int) []string {
if start > end {
fmt.Println("非法范围,起点大于终点")
return []string{}
}
prev := &sl.head
for i := sl.level - 1; i >= 0; i-- {
for cur := prev.next[i]; cur != nil; cur = cur.next[i] {
if cur.score < start {
prev = cur
}
}
}
var res []string
for cur := prev.next[0]; cur != nil && cur.score <= end; cur = cur.next[0] {
res = append(res, cur.value)
}
return res
}
Test
func TestNewSkipList(t *testing.T) {
sl := SkipList.NewSkipList()
sl.Insert(4, "D")
sl.Insert(5, "E")
sl.Insert(6, "F")
sl.Insert(1, "A")
sl.Insert(2, "B")
sl.Insert(3, "C")
sl.Show()
fmt.Println(sl.RangeSearch(5, 5))
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义