顺序数组可以使用二分法快速搜索到元素,但是顺序链表需要遍历才能找到相应元素。插入、删除同理,跳表可以对链表进行优化,使得插入、查找、删除的时间复杂度都为nlogn,其原理在于使用多级索引
参考:数据结构之跳表
golang 实现:
package main
import (
"fmt"
"math/rand"
"time"
)
type List interface {
Insert(data int)
Delete(data int) bool
Search(data int)
}
type SkipList struct {
maxLevel int // 最大层数
head *Node // 开始结点
level int // 当前层数
}
type Node struct {
Data int // 值
Next []*Node // 下一个结点 Next[1] 第一层的下一结点 Next[2] 第二层的下一节点
}
func NewSkipList(maxLevel int) *SkipList {
headNode := new(Node)
headNode.Next = make([]*Node, maxLevel)
return &SkipList{
maxLevel: maxLevel,
head: headNode,
level: 1, // 初始化为1层
}
}
func NewNode(level int, data int) *Node {
return &Node{
Data: data,
Next: make([]*Node, level),
}
}
func init() {
rand.Seed(time.Now().UnixNano())
}
// 获取随机层数
func (sl *SkipList) randomLevel() int {
level := 1
if rand.Float32() < 0.5 && level < sl.maxLevel {
level++
}
return level
}
func (sl *SkipList) Insert(data int) {
update := make([]*Node, sl.maxLevel) // 每层插入结点的前一个结点
// 找到插入的位置
node := sl.head
for level := sl.maxLevel; level > 0; level-- {
for node.Next != nil && node.Next[level-1] != nil && node.Next[level-1].Data < data {
node = node.Next[level-1]
}
update[level-1] = node
}
newLevel := sl.randomLevel() // 新插入的结点的层数
if newLevel > sl.level {
sl.level = newLevel
}
newNode := NewNode(newLevel, data)
for level := newLevel; level > 0; level-- {
// 新结点的当前层级的下一个值
newNode.Next[level-1] = update[level-1].Next[level-1]
update[level-1].Next[level-1] = newNode
}
}
func (sl *SkipList) Delete(data int) (success bool) {
defer func() {
if err := recover(); err != nil {
fmt.Println(err)
}
success = false
return
}()
node := sl.head
for level := sl.level; level > 0; level-- {
for node.Next != nil && node.Next[level-1].Data < data {
node = node.Next[level-1]
}
// 下一个是删除结点,则把指针指向下下个
if node.Next != nil && node.Next[level-1].Data == data {
node.Next[level-1] = node.Next[level-1].Next[level-1]
}
}
return true
}
// 搜索打印搜索轨迹
func (sl *SkipList) Search(data int) {
node := sl.head
for level := sl.level; level > 0; level-- {
for node.Next != nil && node.Next[level-1] != nil && node.Next[level-1].Data <= data {
fmt.Print(node.Data, "--->")
node = node.Next[level-1]
}
if node.Data == data {
fmt.Print(node.Data)
return
}
}
}
// 打印跳表
func (sl *SkipList) print() {
for level := sl.level; level > 0; level-- {
node := sl.head
for node.Next != nil && node.Next[level-1] != nil {
fmt.Print(node.Data, "----")
node = node.Next[level-1]
}
fmt.Print("nil")
fmt.Println()
}
}
func init() {
rand.Seed(time.Now().UnixNano())
}
func main() {
sl := NewSkipList(4)
sl.Insert(1)
sl.Insert(3)
sl.Insert(5)
sl.Insert(7)
sl.Search(5)
fmt.Println()
sl.print()
fmt.Println("after delete")
sl.Delete(3)
sl.Search(5)
fmt.Println()
sl.print()
}
result:
0--->1--->3--->5
0----1----3----nil
0----1----3----5----nil
after delete
0--->1--->5
0----1----nil
0----1----5----nil