├── go.mod ├── .gitignore ├── types_test.go ├── .github └── workflows │ └── go.yml ├── go.sum ├── LICENSE ├── scorable.go ├── scorable_test.go ├── comparable.go ├── element.go ├── README.md ├── types.go ├── skiplist_test.go └── skiplist.go /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/huandu/skiplist 2 | 3 | go 1.12 4 | 5 | require github.com/huandu/go-assert v1.1.5 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | *.exe 23 | *.test 24 | *.prof 25 | 26 | # Intellij 27 | *.iml 28 | .idea/ 29 | 30 | # VS Code 31 | debug 32 | debug_test 33 | .vscode/ 34 | 35 | # Mac 36 | .DS_Store 37 | 38 | # go work 39 | go.work 40 | go.work.sum 41 | -------------------------------------------------------------------------------- /types_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Huan Du. All rights reserved. 2 | // Licensed under the MIT license that can be found in the LICENSE file. 3 | 4 | package skiplist 5 | 6 | import ( 7 | "testing" 8 | 9 | "github.com/huandu/go-assert" 10 | ) 11 | 12 | func TestCompareTypes(t *testing.T) { 13 | a := assert.New(t) 14 | cases := []struct { 15 | kt keyType 16 | lhs, rhs interface{} 17 | result int 18 | }{ 19 | {Int, 0, 0, 0}, 20 | {Int, 2, 0, 1}, 21 | {Int, -1, 1, -1}, 22 | {Byte, 9, 2, 1}, 23 | {Float32, 1.2, 1.20001, -1}, 24 | {String, "foo", "bar", 1}, 25 | {String, "001", "101", -1}, 26 | {String, "equals", "equals", 0}, 27 | {Bytes, []byte("abcdefghijk"), []byte("abcdefghij"), 1}, 28 | } 29 | 30 | for i, c := range cases { 31 | a.Use(&i, &c) 32 | a.Equal(c.result, c.kt.Compare(c.lhs, c.rhs)) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /.github/workflows/go.yml: -------------------------------------------------------------------------------- 1 | name: Go 2 | 3 | on: 4 | push: 5 | branches: [master] 6 | pull_request: 7 | branches: [master] 8 | 9 | jobs: 10 | build: 11 | name: Build 12 | runs-on: ubuntu-latest 13 | steps: 14 | - name: Set up Go 1.x 15 | uses: actions/setup-go@v2 16 | with: 17 | go-version: ^1.13 18 | 19 | - name: Check out code into the Go module directory 20 | uses: actions/checkout@v2 21 | 22 | - name: Get dependencies 23 | run: | 24 | go mod download 25 | 26 | - name: Test 27 | run: go test -v -coverprofile=covprofile.cov ./... 28 | 29 | - name: Send coverage 30 | env: 31 | COVERALLS_TOKEN: ${{ secrets.GITHUB_TOKEN }} 32 | run: | 33 | go get github.com/mattn/goveralls 34 | go run github.com/mattn/goveralls -coverprofile=covprofile.cov -service=github 35 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 2 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 3 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 4 | github.com/huandu/go-assert v1.1.5 h1:fjemmA7sSfYHJD7CUqs9qTwwfdNAx7/j2/ZlHXzNB3c= 5 | github.com/huandu/go-assert v1.1.5/go.mod h1:yOLvuqZwmcHIC5rIzrBhT7D3Q9c3GFnd0JrPVhn/06U= 6 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 7 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 8 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 9 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 10 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011 Huan Du 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. -------------------------------------------------------------------------------- /scorable.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Huan Du. All rights reserved. 2 | // Licensed under the MIT license that can be found in the LICENSE file. 3 | 4 | package skiplist 5 | 6 | import "reflect" 7 | 8 | // Scorable is used by skip list to optimize comparing performance. 9 | // If two keys have different score values, they must be different keys. 10 | // 11 | // For any key `k1` and `k2`, the calculated score must follow these rules. 12 | // 13 | // - If Compare(k1, k2) is positive, k1.Score() >= k2.Score() must be true. 14 | // - If Compare(k1, k2) is negative, k1.Score() <= k2.Score() must be true. 15 | // - If Compare(k1, k2) is 0, k1.Score() == k2.Score() must be true. 16 | type Scorable interface { 17 | Score() float64 18 | } 19 | 20 | // CalcScore calculates score of a key. 21 | // 22 | // The score is a hint to optimize comparable performance. 23 | // A skip list keeps all elements sorted by score from smaller to largest. 24 | // If there are keys with different scores, these keys must be different. 25 | func CalcScore(key interface{}) (score float64) { 26 | if scorable, ok := key.(Scorable); ok { 27 | score = scorable.Score() 28 | return 29 | } 30 | 31 | val := reflect.ValueOf(key) 32 | score = calcScore(val) 33 | return 34 | } 35 | -------------------------------------------------------------------------------- /scorable_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Huan Du. All rights reserved. 2 | // Licensed under the MIT license that can be found in the LICENSE file. 3 | 4 | package skiplist 5 | 6 | import ( 7 | "testing" 8 | 9 | "github.com/huandu/go-assert" 10 | ) 11 | 12 | func TestKeyScore(t *testing.T) { 13 | a := assert.New(t) 14 | keys := []interface{}{ 15 | byte(11), -12, int(13), int8(14), int16(-15), int32(16), int64(-17), rune(18), 16 | uint(20), uint8(21), uint16(22), uint32(23), uint64(24), uintptr(25), 17 | 30.05, float32(30.1), float64(30.2), 18 | "abcde", "abcdefg", "abcdefghijk", 19 | []byte("abcde"), []byte("abcdefg"), []byte("abcdefghijk"), 20 | []int{1, 2, 3}, nil, 21 | } 22 | scores := []float64{ 23 | 11, -12, 13, 14, -15, 16, -17, 18, 24 | 20, 21, 22, 23, 24, 25, 25 | 30.05, float64(float32(30.1)), 30.2, 26 | 0x6162636465000000, 0x6162636465666768, 0x6162636465666768, 27 | 0x6162636465000000, 0x6162636465666768, 0x6162636465666768, 28 | 0, 0, 29 | } 30 | 31 | for i, k := range keys { 32 | score := CalcScore(k) 33 | 34 | a.Use(&i, &k, &score) 35 | a.Equal(score, scores[i]) 36 | } 37 | } 38 | 39 | type testScorable int 40 | 41 | func (s testScorable) Score() float64 { 42 | return float64(s) * 2 43 | } 44 | 45 | func TestScarable(t *testing.T) { 46 | a := assert.New(t) 47 | 48 | s1 := testScorable(12) 49 | a.Equal(CalcScore(s1), 2*12.0) 50 | 51 | s2 := int(s1) 52 | a.Equal(CalcScore(s2), 12.0) 53 | } 54 | -------------------------------------------------------------------------------- /comparable.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Huan Du. All rights reserved. 2 | // Licensed under the MIT license that can be found in the LICENSE file. 3 | 4 | package skiplist 5 | 6 | // Comparable defines a comparable func. 7 | type Comparable interface { 8 | Compare(lhs, rhs interface{}) int 9 | CalcScore(key interface{}) float64 10 | } 11 | 12 | var ( 13 | _ Comparable = GreaterThanFunc(nil) 14 | _ Comparable = LessThanFunc(nil) 15 | ) 16 | 17 | // GreaterThanFunc returns true if lhs greater than rhs 18 | type GreaterThanFunc func(lhs, rhs interface{}) int 19 | 20 | // LessThanFunc returns true if lhs less than rhs 21 | type LessThanFunc GreaterThanFunc 22 | 23 | // Compare compares lhs and rhs by calling `f(lhs, rhs)`. 24 | func (f GreaterThanFunc) Compare(lhs, rhs interface{}) int { 25 | return f(lhs, rhs) 26 | } 27 | 28 | // CalcScore always returns 0 as there is no way to understand how f compares keys. 29 | func (f GreaterThanFunc) CalcScore(key interface{}) float64 { 30 | return 0 31 | } 32 | 33 | // Compare compares lhs and rhs by calling `-f(lhs, rhs)`. 34 | func (f LessThanFunc) Compare(lhs, rhs interface{}) int { 35 | return -f(lhs, rhs) 36 | } 37 | 38 | // CalcScore always returns 0 as there is no way to understand how f compares keys. 39 | func (f LessThanFunc) CalcScore(key interface{}) float64 { 40 | return 0 41 | } 42 | 43 | // Reverse creates a reversed comparable. 44 | func Reverse(comparable Comparable) Comparable { 45 | return reversedComparable{ 46 | comparable: comparable, 47 | } 48 | } 49 | 50 | type reversedComparable struct { 51 | comparable Comparable 52 | } 53 | 54 | var _ Comparable = reversedComparable{} 55 | 56 | func (reversed reversedComparable) Compare(lhs, rhs interface{}) int { 57 | return -reversed.comparable.Compare(lhs, rhs) 58 | } 59 | 60 | func (reversed reversedComparable) CalcScore(key interface{}) float64 { 61 | return -reversed.comparable.CalcScore(key) 62 | } 63 | -------------------------------------------------------------------------------- /element.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Huan Du. All rights reserved. 2 | // Licensed under the MIT license that can be found in the LICENSE file. 3 | 4 | package skiplist 5 | 6 | import ( 7 | "unsafe" 8 | ) 9 | 10 | // Element is an element node of a skip list. 11 | type Element struct { 12 | elementHeader 13 | 14 | Value interface{} 15 | key interface{} 16 | score float64 17 | 18 | prev *Element // Points to previous adjacent elem. 19 | prevTopLevel *Element // Points to previous element which points to this element's top most level. 20 | list *SkipList // The list contains this elem. 21 | } 22 | 23 | // elementHeader is the header of an element or a skip list. 24 | // It must be the first anonymous field in a type to make Element() work correctly. 25 | type elementHeader struct { 26 | levels []*Element // Next element at all levels. 27 | } 28 | 29 | func (header *elementHeader) Element() *Element { 30 | return (*Element)(unsafe.Pointer(header)) 31 | } 32 | 33 | func newElement(list *SkipList, level int, score float64, key, value interface{}) *Element { 34 | return &Element{ 35 | elementHeader: elementHeader{ 36 | levels: make([]*Element, level), 37 | }, 38 | Value: value, 39 | key: key, 40 | score: score, 41 | list: list, 42 | } 43 | } 44 | 45 | // Next returns next adjacent elem. 46 | func (elem *Element) Next() *Element { 47 | if len(elem.levels) == 0 { 48 | return nil 49 | } 50 | 51 | return elem.levels[0] 52 | } 53 | 54 | // Prev returns previous adjacent elem. 55 | func (elem *Element) Prev() *Element { 56 | return elem.prev 57 | } 58 | 59 | // NextLevel returns next element at specific level. 60 | // If level is invalid, returns nil. 61 | func (elem *Element) NextLevel(level int) *Element { 62 | if level < 0 || level >= len(elem.levels) { 63 | return nil 64 | } 65 | 66 | return elem.levels[level] 67 | } 68 | 69 | // PrevLevel returns previous element which points to this element at specific level. 70 | // If level is invalid, returns nil. 71 | func (elem *Element) PrevLevel(level int) *Element { 72 | if level < 0 || level >= len(elem.levels) { 73 | return nil 74 | } 75 | 76 | if level == 0 { 77 | return elem.prev 78 | } 79 | 80 | if level == len(elem.levels)-1 { 81 | return elem.prevTopLevel 82 | } 83 | 84 | prev := elem.prev 85 | 86 | for prev != nil { 87 | if level < len(prev.levels) { 88 | return prev 89 | } 90 | 91 | prev = prev.prevTopLevel 92 | } 93 | 94 | return prev 95 | } 96 | 97 | // Key returns the key of the elem. 98 | func (elem *Element) Key() interface{} { 99 | return elem.key 100 | } 101 | 102 | // Score returns the score of this element. 103 | // The score is a hint when comparing elements. 104 | // Skip list keeps all elements sorted by score from smallest to largest. 105 | func (elem *Element) Score() float64 { 106 | return elem.score 107 | } 108 | 109 | // Level returns the level of this elem. 110 | func (elem *Element) Level() int { 111 | return len(elem.levels) 112 | } 113 | 114 | func (elem *Element) reset() { 115 | elem.list = nil 116 | elem.prev = nil 117 | elem.prevTopLevel = nil 118 | elem.levels = nil 119 | } 120 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Skip List in Golang 2 | 3 | [![Go](https://github.com/huandu/skiplist/workflows/Go/badge.svg)](https://github.com/huandu/skiplist/actions) 4 | [![Go Doc](https://godoc.org/github.com/huandu/skiplist?status.svg)](https://pkg.go.dev/github.com/huandu/skiplist) 5 | [![Go Report](https://goreportcard.com/badge/github.com/huandu/skiplist)](https://goreportcard.com/report/github.com/huandu/skiplist) 6 | [![Coverage Status](https://coveralls.io/repos/github/huandu/skiplist/badge.svg?branch=master)](https://coveralls.io/github/huandu/skiplist?branch=master) 7 | 8 | Skip list is an ordered map. See wikipedia page [skip list](http://en.wikipedia.org/wiki/Skip_list) to learn algorithm details about this data structure. 9 | 10 | Highlights in this implementation: 11 | 12 | - Built-in types can be used as key with predefined key types. See [Int](https://pkg.go.dev/github.com/huandu/skiplist#Int) and related constants as a sample. 13 | - Support custom comparable function so that any type can be used as key. 14 | - Key sort order can be changed quite easily. See [Reverse](https://pkg.go.dev/github.com/huandu/skiplist#Reverse) and [LessThanFunc](https://pkg.go.dev/github.com/huandu/skiplist#LessThanFunc). 15 | - Rand source and max level can be changed per list. It can be useful in performance critical scenarios. 16 | 17 | ## Install 18 | 19 | Install this package through `go get`. 20 | 21 | ```bash 22 | go get github.com/huandu/skiplist 23 | ``` 24 | 25 | ## Basic Usage 26 | 27 | Here is a quick sample. 28 | 29 | ```go 30 | package main 31 | 32 | import ( 33 | "fmt" 34 | 35 | "github.com/huandu/skiplist" 36 | ) 37 | 38 | func main() { 39 | // Create a skip list with int key. 40 | list := skiplist.New(skiplist.Int) 41 | 42 | // Add some values. Value can be anything. 43 | list.Set(12, "hello world") 44 | list.Set(34, 56) 45 | list.Set(78, 90.12) 46 | 47 | // Get element by index. 48 | elem := list.Get(34) // Value is stored in elem.Value. 49 | fmt.Println(elem.Value) // Output: 56 50 | next := elem.Next() // Get next element. 51 | prev := next.Prev() // Get previous element. 52 | fmt.Println(next.Value, prev.Value) // Output: 90.12 56 53 | 54 | // Or, directly get value just like a map 55 | val, ok := list.GetValue(34) 56 | fmt.Println(val, ok) // Output: 56 true 57 | 58 | // Find first elements with score greater or equal to key 59 | foundElem := list.Find(30) 60 | fmt.Println(foundElem.Key(), foundElem.Value) // Output: 34 56 61 | 62 | // Remove an element for key. 63 | list.Remove(34) 64 | } 65 | ``` 66 | 67 | ## Using `GreaterThanFunc` and `LessThanFunc` 68 | 69 | Define your own `GreaterThanFunc` or `LessThanFunc` to use any custom type as the key in a skip list. 70 | 71 | The signature of `GreaterThanFunc` are `LessThanFunc` are the same. 72 | The only difference between them is that `LessThanFunc` reverses result returned by custom func 73 | to make the list ordered by key in a reversed order. 74 | 75 | ```go 76 | type T struct { 77 | Rad float64 78 | } 79 | list := New(GreaterThanFunc(func(k1, k2 interface{}) int { 80 | s1 := math.Sin(k1.(T).Rad) 81 | s2 := math.Sin(k2.(T).Rad) 82 | 83 | if s1 > s2 { 84 | return 1 85 | } else if s1 < s2 { 86 | return -1 87 | } 88 | 89 | return 0 90 | })) 91 | list.Set(T{math.Pi / 8}, "sin(π/8)") 92 | list.Set(T{math.Pi / 2}, "sin(π/2)") 93 | list.Set(T{math.Pi}, "sin(π)") 94 | 95 | fmt.Println(list.Front().Value) // Output: sin(π) 96 | fmt.Println(list.Back().Value) // Output: sin(π/2) 97 | ``` 98 | 99 | ## License 100 | 101 | This library is licensed under MIT license. See LICENSE for details. 102 | -------------------------------------------------------------------------------- /types.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Huan Du. All rights reserved. 2 | // Licensed under the MIT license that can be found in the LICENSE file. 3 | 4 | package skiplist 5 | 6 | import ( 7 | "bytes" 8 | "fmt" 9 | "reflect" 10 | ) 11 | 12 | // Key types for all built-in types. 13 | // We can use these type as key type when creating a new skip list. 14 | // 15 | // list := New(Int) // Use int as key. 16 | const ( 17 | Byte = byteType 18 | ByteAsc = Byte 19 | ByteDesc = -Byte 20 | 21 | Rune = runeType 22 | RuneAsc = Rune 23 | RuneDesc = -Rune 24 | 25 | Int = intType 26 | IntAsc = Int 27 | IntDesc = -Int 28 | 29 | Int8 = int8Type 30 | Int8Asc = Int8 31 | Int8Desc = -Int8 32 | 33 | Int16 = int16Type 34 | Int16Asc = Int16 35 | Int16Desc = -Int16 36 | 37 | Int32 = int32Type 38 | Int32Asc = Int32 39 | Int32Desc = -Int32 40 | 41 | Int64 = int64Type 42 | Int64Asc = Int64 43 | Int64Desc = -Int64 44 | 45 | Uint = uintType 46 | UintAsc = Uint 47 | UintDesc = -Uint 48 | 49 | Uint8 = uint8Type 50 | Uint8Asc = Uint8 51 | Uint8Desc = -Uint8 52 | 53 | Uint16 = uint16Type 54 | Uint16Asc = Uint16 55 | Uint16Desc = -Uint16 56 | 57 | Uint32 = uint32Type 58 | Uint32Asc = Uint32 59 | Uint32Desc = -Uint32 60 | 61 | Uint64 = uint64Type 62 | Uint64Asc = Uint64 63 | Uint64Desc = -Uint64 64 | 65 | Uintptr = uintptrType 66 | UintptrAsc = Uintptr 67 | UintptrDesc = -Uintptr 68 | 69 | Float32 = float32Type 70 | Float32Asc = Float32 71 | Float32Desc = -Float32 72 | 73 | Float64 = float64Type 74 | Float64Asc = Float64 75 | Float64Desc = -Float64 76 | 77 | String = stringType 78 | StringAsc = String 79 | StringDesc = -String 80 | 81 | Bytes = bytesType 82 | BytesAsc = Bytes 83 | BytesDesc = -Bytes 84 | ) 85 | 86 | const ( 87 | byteType = keyType(reflect.Uint8) 88 | runeType = keyType(reflect.Int32) 89 | intType = keyType(reflect.Int) 90 | int8Type = keyType(reflect.Int8) 91 | int16Type = keyType(reflect.Int16) 92 | int32Type = keyType(reflect.Int32) 93 | int64Type = keyType(reflect.Int64) 94 | uintType = keyType(reflect.Uint) 95 | uint8Type = keyType(reflect.Uint8) 96 | uint16Type = keyType(reflect.Uint16) 97 | uint32Type = keyType(reflect.Uint32) 98 | uint64Type = keyType(reflect.Uint64) 99 | uintptrType = keyType(reflect.Uintptr) 100 | float32Type = keyType(reflect.Float32) 101 | float64Type = keyType(reflect.Float64) 102 | stringType = keyType(reflect.String) 103 | bytesType = keyType(reflect.Slice) 104 | ) 105 | 106 | type keyType int 107 | 108 | var _ Comparable = keyType(0) 109 | 110 | func (kt keyType) kind() (kind reflect.Kind, reversed bool) { 111 | if kt < 0 { 112 | reversed = true 113 | kt = -kt 114 | } 115 | 116 | kind = reflect.Kind(kt) 117 | return 118 | } 119 | 120 | func (kt keyType) Compare(lhs, rhs interface{}) int { 121 | val1 := reflect.ValueOf(lhs) 122 | val2 := reflect.ValueOf(rhs) 123 | kind, reversed := kt.kind() 124 | result := compareTypes(val1, val2, kind) 125 | 126 | if reversed { 127 | result = -result 128 | } 129 | 130 | return result 131 | } 132 | 133 | var typeOfBytes = reflect.TypeOf([]byte(nil)) 134 | 135 | func compareTypes(lhs, rhs reflect.Value, kind reflect.Kind) int { 136 | switch kind { 137 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, 138 | reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uintptr, 139 | reflect.Float32, reflect.Float64: 140 | v1 := calcScore(lhs) 141 | v2 := calcScore(rhs) 142 | 143 | if v1 > v2 { 144 | return 1 145 | } 146 | 147 | if v1 < v2 { 148 | return -1 149 | } 150 | 151 | return 0 152 | 153 | case reflect.Int64: 154 | v1 := lhs.Int() 155 | v2 := rhs.Int() 156 | 157 | if v1 > v2 { 158 | return 1 159 | } 160 | 161 | if v1 < v2 { 162 | return -1 163 | } 164 | 165 | return 0 166 | 167 | case reflect.Uint64: 168 | v1 := lhs.Uint() 169 | v2 := rhs.Uint() 170 | 171 | if v1 > v2 { 172 | return 1 173 | } 174 | 175 | if v1 < v2 { 176 | return -1 177 | } 178 | 179 | return 0 180 | 181 | case reflect.String: 182 | v1 := lhs.String() 183 | v2 := rhs.String() 184 | 185 | if v1 == v2 { 186 | return 0 187 | } 188 | 189 | if v1 > v2 { 190 | return 1 191 | } 192 | 193 | return -1 194 | 195 | case reflect.Slice: 196 | if lhs.Type().ConvertibleTo(typeOfBytes) && rhs.Type().ConvertibleTo(typeOfBytes) { 197 | bytes1 := lhs.Convert(typeOfBytes).Interface().([]byte) 198 | bytes2 := rhs.Convert(typeOfBytes).Interface().([]byte) 199 | return bytes.Compare(bytes1, bytes2) 200 | } 201 | } 202 | 203 | panic("never be here") 204 | } 205 | 206 | var numberLikeKinds = [...]bool{ 207 | reflect.Int: true, 208 | reflect.Int8: true, 209 | reflect.Int16: true, 210 | reflect.Int32: true, 211 | reflect.Int64: true, 212 | reflect.Uint: true, 213 | reflect.Uint8: true, 214 | reflect.Uint16: true, 215 | reflect.Uint32: true, 216 | reflect.Uint64: true, 217 | reflect.Uintptr: true, 218 | reflect.Float32: true, 219 | reflect.Float64: true, 220 | reflect.String: false, 221 | reflect.Slice: false, 222 | } 223 | 224 | func (kt keyType) CalcScore(key interface{}) float64 { 225 | k := reflect.ValueOf(key) 226 | kind, reversed := kt.kind() 227 | 228 | if kk := k.Kind(); kk != kind { 229 | // Special case for constant values. 230 | // It allows us to write code like following without panic. 231 | // 232 | // list := skiplist.New(skiplist.Float64) 233 | // list.Set(123, "foo") // 123 is int instead of float64. 234 | if numberLikeKinds[kind] && (kk == reflect.Int || kk == reflect.Float64) { 235 | // By pass the check. 236 | } else { 237 | name := kind.String() 238 | 239 | if kind == reflect.Slice { 240 | name = "[]byte" 241 | } 242 | 243 | panic(fmt.Errorf("skiplist: key type must be %v, but actual type is %v", name, k.Type())) 244 | } 245 | } 246 | 247 | score := calcScore(k) 248 | 249 | if reversed { 250 | score = -score 251 | } 252 | 253 | return score 254 | } 255 | 256 | func calcScore(val reflect.Value) (score float64) { 257 | switch val.Kind() { 258 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 259 | score = float64(val.Int()) 260 | 261 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 262 | score = float64(val.Uint()) 263 | 264 | case reflect.Float32, reflect.Float64: 265 | score = val.Float() 266 | 267 | case reflect.String: 268 | var hash uint64 269 | str := val.String() 270 | l := len(str) 271 | 272 | // only use first 8 bytes 273 | if l > 8 { 274 | l = 8 275 | } 276 | 277 | // Consider str as a Big-Endian uint64. 278 | for i := 0; i < l; i++ { 279 | shift := uint(64 - 8 - i*8) 280 | hash |= uint64(str[i]) << shift 281 | } 282 | 283 | score = float64(hash) 284 | 285 | case reflect.Slice: 286 | if val.Type().ConvertibleTo(typeOfBytes) { 287 | var hash uint64 288 | data := val.Convert(typeOfBytes).Interface().([]byte) 289 | 290 | l := len(data) 291 | 292 | // only use first 8 bytes 293 | if l > 8 { 294 | l = 8 295 | } 296 | 297 | // Consider str as a Big-Endian uint64. 298 | for i := 0; i < l; i++ { 299 | shift := uint(64 - 8 - i*8) 300 | hash |= uint64(data[i]) << shift 301 | } 302 | 303 | score = float64(hash) 304 | } 305 | } 306 | 307 | return 308 | } 309 | -------------------------------------------------------------------------------- /skiplist_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Huan Du. All rights reserved. 2 | // Licensed under the MIT license that can be found in the LICENSE file. 3 | 4 | package skiplist 5 | 6 | import ( 7 | "fmt" 8 | "math" 9 | "math/rand" 10 | "testing" 11 | "time" 12 | 13 | "github.com/huandu/go-assert" 14 | ) 15 | 16 | func TestBasicCRUD(t *testing.T) { 17 | a := assert.New(t) 18 | list := New(Float64) 19 | a.Assert(list.Len() == 0) 20 | a.Equal(list.Find(0), nil) 21 | 22 | elem1 := list.Set(12.34, "first") 23 | a.Assert(elem1 != nil) 24 | a.Equal(list.Len(), 1) 25 | a.Equal(list.Front(), elem1) 26 | a.Equal(list.Back(), elem1) 27 | a.Equal(elem1.Next(), nil) 28 | a.Equal(elem1.Prev(), nil) 29 | a.Equal(list.Find(0), elem1) 30 | a.Equal(list.Find(12.34), elem1) 31 | a.Equal(list.Find(15), nil) 32 | 33 | assertSanity(a, list) 34 | 35 | elem2 := list.Set(23.45, "second") 36 | a.Assert(elem2 != nil) 37 | a.NotEqual(elem1, elem2) 38 | a.Equal(list.Len(), 2) 39 | a.Equal(list.Front(), elem1) 40 | a.Equal(list.Back(), elem2) 41 | a.Equal(elem2.Next(), nil) 42 | a.Equal(elem2.Prev(), elem1) 43 | a.Equal(list.Find(-10), elem1) 44 | a.Equal(list.Find(15), elem2) 45 | a.Equal(list.Find(25), nil) 46 | 47 | assertSanity(a, list) 48 | 49 | elem3 := list.Set(16.78, "middle") 50 | a.Assert(elem3 != nil) 51 | a.NotEqual(elem3, elem1) 52 | a.NotEqual(elem3, elem2) 53 | a.Equal(list.Len(), 3) 54 | a.Equal(list.Front(), elem1) 55 | a.Equal(list.Back(), elem2) 56 | a.Equal(elem3.Next(), elem2) 57 | a.Equal(elem3.Prev(), elem1) 58 | a.Equal(list.Find(-20), elem1) 59 | a.Equal(list.Find(15), elem3) 60 | a.Equal(list.Find(20), elem2) 61 | 62 | assertSanity(a, list) 63 | 64 | elem4 := list.Set(9.01, "very beginning") 65 | a.Assert(elem4 != nil) 66 | a.NotEqual(elem4, elem1) 67 | a.NotEqual(elem4, elem2) 68 | a.NotEqual(elem4, elem3) 69 | a.Equal(list.Len(), 4) 70 | a.Equal(list.Front(), elem4) 71 | a.Equal(list.Back(), elem2) 72 | a.Equal(elem4.Next(), elem1) 73 | a.Equal(elem4.Prev(), nil) 74 | a.Equal(list.Find(0), elem4) 75 | a.Equal(list.Find(15), elem3) 76 | a.Equal(list.Find(20), elem2) 77 | 78 | assertSanity(a, list) 79 | 80 | elem5 := list.Set(16.78, "middle overwrite") 81 | a.Assert(elem3 != nil) 82 | a.NotEqual(elem3, elem1) 83 | a.NotEqual(elem3, elem2) 84 | a.Equal(elem5, elem3) 85 | a.NotEqual(elem5, elem4) 86 | a.Equal(list.Len(), 4) 87 | a.Equal(list.Front(), elem4) 88 | a.Equal(list.Back(), elem2) 89 | a.Equal(elem5.Next(), elem2) 90 | a.Equal(elem5.Prev(), elem1) 91 | a.Equal(list.Find(15), elem5) 92 | a.Equal(list.Find(16.78), elem5) 93 | a.Equal(list.Find(16.79), elem2) 94 | a.Equal(list.FindNext(nil, 15), elem5) 95 | a.Equal(list.FindNext(nil, 16.78), elem5) 96 | a.Equal(list.FindNext(nil, 16.79), elem2) 97 | a.Equal(list.FindNext(elem1, 15), elem5) 98 | a.Equal(list.FindNext(elem5, 15), elem5) 99 | a.Equal(list.FindNext(elem5, 30), nil) 100 | 101 | min1_2 := func(a, b int) int { 102 | if a < b { 103 | return a / 2 104 | } 105 | return b / 2 106 | } 107 | a.Equal(elem5.NextLevel(0), elem5.Next()) 108 | a.Equal(elem5.NextLevel(-1), nil) 109 | a.Equal(elem5.NextLevel(min1_2(elem2.Level(), elem5.Level())), elem2) 110 | a.Equal(elem5.NextLevel(elem2.Level()), nil) 111 | a.Equal(elem5.PrevLevel(0), elem5.Prev()) 112 | a.Equal(elem5.PrevLevel(min1_2(elem1.Level(), elem5.Level())), elem1) 113 | a.Equal(elem5.PrevLevel(-1), nil) 114 | 115 | a.Assert(list.Remove(9999) == nil) 116 | a.Equal(list.Len(), 4) 117 | a.Assert(list.Remove(13.24) == nil) 118 | a.Equal(list.Len(), 4) 119 | 120 | assertSanity(a, list) 121 | 122 | list.SetMaxLevel(1) 123 | assertSanity(a, list) 124 | list.SetMaxLevel(128) 125 | assertSanity(a, list) 126 | list.SetMaxLevel(32) 127 | assertSanity(a, list) 128 | list.SetMaxLevel(32) 129 | assertSanity(a, list) 130 | 131 | elem2Removed := list.Remove(elem2.Key()) 132 | a.Assert(elem2Removed != nil) 133 | a.Equal(elem2Removed, elem2) 134 | a.Assert(elem2Removed.Prev() == nil) 135 | a.Assert(elem2Removed.Next() == nil) 136 | a.Equal(list.Len(), 3) 137 | a.Equal(list.Front(), elem4) 138 | a.Equal(list.Back(), elem5) 139 | a.Equal(list.Find(-99), elem4) 140 | a.Equal(list.Find(10), elem1) 141 | a.Equal(list.Find(15), elem3) 142 | a.Equal(list.Find(20), nil) 143 | 144 | assertSanity(a, list) 145 | 146 | front := list.RemoveFront() 147 | a.Assert(front == elem4) 148 | a.Equal(list.Len(), 2) 149 | a.Equal(list.Front(), elem1) 150 | a.Equal(list.Back(), elem5) 151 | a.Equal(list.Find(-99), elem1) 152 | 153 | back := list.RemoveBack() 154 | a.Assert(back == elem5) 155 | a.Equal(list.Len(), 1) 156 | a.Equal(list.Front(), elem1) 157 | a.Equal(list.Back(), elem1) 158 | a.Equal(list.Find(15), nil) 159 | a.Equal(list.FindNext(nil, 10), elem1) 160 | a.Equal(list.FindNext(elem1, 10), elem1) 161 | a.Equal(list.FindNext(nil, 15), nil) 162 | 163 | assertSanity(a, list) 164 | 165 | list.Init() 166 | a.Equal(list.Len(), 0) 167 | a.Equal(list.Get(12.34), nil) 168 | } 169 | 170 | type testCustomComparable struct { 171 | High, Low int 172 | } 173 | 174 | func TestCustomComparable(t *testing.T) { 175 | a := assert.New(t) 176 | comparable := GreaterThanFunc(func(k1, k2 interface{}) int { 177 | v1 := k1.(*testCustomComparable) 178 | v2 := k2.(*testCustomComparable) 179 | 180 | if v1.High > v2.High { 181 | return 1 182 | } 183 | 184 | if v1.High < v2.High { 185 | return -1 186 | } 187 | 188 | if v1.Low > v2.Low { 189 | return 1 190 | } 191 | 192 | if v1.Low < v2.Low { 193 | return -1 194 | } 195 | 196 | return 0 197 | }) 198 | k1 := &testCustomComparable{10, 10} 199 | k2 := &testCustomComparable{10, 7} 200 | k3 := &testCustomComparable{11, 3} 201 | 202 | list := New(comparable) 203 | list.Set(k1, "k1") 204 | list.Set(k2, "k2") 205 | list.Set(k3, "k3") 206 | 207 | a.Equal(list.Front(), list.Get(k2)) 208 | a.Equal(list.Back(), list.Get(k3)) 209 | a.Equal(list.Find(k1), list.Get(k1)) 210 | a.Equal(list.Find(k2), list.Get(k2)) 211 | a.Equal(list.Find(k3), list.Get(k3)) 212 | a.Equal(list.Find(&testCustomComparable{High: 0, Low: 0}), list.Get(k2)) 213 | a.Equal(list.Find(&testCustomComparable{High: 99, Low: 99}), nil) 214 | a.Equal(list.FindNext(nil, k1), list.Get(k1)) 215 | a.Equal(list.FindNext(list.Get(k2), k1), list.Get(k1)) 216 | a.Equal(list.FindNext(list.Get(k3), k1), list.Get(k3)) 217 | a.Equal(list.FindNext(list.Get(k3), &testCustomComparable{High: 99, Low: 99}), nil) 218 | 219 | // Reset list to a new one. 220 | list = New(Reverse(comparable)) 221 | list.Set(k1, "k1") 222 | list.Set(k2, "k2") 223 | list.Set(k3, "k3") 224 | 225 | a.Equal(list.Front(), list.Get(k3)) 226 | a.Equal(list.Back(), list.Get(k2)) 227 | 228 | // Reset list again to a new one. 229 | list = New(LessThanFunc(comparable)) 230 | list.Set(k1, "k1") 231 | list.Set(k2, "k2") 232 | list.Set(k3, "k3") 233 | 234 | a.Equal(list.Front(), list.Get(k3)) 235 | a.Equal(list.Back(), list.Get(k2)) 236 | } 237 | 238 | func TestRandomList(t *testing.T) { 239 | a := assert.New(t) 240 | 241 | const seed = 0xa30378d2 242 | const N = 1000000 243 | source := rand.NewSource(seed) 244 | rnd := rand.New(source) 245 | list := New(Int64Desc) 246 | 247 | for i := 0; i < N; i++ { 248 | key := rnd.Intn(N) 249 | list.Set(key, i) 250 | } 251 | 252 | for i := 0; i < N; i++ { 253 | switch i % 4 { 254 | case 0: 255 | key := rnd.Intn(N) 256 | list.Remove(key) 257 | 258 | case 1: 259 | key := rnd.Intn(N) 260 | list.Set(key, i) 261 | 262 | case 2: 263 | list.RemoveBack() 264 | 265 | case 3: 266 | list.RemoveFront() 267 | } 268 | } 269 | 270 | assertSanity(a, list) 271 | } 272 | 273 | func BenchmarkDefaultWorstInserts(b *testing.B) { 274 | list := New(Int) 275 | 276 | for i := 0; i < b.N; i++ { 277 | list.Set(i, i) 278 | } 279 | } 280 | 281 | func BenchmarkDefaultBestInserts(b *testing.B) { 282 | list := New(IntDesc) 283 | 284 | for i := 0; i < b.N; i++ { 285 | var v interface{} = i 286 | list.Set(v, v) 287 | } 288 | } 289 | 290 | func BenchmarkRandomSelect(b *testing.B) { 291 | list := New(IntDesc) 292 | keys := make([]interface{}, 0, b.N) 293 | 294 | for i := 0; i < b.N; i++ { 295 | keys = append(keys, i) 296 | } 297 | 298 | rnd := rand.New(rand.NewSource(time.Now().UnixNano())) 299 | rnd.Shuffle(b.N, func(i, j int) { 300 | keys[i], keys[j] = keys[j], keys[i] 301 | }) 302 | 303 | for i := 0; i < b.N; i++ { 304 | list.Set(keys[i], i) 305 | } 306 | 307 | rnd.Shuffle(b.N, func(i, j int) { 308 | keys[i], keys[j] = keys[j], keys[i] 309 | }) 310 | 311 | b.ResetTimer() 312 | 313 | for i := 0; i < b.N; i++ { 314 | key := keys[i] 315 | list.Get(key) 316 | } 317 | } 318 | 319 | func ExampleSkipList() { 320 | // Create a skip list with int key. 321 | list := New(Int) 322 | 323 | // Add some values. Value can be anything. 324 | list.Set(12, "hello world") 325 | list.Set(34, 56) 326 | list.Set(78, 90.12) 327 | 328 | // Get element by index. 329 | elem := list.Get(34) // Value is stored in elem.Value. 330 | fmt.Println(elem.Value) // Output: 56 331 | next := elem.Next() // Get next element. 332 | prev := next.Prev() // Get previous element. 333 | fmt.Println(next.Value, prev.Value) // Output: 90.12 56 334 | 335 | // Or, directly get value just like a map 336 | val, ok := list.GetValue(34) 337 | fmt.Println(val, ok) // Output: 56 true 338 | 339 | // Find first elements with score greater or equal to key 340 | foundElem := list.Find(30) 341 | fmt.Println(foundElem.Key(), foundElem.Value) // Output: 34 56 342 | 343 | // Remove an element for key. 344 | list.Remove(34) 345 | } 346 | 347 | func ExampleGreaterThanFunc() { 348 | type T struct { 349 | Rad float64 350 | } 351 | list := New(GreaterThanFunc(func(k1, k2 interface{}) int { 352 | s1 := math.Sin(k1.(T).Rad) 353 | s2 := math.Sin(k2.(T).Rad) 354 | 355 | if s1 > s2 { 356 | return 1 357 | } else if s1 < s2 { 358 | return -1 359 | } 360 | 361 | return 0 362 | })) 363 | list.Set(T{math.Pi / 8}, "sin(π/8)") 364 | list.Set(T{math.Pi / 2}, "sin(π/2)") 365 | list.Set(T{math.Pi}, "sin(π)") 366 | 367 | fmt.Println(list.Front().Value) // Output: sin(π) 368 | fmt.Println(list.Back().Value) // Output: sin(π/2) 369 | 370 | // Output: 371 | // sin(π) 372 | // sin(π/2) 373 | } 374 | 375 | func assertSanity(a *assert.A, list *SkipList) { 376 | l := list.Len() 377 | maxLevel := len(list.levels) // Actual max level can be larger than list.MaxLevel(). 378 | cnt := 0 379 | a.Use(&l, &cnt, &maxLevel) 380 | a.Assert(l >= 0) 381 | a.Assert(maxLevel >= list.MaxLevel()) 382 | 383 | if l == 0 { 384 | return 385 | } 386 | 387 | // Collect all elements. 388 | allElems := make([]*Element, 0, l) 389 | 390 | for elem := list.Front(); elem != nil; elem = elem.Next() { 391 | allElems = append(allElems, elem) 392 | cnt++ 393 | 394 | a.Assert(elem.list == list) 395 | } 396 | 397 | a.Assert(cnt == l) 398 | a.Equal(allElems[0], list.Front()) 399 | a.Equal(allElems[l-1], list.Back()) 400 | 401 | // Score must be sorted. 402 | prevScore := allElems[0].Score() 403 | comp := list.comparable 404 | a.Use(&prevScore) 405 | 406 | for i := 1; i < l; i++ { 407 | score := allElems[i].Score() 408 | k1 := allElems[i-1].Key() 409 | k2 := allElems[i].Key() 410 | 411 | // a.Use(&i, &score, &k1, k2) 412 | a.Assert(prevScore <= score) 413 | a.Assert(comp.Compare(k1, k2) < 0) 414 | 415 | prevScore = score 416 | } 417 | 418 | // All levels are well-orgnized. 419 | for i := 0; i < maxLevel; i++ { 420 | var prev *Element 421 | elem := list.levels[i] 422 | 423 | for elem != nil { 424 | level := elem.Level() 425 | 426 | // a.Use(&i, &level) 427 | a.Assert(level > i) 428 | a.Equal(elem.PrevLevel(i), prev) 429 | 430 | prev = elem 431 | elem = elem.NextLevel(i) 432 | } 433 | } 434 | 435 | // Prev and levels must be correct. 436 | for _, elem := range allElems { 437 | if prev := elem.Prev(); prev != nil { 438 | a.Equal(prev.Next(), elem) 439 | } 440 | } 441 | } 442 | 443 | func TestUint64(t *testing.T) { 444 | a := assert.New(t) 445 | list := New(Uint64) 446 | a.Assert(list.Len() == 0) 447 | 448 | elem1 := list.Set(uint64(0xF141000000000404), "uint64-404") 449 | a.Assert(elem1 != nil) 450 | elem2 := list.Set(uint64(0xF141000000000405), "uint64-405") 451 | a.Assert(elem2 != nil) 452 | elem3 := list.Set(uint64(0xF141000000000201), "uint64-201") 453 | a.Assert(elem3 != nil) 454 | elem4 := list.Set(uint64(0xF141000000000200), "uint64-200") 455 | a.Assert(elem4 != nil) 456 | 457 | a.Assert(list.Get(uint64(0xF141000000000404)).Value == "uint64-404") 458 | a.Assert(list.Get(uint64(0xF141000000000405)).Value == "uint64-405") 459 | a.Assert(list.Get(uint64(0xF141000000000201)).Value == "uint64-201") 460 | a.Assert(list.Get(uint64(0xF141000000000200)).Value == "uint64-200") 461 | } 462 | 463 | func TestInt64(t *testing.T) { 464 | a := assert.New(t) 465 | list := New(Int64) 466 | a.Assert(list.Len() == 0) 467 | 468 | elem1 := list.Set(int64(0x2141000000000404), "int64-404") 469 | a.Assert(elem1 != nil) 470 | elem2 := list.Set(int64(0x2141000000000405), "int64-405") 471 | a.Assert(elem2 != nil) 472 | elem3 := list.Set(int64(0x2141000000000201), "int64-201") 473 | a.Assert(elem3 != nil) 474 | elem4 := list.Set(int64(0x2141000000000200), "int64-200") 475 | a.Assert(elem4 != nil) 476 | 477 | a.Assert(list.Get(int64(0x2141000000000404)).Value == "int64-404") 478 | a.Assert(list.Get(int64(0x2141000000000405)).Value == "int64-405") 479 | a.Assert(list.Get(int64(0x2141000000000201)).Value == "int64-201") 480 | a.Assert(list.Get(int64(0x2141000000000200)).Value == "int64-200") 481 | } 482 | -------------------------------------------------------------------------------- /skiplist.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Huan Du. All rights reserved. 2 | // Licensed under the MIT license that can be found in the LICENSE file. 3 | 4 | // Package skiplist implement skip list data structure. 5 | // See wikipedia for more details about this data structure. http://en.wikipedia.org/wiki/Skip_list 6 | // 7 | // Skip list is basically an ordered map. 8 | // 9 | // Here is a sample to use this package. 10 | // 11 | // // Creates a new skip list and restricts key type to int-like types. 12 | // list := skiplist.New(skiplist.Int) 13 | // 14 | // // Adds some values for keys. 15 | // list.Set(20, "Hello") 16 | // list.Set(10, "World") 17 | // list.Set(40, true) // Value type is not restricted. 18 | // list.Set(40, 1000) // Replace the of an existing element. 19 | // 20 | // // Finds elements. 21 | // e := list.Get(10) // Returns the element with the key. 22 | // _ = e.Value.(string) 23 | // v, ok := list.GetValue(20) // Directly get value of the element. If the key is not found, ok is false. 24 | // v2 := list.MustGetValue(10) // Directly get value of the element. Panic if the key is not found. 25 | // notFound := list.Get(15) // Returns nil if the key is not found. 26 | // 27 | // // Removes an element and gets removed element. 28 | // old := list.Remove(40) 29 | // notFound := list.Remove(-20) // Returns nil if the key is not found. 30 | // 31 | // // Initializes the list again to clean up all elements in the list. 32 | // list.Init() 33 | package skiplist 34 | 35 | import ( 36 | "fmt" 37 | "math/rand" 38 | "time" 39 | ) 40 | 41 | // DefaultMaxLevel is the default level for all newly created skip lists. 42 | // It can be changed globally. Changing it will not affect existing lists. 43 | // And all skip lists can update max level after creation through `SetMaxLevel()` method. 44 | var DefaultMaxLevel = 48 45 | 46 | // preallocDefaultMaxLevel is a constant to alloc memory on stack when Set new element. 47 | const preallocDefaultMaxLevel = 48 48 | 49 | // SkipList is the header of a skip list. 50 | type SkipList struct { 51 | elementHeader 52 | 53 | comparable Comparable 54 | rand *rand.Rand 55 | 56 | maxLevel int 57 | length int 58 | back *Element 59 | } 60 | 61 | // New creates a new skip list with comparable to compare keys. 62 | // 63 | // There are lots of pre-defined strict-typed keys like Int, Float64, String, etc. 64 | // We can create custom comparable by implementing Comparable interface. 65 | func New(comparable Comparable) *SkipList { 66 | if DefaultMaxLevel <= 0 { 67 | panic("skiplist default level must not be zero or negative") 68 | } 69 | 70 | source := rand.NewSource(time.Now().UnixNano()) 71 | return &SkipList{ 72 | elementHeader: elementHeader{ 73 | levels: make([]*Element, DefaultMaxLevel), 74 | }, 75 | 76 | comparable: comparable, 77 | rand: rand.New(source), 78 | 79 | maxLevel: DefaultMaxLevel, 80 | } 81 | } 82 | 83 | // Init resets the list and discards all existing elements. 84 | func (list *SkipList) Init() *SkipList { 85 | list.back = nil 86 | list.length = 0 87 | list.levels = make([]*Element, len(list.levels)) 88 | return list 89 | } 90 | 91 | // SetRandSource sets a new rand source. 92 | // 93 | // Skiplist uses global rand defined in math/rand by default. 94 | // The default rand acquires a global mutex before generating any number. 95 | // It's not necessary if the skiplist is well protected by caller. 96 | func (list *SkipList) SetRandSource(source rand.Source) { 97 | list.rand = rand.New(source) 98 | } 99 | 100 | // Front returns the first element. 101 | // 102 | // The complexity is O(1). 103 | func (list *SkipList) Front() *Element { 104 | return list.levels[0] 105 | } 106 | 107 | // Back returns the last element. 108 | // 109 | // The complexity is O(1). 110 | func (list *SkipList) Back() *Element { 111 | return list.back 112 | } 113 | 114 | // Len returns element count in this list. 115 | // 116 | // The complexity is O(1). 117 | func (list *SkipList) Len() int { 118 | return list.length 119 | } 120 | 121 | // Set sets value for the key. 122 | // If the key exists, updates element's value. 123 | // Returns the element holding the key and value. 124 | // 125 | // The complexity is O(log(N)). 126 | func (list *SkipList) Set(key, value interface{}) (elem *Element) { 127 | score := list.calcScore(key) 128 | 129 | // Happy path for empty list. 130 | if list.length == 0 { 131 | level := list.randLevel() 132 | elem = newElement(list, level, score, key, value) 133 | 134 | for i := 0; i < level; i++ { 135 | list.levels[i] = elem 136 | } 137 | 138 | list.back = elem 139 | list.length++ 140 | return 141 | } 142 | 143 | // Find out previous elements on every possible levels. 144 | max := len(list.levels) 145 | prevHeader := &list.elementHeader 146 | 147 | var maxStaticAllocElemHeaders [preallocDefaultMaxLevel]*elementHeader 148 | var prevElemHeaders []*elementHeader 149 | 150 | if max <= preallocDefaultMaxLevel { 151 | prevElemHeaders = maxStaticAllocElemHeaders[:max] 152 | } else { 153 | prevElemHeaders = make([]*elementHeader, max) 154 | } 155 | 156 | for i := max - 1; i >= 0; { 157 | prevElemHeaders[i] = prevHeader 158 | 159 | for next := prevHeader.levels[i]; next != nil; next = prevHeader.levels[i] { 160 | if comp := list.compare(score, key, next); comp <= 0 { 161 | // Find the elem with the same key. 162 | // Update value and return the elem. 163 | if comp == 0 { 164 | elem = next 165 | elem.Value = value 166 | return 167 | } 168 | 169 | break 170 | } 171 | 172 | prevHeader = &next.elementHeader 173 | prevElemHeaders[i] = prevHeader 174 | } 175 | 176 | // Skip levels if they point to the same element as topLevel. 177 | topLevel := prevHeader.levels[i] 178 | 179 | for i--; i >= 0 && prevHeader.levels[i] == topLevel; i-- { 180 | prevElemHeaders[i] = prevHeader 181 | } 182 | } 183 | 184 | // Create a new element. 185 | level := list.randLevel() 186 | elem = newElement(list, level, score, key, value) 187 | 188 | // Set up prev element. 189 | if prev := prevElemHeaders[0]; prev != &list.elementHeader { 190 | elem.prev = prev.Element() 191 | } 192 | 193 | // Set up prevTopLevel. 194 | if prev := prevElemHeaders[level-1]; prev != &list.elementHeader { 195 | elem.prevTopLevel = prev.Element() 196 | } 197 | 198 | // Set up levels. 199 | for i := 0; i < level; i++ { 200 | elem.levels[i] = prevElemHeaders[i].levels[i] 201 | prevElemHeaders[i].levels[i] = elem 202 | } 203 | 204 | // Find out the largest level with next element. 205 | largestLevel := 0 206 | 207 | for i := level - 1; i >= 0; i-- { 208 | if elem.levels[i] != nil { 209 | largestLevel = i + 1 210 | break 211 | } 212 | } 213 | 214 | // Adjust prev and prevTopLevel of next elements. 215 | if next := elem.levels[0]; next != nil { 216 | next.prev = elem 217 | } 218 | 219 | for i := 0; i < largestLevel; { 220 | next := elem.levels[i] 221 | nextLevel := next.Level() 222 | 223 | if nextLevel <= level { 224 | next.prevTopLevel = elem 225 | } 226 | 227 | i = nextLevel 228 | } 229 | 230 | // If the elem is the last element, set it as back. 231 | if elem.Next() == nil { 232 | list.back = elem 233 | } 234 | 235 | list.length++ 236 | return 237 | } 238 | 239 | func (list *SkipList) findNext(start *Element, score float64, key interface{}) (elem *Element) { 240 | if list.length == 0 { 241 | return 242 | } 243 | 244 | if start == nil && list.compare(score, key, list.Front()) <= 0 { 245 | elem = list.Front() 246 | return 247 | } 248 | if start != nil && list.compare(score, key, start) <= 0 { 249 | elem = start 250 | return 251 | } 252 | if list.compare(score, key, list.Back()) > 0 { 253 | return 254 | } 255 | 256 | var prevHeader *elementHeader 257 | if start == nil { 258 | prevHeader = &list.elementHeader 259 | } else { 260 | prevHeader = &start.elementHeader 261 | } 262 | i := len(prevHeader.levels) - 1 263 | 264 | // Find out previous elements on every possible levels. 265 | for i >= 0 { 266 | for next := prevHeader.levels[i]; next != nil; next = prevHeader.levels[i] { 267 | if comp := list.compare(score, key, next); comp <= 0 { 268 | elem = next 269 | if comp == 0 { 270 | return 271 | } 272 | 273 | break 274 | } 275 | 276 | prevHeader = &next.elementHeader 277 | } 278 | 279 | topLevel := prevHeader.levels[i] 280 | 281 | // Skip levels if they point to the same element as topLevel. 282 | for i--; i >= 0 && prevHeader.levels[i] == topLevel; i-- { 283 | } 284 | } 285 | 286 | return 287 | } 288 | 289 | // FindNext returns the first element after start that is greater or equal to key. 290 | // If start is greater or equal to key, returns start. 291 | // If there is no such element, returns nil. 292 | // If start is nil, find element from front. 293 | // 294 | // The complexity is O(log(N)). 295 | func (list *SkipList) FindNext(start *Element, key interface{}) (elem *Element) { 296 | return list.findNext(start, list.calcScore(key), key) 297 | } 298 | 299 | // Find returns the first element that is greater or equal to key. 300 | // It's short hand for FindNext(nil, key). 301 | // 302 | // The complexity is O(log(N)). 303 | func (list *SkipList) Find(key interface{}) (elem *Element) { 304 | return list.FindNext(nil, key) 305 | } 306 | 307 | // Get returns an element with the key. 308 | // If the key is not found, returns nil. 309 | // 310 | // The complexity is O(log(N)). 311 | func (list *SkipList) Get(key interface{}) (elem *Element) { 312 | score := list.calcScore(key) 313 | 314 | firstElem := list.findNext(nil, score, key) 315 | if firstElem == nil { 316 | return 317 | } 318 | 319 | if list.compare(score, key, firstElem) != 0 { 320 | return 321 | } 322 | 323 | elem = firstElem 324 | return 325 | } 326 | 327 | // GetValue returns value of the element with the key. 328 | // It's short hand for Get().Value. 329 | // 330 | // The complexity is O(log(N)). 331 | func (list *SkipList) GetValue(key interface{}) (val interface{}, ok bool) { 332 | element := list.Get(key) 333 | 334 | if element == nil { 335 | return 336 | } 337 | 338 | val = element.Value 339 | ok = true 340 | return 341 | } 342 | 343 | // MustGetValue returns value of the element with the key. 344 | // It will panic if the key doesn't exist in the list. 345 | // 346 | // The complexity is O(log(N)). 347 | func (list *SkipList) MustGetValue(key interface{}) interface{} { 348 | element := list.Get(key) 349 | 350 | if element == nil { 351 | panic(fmt.Errorf("skiplist: cannot find key `%v` in skiplist", key)) 352 | } 353 | 354 | return element.Value 355 | } 356 | 357 | // Remove removes an element. 358 | // Returns removed element pointer if found, nil if it's not found. 359 | // 360 | // The complexity is O(log(N)). 361 | func (list *SkipList) Remove(key interface{}) (elem *Element) { 362 | elem = list.Get(key) 363 | 364 | if elem == nil { 365 | return 366 | } 367 | 368 | list.RemoveElement(elem) 369 | return 370 | } 371 | 372 | // RemoveFront removes front element node and returns the removed element. 373 | // 374 | // The complexity is O(1). 375 | func (list *SkipList) RemoveFront() (front *Element) { 376 | if list.length == 0 { 377 | return 378 | } 379 | 380 | front = list.Front() 381 | list.RemoveElement(front) 382 | return 383 | } 384 | 385 | // RemoveBack removes back element node and returns the removed element. 386 | // 387 | // The complexity is O(log(N)). 388 | func (list *SkipList) RemoveBack() (back *Element) { 389 | if list.length == 0 { 390 | return 391 | } 392 | 393 | back = list.back 394 | list.RemoveElement(back) 395 | return 396 | } 397 | 398 | // RemoveElement removes the elem from the list. 399 | // 400 | // The complexity is O(log(N)). 401 | func (list *SkipList) RemoveElement(elem *Element) { 402 | if elem == nil || elem.list != list { 403 | return 404 | } 405 | 406 | level := elem.Level() 407 | 408 | // Find out all previous elements. 409 | max := 0 410 | prevElems := make([]*Element, level) 411 | prev := elem.prev 412 | 413 | for prev != nil && max < level { 414 | prevLevel := len(prev.levels) 415 | 416 | for ; max < prevLevel && max < level; max++ { 417 | prevElems[max] = prev 418 | } 419 | 420 | for prev = prev.prevTopLevel; prev != nil && prev.Level() == prevLevel; prev = prev.prevTopLevel { 421 | } 422 | } 423 | 424 | // Adjust prev elements which point to elem directly. 425 | for i := 0; i < max; i++ { 426 | prevElems[i].levels[i] = elem.levels[i] 427 | } 428 | 429 | for i := max; i < level; i++ { 430 | list.levels[i] = elem.levels[i] 431 | } 432 | 433 | // Adjust prev and prevTopLevel of next elements. 434 | if next := elem.Next(); next != nil { 435 | next.prev = elem.prev 436 | } 437 | 438 | for i := 0; i < level; { 439 | next := elem.levels[i] 440 | 441 | if next == nil || next.prevTopLevel != elem { 442 | break 443 | } 444 | 445 | i = next.Level() 446 | next.prevTopLevel = prevElems[i-1] 447 | } 448 | 449 | // Adjust list.Back() if necessary. 450 | if list.back == elem { 451 | list.back = elem.prev 452 | } 453 | 454 | list.length-- 455 | elem.reset() 456 | } 457 | 458 | // MaxLevel returns current max level value. 459 | func (list *SkipList) MaxLevel() int { 460 | return list.maxLevel 461 | } 462 | 463 | // SetMaxLevel changes skip list max level. 464 | // If level is not greater than 0, just panic. 465 | func (list *SkipList) SetMaxLevel(level int) (old int) { 466 | if level <= 0 { 467 | panic(fmt.Errorf("skiplist: level must be larger than 0 (current is %v)", level)) 468 | } 469 | 470 | list.maxLevel = level 471 | old = len(list.levels) 472 | 473 | if level == old { 474 | return 475 | } 476 | 477 | if old > level { 478 | for i := old - 1; i >= level; i-- { 479 | if list.levels[i] != nil { 480 | level = i 481 | break 482 | } 483 | } 484 | 485 | list.levels = list.levels[:level] 486 | return 487 | } 488 | 489 | if level <= cap(list.levels) { 490 | list.levels = list.levels[:level] 491 | return 492 | } 493 | 494 | levels := make([]*Element, level) 495 | copy(levels, list.levels) 496 | list.levels = levels 497 | return 498 | } 499 | 500 | func (list *SkipList) randLevel() int { 501 | estimated := list.maxLevel 502 | const prob = 1 << 30 // Half of 2^31. 503 | rand := list.rand 504 | i := 1 505 | 506 | for ; i < estimated; i++ { 507 | if rand.Int31() < prob { 508 | break 509 | } 510 | } 511 | 512 | return i 513 | } 514 | 515 | // compare compares value of two elements and returns -1, 0 and 1. 516 | func (list *SkipList) compare(score float64, key interface{}, rhs *Element) int { 517 | if score != rhs.score { 518 | if score > rhs.score { 519 | return 1 520 | } else if score < rhs.score { 521 | return -1 522 | } 523 | 524 | return 0 525 | } 526 | 527 | return list.comparable.Compare(key, rhs.key) 528 | } 529 | 530 | func (list *SkipList) calcScore(key interface{}) (score float64) { 531 | score = list.comparable.CalcScore(key) 532 | return 533 | } 534 | --------------------------------------------------------------------------------