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

  

原文地址:https://www.cnblogs.com/mengxingxinqing/p/12367807.html