zoukankan      html  css  js  c++  java
  • 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)
    	}
    }
    

      

  • 相关阅读:
    weexpack build android 和 weexpack run android 报错 及 解决方案
    weexapp 开发流程(三)其他页面创建
    svn 创建分支、切换分支 及 合并分支 操作
    github 新建远程仓库 及 删除远程仓库
    photoshop 前端常用技巧
    vue2.0 常用的 UI 库
    weex 小结
    Android-studio 连接真机 调试weex项目
    js中Math之random,round,ceil,floor的用法总结
    基于canvas图像处理的图片 灰色图像
  • 原文地址:https://www.cnblogs.com/mengxingxinqing/p/12367807.html
Copyright © 2011-2022 走看看