1. 程式人生 > 實用技巧 >Golang 實現跳錶(暫未加讀寫鎖)

Golang 實現跳錶(暫未加讀寫鎖)

package main

import (
    "errors"
    "math/rand"
)

type CompareResult int
// TODO 目前尚未實現併發安全,待辦

const (
    // 跳錶節點key的比較回撥函式返回值 -1:left<right;0:left==right;1:left>right
    LEFT_LT_RIGHT CompareResult = -1
    LEFT_EQ_RIGHT CompareResult = 0
    LEFT_GT_RIGHT CompareResult = 1

    SKIP_LIST_MAX_LEVEL  
= 32 // 跳錶首節點最高層數 SKIP_LIST_INIT_LEVEL = 3 // 跳錶初始化時首節點的可用層級數 P = 0.25 // Redis的跳錶使用的概率 ) // 檢查鍵的合法性 func NilCheck(element interface{}) error { if element == nil { return errors.New("element is nil") } return nil } type ISkipList interface { IsEmpty() bool Size() int Get(key
interface{}) (interface{}, error) Set(key interface{}, value interface{}) (interface{}, error) Remove(key interface{}) (interface{}, error) } type SkipList struct { compareCallBack func(left interface{}, right interface{}) CompareResult header skipListNode // 跳錶首節點,不存放任何值 size int
// 跳錶元素個數 level int // 當前跳錶層級 } type skipListNode struct { key interface{} value interface{} next []*skipListNode // Next元素個數最多32(參考redis) } func NewSkipList(compareCallBack func(left interface{}, right interface{}) CompareResult) (ISkipList, error) { if err := NilCheck(compareCallBack); err != nil { return nil, err } skipList := new(SkipList) skipList.compareCallBack = compareCallBack //設定回撥函式 skipList.header.next = make([]*skipListNode, SKIP_LIST_MAX_LEVEL) // 設定跳錶層級索引指標 return skipList, nil } func (sl *SkipList) IsEmpty() bool { return sl.size == 0 } func (sl *SkipList) Size() int { return sl.size } func (sl *SkipList) Get(key interface{}) (interface{}, error) { if err := NilCheck(sl.compareCallBack); err != nil { return nil, err } if err := NilCheck(key); err != nil { return nil, err } node := sl.header for level := sl.level - 1; level >= 0; level-- { for node.next != nil { if node.next[level] == nil { break } nodeKey := node.next[level].key if sl.compareCallBack(key, nodeKey) == LEFT_GT_RIGHT { node = *node.next[level] } else if sl.compareCallBack(key, nodeKey) == LEFT_EQ_RIGHT { return node.next[level].value, nil } else { break } } } return nil, nil } func (sl *SkipList) Set(key interface{}, value interface{}) (interface{}, error) { if err := NilCheck(sl.compareCallBack); err != nil { return nil, err } if err := NilCheck(key); err != nil { return nil, err } node := sl.header prevNodeArr := make([]skipListNode, sl.level) // 用來儲存前驅節點的陣列 for level := sl.level - 1; level >= 0; level-- { for node.next != nil { if node.next[level] == nil { break } nodeKey := node.next[level].key if sl.compareCallBack(key, nodeKey) == LEFT_GT_RIGHT { node = *node.next[level] } else if sl.compareCallBack(key, nodeKey) == LEFT_EQ_RIGHT { // 節點存在,覆蓋掉並返回原來的值就ok tempValue := node.next[level].value node.next[level].value = value return tempValue, nil } else { break } } // 儲存前驅節點 prevNodeArr[level] = node } // 節點不存在,新建立一個節點 newNode := new(skipListNode) // 節點元素層數定義隨機,利用拋硬幣來實現 newNode.key = key newNode.value = value newLevel := randomLevel() newNode.next = make([]*skipListNode, newLevel) // 設定前驅和後繼 for i := 0; i < newLevel; i++ { if i >= sl.level { // 如果level增加了 sl.header.next[i] = newNode } else { newNode.next[i] = prevNodeArr[i].next[i] prevNodeArr[i].next[i] = newNode } } // 節點數量和跳錶層級修改 sl.size++ if newLevel > sl.level { sl.level = newLevel } return value, nil } func (sl *SkipList) Remove(key interface{}) (interface{}, error) { if err := NilCheck(sl.compareCallBack); err != nil { return nil, err } if err := NilCheck(key); err != nil { return nil, err } node := sl.header prevNodeArr := make([]skipListNode, sl.level) // 用來儲存前驅節點的陣列 exists := false for level := sl.level - 1; level >= 0; level-- { for node.next != nil { if node.next[level] == nil { break } nodeKey := node.next[level].key if sl.compareCallBack(key, nodeKey) == LEFT_GT_RIGHT { node = *node.next[level] } else if sl.compareCallBack(key, nodeKey) == LEFT_EQ_RIGHT { // 節點存在 exists = true } else { break } } // 儲存前驅節點 prevNodeArr[level] = node } if !exists { return nil, nil } // 節點存在,刪除此節點 deletedNode := node.next[0] // 設定前驅和後繼 for i := 0; i < sl.level; i++ { prevNodeArr[i].next[i] = deletedNode.next[i] } // 節點數量和跳錶層級修改 sl.size-- for i := sl.level - 1; i >= 0; i-- { if sl.header.next[i] != nil { sl.level = i + 1 break } } return deletedNode.value, nil } func randomLevel() int { level := 1 for rand.Float64() < P && level < SKIP_LIST_MAX_LEVEL { level++ } return level } func intCallBack(left interface{}, right interface{}) CompareResult { if left.(int) > right.(int) { return LEFT_GT_RIGHT } else if left.(int) == right.(int) { return LEFT_EQ_RIGHT } else { return LEFT_LT_RIGHT } } func main() { testSkipList, _ := NewSkipList(intCallBack) testSkipList.Set(1, 12) testSkipList.Set(2, 23) testSkipList.Set(4, 34) testSkipList.Set(5, 45) testSkipList.Set(7, 45) testSkipList.Set(9, 45) testSkipList.Set(-1, 45) testSkipList.Set(100, 45) testSkipList.Set(34, 45) testSkipList.Set(101, 45) testSkipList.Set(200, 45) }