Loading

[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))
}

posted @   Duancf  阅读(13)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
点击右上角即可分享
微信分享提示