skiptable的golang实现
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) } }