首页 > 代码库 > Go语言实现跳表(SkipList)
Go语言实现跳表(SkipList)
跳表(skiplist)在redis/levelDB中属于核心数据结构,我简单粗暴的用Golang实现了下。
就我的简单理解来说,就一个普通的链表,在insert时,通过Random_level(),把一层变成很多层,
越上数据越小,跨度越大。 查找时从上往下找,用空间换时间。
记下测试代码:
package main import ( "fmt" //"github.com/xclpkg/algorithm" "math/rand" ) func main() { slt := NewSkipList() for i := 100; i > 0; i-- { slt.Insert(i) } slt.PrintSkipList() slt.Search(20) slt.Search(36) slt.Search(93) slt.Delete(55) slt.PrintSkipList() } const SKIPLIST_MAXLEVEL = 8 //32 const SKIPLIST_P = 4 type SkipList struct { Header []List Level int } func NewSkipList() *SkipList { return &SkipList{Level: 1, Header: make([]List, SKIPLIST_MAXLEVEL)} } func (skipList *SkipList) Insert(key int) { update := make(map[int]*Node) for i := len(skipList.Header) - 1; i >= 0; i-- { if skipList.Header[i].Len() > 0 { for e := skipList.Header[i].Front(); e != nil; e = e.Next() { if e.Value.(int) >= key { update[i] = e break } } } //Heaer[lv].List } //Header Level level := skipList.Random_level() if level > skipList.Level { skipList.Level = level } for i := 0; i < level; i++ { if v, ok := update[i]; ok { skipList.Header[i].InsertBefore(key, v) } else { skipList.Header[i].PushBack(key) } } } func (skipList *SkipList) Search(key int) *Node { for i := len(skipList.Header) - 1; i >= 0; i-- { if skipList.Header[i].Len() > 0 { for e := skipList.Header[i].Front(); e != nil; e = e.Next() { switch { case e.Value.(int) == key: fmt.Println("Found level=", i, " key=", key) return e case e.Value.(int) > key: break } } //end for } //end if } //end for return nil } func (skipList *SkipList) Delete(key int) { for i := len(skipList.Header) - 1; i >= 0; i-- { if skipList.Header[i].Len() > 0 { for e := skipList.Header[i].Front(); e != nil; e = e.Next() { switch { case e.Value.(int) == key: fmt.Println("Delete level=", i, " key=", key) skipList.Header[i].remove(e) case e.Value.(int) > key: break } } //end for } //end if } //end for } func (skipList *SkipList) PrintSkipList() { fmt.Println("\nSkipList-------------------------------------------") for i := SKIPLIST_MAXLEVEL - 1; i >= 0; i-- { fmt.Println("level:", i) if skipList.Header[i].Len() > 0 { for e := skipList.Header[i].Front(); e != nil; e = e.Next() { fmt.Printf("%d ", e.Value) } //end for } //end if fmt.Println("\n--------------------------------------------------------") } //end for } func (skipList *SkipList) Random_level() int { level := 1 for (rand.Int31()&0xFFFF)%SKIPLIST_P == 0 { level += 1 } if level < SKIPLIST_MAXLEVEL { return level } else { return SKIPLIST_MAXLEVEL } } ////////////////////////////////////////////////////// type Node struct { next, prev *Node list *List Value interface{} } type List struct { root Node len int } func (node *Node) Next() *Node { if p := node.next; node.list != nil && p != &node.list.root { return p } return nil } func (node *Node) Prev() *Node { if p := node.prev; node.list != nil && p != &node.list.root { return p } return nil } func (list *List) Init() *List { list.root.next = &list.root list.root.prev = &list.root list.len = 0 return list } func New() *List { return new(List).Init() } func (list *List) lazyInit() { if list.root.next == nil { list.Init() } } func (list *List) Len() int { return list.len } func (list *List) remove(e *Node) *Node { e.prev.next = e.next e.next.prev = e.prev e.next = nil e.prev = nil e.list = nil list.len-- return e } func (list *List) Remove(e *Node) interface{} { if e.list == list { list.remove(e) } return e.Value } func (list *List) Front() *Node { if list.len == 0 { return nil } return list.root.next } func (list *List) Back() *Node { if list.len == 0 { return nil } return list.root.prev } func (list *List) insert(e, at *Node) *Node { n := at.next at.next = e e.prev = at e.next = n n.prev = e e.list = list list.len++ return e } func (list *List) insertValue(v interface{}, at *Node) *Node { return list.insert(&Node{Value: v}, at) } func (list *List) InsertBefore(v interface{}, mark *Node) *Node { if mark.list != list { return nil } return list.insertValue(v, mark.prev) } func (list *List) PushBack(v interface{}) *Node { list.lazyInit() return list.insertValue(v, list.root.prev) }
效果:
SkipList------------------------------------------- level: 7 -------------------------------------------------------- level: 6 -------------------------------------------------------- level: 5 -------------------------------------------------------- level: 4 -------------------------------------------------------- level: 3 93 -------------------------------------------------------- level: 2 36 93 -------------------------------------------------------- level: 1 6 10 22 23 25 36 42 47 48 54 55 61 72 75 78 82 89 93 -------------------------------------------------------- level: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 5 7 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 -------------------------------------------------------- Found level= 0 key= 20 Found level= 2 key= 36 Found level= 3 key= 93 Delete level= 1 key= 55 Delete level= 0 key= 55 SkipList------------------------------------------- level: 7 -------------------------------------------------------- level: 6 -------------------------------------------------------- level: 5 -------------------------------------------------------- level: 4 -------------------------------------------------------- level: 3 93 -------------------------------------------------------- level: 2 36 93 -------------------------------------------------------- level: 1 6 10 22 23 25 36 42 47 48 54 61 72 75 78 82 89 93 -------------------------------------------------------- level: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 56 57 5 8 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 --------------------------------------------------------搞定。
MAIL: xcl_168@aliyun.com
BLOG: http://blog.csdn.net./xcl168
Go语言实现跳表(SkipList)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。