package main
import (
"fmt"
"math/rand"
"sync"
)
type SkipTable struct {
maxHeight int
head *Node
comparator Comparator
mu sync.RWMutex
}
type Node struct {
key interface{}
next []*Node
}
func newNode(key interface{}, height int) *Node {
x := new(Node)
x.key = key
x.next = make([]*Node, height)
return x
}
func (node *Node) getNext(level int) *Node {
return node.next[level]
}
func (node *Node) setNext(level int, x *Node) {
node.next[level] = x
}
// <0 , if a < b
// =0 , if a == b
// >0 , if a > b
type Comparator func(a, b interface{}) int
func IntComparator(a, b interface{}) int {
aInt := a.(int)
bInt := b.(int)
return aInt - bInt
}
const (
kMaxHeight = 12
kBranching = 4
)
func NewSkipTable(comparator Comparator)*SkipTable{
t := &SkipTable{
maxHeight:1,
head:newNode(nil,kMaxHeight),
comparator:comparator,
}
return t
}
func (s *SkipTable)randomHeight()int{
height := 1
for height<kMaxHeight&&rand.Int63n(kBranching) == 0{
height++
}
return height
}
func (s *SkipTable)Search(key interface{}) (pre [kMaxHeight]*Node,cur *Node) {
cur = s.head
next := cur
level := s.maxHeight-1
for{
next = cur.getNext(level)
if s.searchAfter(key,next){ //当前节点值小于搜索值,往后继续查找
fmt.Println("go to next",level)
cur = next
}else { //当前节点值大于搜索值,确定区间后值,降级查询,cur值不变
pre[level] = cur
if level == 0{ //如果是在最底层确定后区间
if next !=nil && s.comparator(key,next.key) == 0{ //找到对应的目标
return pre,next
}else{ //key不存在
return pre,nil
}
}else{
level--
fmt.Println("level--",level)
}
}
}
return pre,nil
}
func (s *SkipTable)searchAfter(key interface{},next *Node) bool{
if next!=nil && s.comparator(key,next.key)>0{
return true
}
return false
}
func (s *SkipTable)Contains(key interface{}) bool {
if _,n := s.Search(key);n!=nil{
return true
}
return false
}
func (s *SkipTable)Insert(key interface{}){
s.mu.Lock()
defer s.mu.Unlock()
pre,_:=s.Search(key)
height := s.randomHeight()
if height>s.maxHeight{
fmt.Println("random height=",height,"val=",key)
for i := s.maxHeight; i < height; i++ {
pre[i] = s.head
}
s.maxHeight = height
}
x := newNode(key,height)
for i:=0;i<height;i++{
x.setNext(i,pre[i].getNext(i))
pre[i].setNext(i,x)
}
}