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 57 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 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
|
package skip
import (
"fmt"
"math/rand"
"time"
)
type (
node struct {
next []*node
key interface{}
value interface{}
}
SkipList struct {
root *node
size int
less func(interface{},interface{})bool
gen *rand.Rand
probability float64
}
)
// Create a new skip list
func New(less func(interface{},interface{})bool) *SkipList {
gen := rand.New(rand.NewSource(time.Now().UnixNano()))
n := &node{make([]*node, 0),nil,nil}
return &SkipList{n, 0, less, gen, 0.75}
}
func (this *SkipList) Do(f func(interface{}, interface{})bool) {
if this.size == 0 {
return
}
cur := this.root.next[0]
for cur != nil {
if !f(cur.key, cur.value) {
break
}
cur = cur.next[0]
}
}
// Get an item from the skip list
func (this *SkipList) Get(key interface{}) interface{} {
if this.size == 0 {
return nil
}
cur := this.root
// Start at the top
for i := len(cur.next)-1; i >= 0; i-- {
for this.less(cur.next[i].key, key) {
cur = cur.next[i]
}
}
cur = cur.next[0]
if this.equals(cur.key, key) {
return cur.value
}
return nil
}
// Insert a new item into the skip list
func (this *SkipList) Insert(key interface{}, value interface{}) {
prev := this.getPrevious(key)
// Already in the list so just update the value
if len(prev) > 0 && prev[0].next[0] != nil && this.equals(prev[0].next[0].key, key) {
prev[0].next[0].value = value
return
}
h := len(this.root.next)
nh := this.pickHeight()
n := &node{make([]*node, nh),key,value}
// Higher than anything seen before, so tack it on top
if nh > h {
this.root.next = append(this.root.next, n)
}
// Update the previous nodes
for i := 0; i < h && i < nh; i++ {
n.next[i] = prev[i].next[i]
prev[i].next[i] = n
}
this.size++
}
// Get the length of the skip list
func (this *SkipList) Len() int {
return this.size
}
// Remove an item from the skip list
func (this *SkipList) Remove(key interface{}) interface{} {
prev := this.getPrevious(key)
if len(prev) == 0 {
return nil
}
cur := prev[0].next[0]
// If we found it
if cur != nil && this.equals(key, cur.key) {
// Change all the linked lists
for i := 0; i < len(prev); i++ {
if prev[i] != nil && prev[i].next[i] != nil {
prev[i].next[i] = cur.next[i]
}
}
// Kill off the upper links if they're nil
for i := len(this.root.next)-1; i>=0; i-- {
if this.root.next[i] == nil {
this.root.next = this.root.next[:i]
} else {
break
}
}
this.size--
return cur.value
}
return nil
}
// String representation of the list
func (this *SkipList) String() string {
str := "{"
if len(this.root.next) > 0 {
cur := this.root.next[0]
for cur != nil {
str += fmt.Sprint(cur.key)
str += ":"
str += fmt.Sprint(cur.value)
str += " "
cur = cur.next[0]
}
}
str += "}"
return str
}
// Get a vertical list of nodes of all the things that occur
// immediately before "key"
func (this *SkipList) getPrevious(key interface{}) []*node {
cur := this.root
h := len(cur.next)
nodes := make([]*node, h)
for i := h-1; i >= 0; i-- {
for cur.next[i] != nil && this.less(cur.next[i].key, key) {
cur = cur.next[i]
}
nodes[i] = cur
}
return nodes
}
// Defines an equals method in terms of "less"
func (this *SkipList) equals(a, b interface{}) bool {
return !this.less(a,b) && !this.less(b,a)
}
// Pick a random height
func (this *SkipList) pickHeight() int {
h := 1
for this.gen.Float64() > this.probability {
h++
}
if h > len(this.root.next) {
return h + 1
}
return h
}
|