跳跃表Golang版本

2023-08-20
1分钟阅读时长

跳跃表

import (
	"fmt"
	"math/rand"
	"time"
)

type Node struct {
	key                   int
	value                 interface{}
	up, down, left, right *Node
	level                 int
}

func newNode(k int, v interface{}) *Node {
	return &Node{
		key:   k,
		value: v,
	}
}

func (n *Node) equals(node *Node) bool {
	if node == nil {
		return false
	}
	if n.key != node.key {

		return false
	}
	if n.value != node.value {

		return false
	}
	if n.level != node.level {
		return false
	}
	return true
}

// 实现跳跃表
type jumpTable struct {
	header *Node
	r      *rand.Rand
}

func New() *jumpTable {
	return &jumpTable{
		r:      rand.New(rand.NewSource(time.Now().UnixNano())),
		header: newNode(-int(^uint(0)>>1), nil),
	}
}

func println(input string) {
	return fmt.Println(input)
}

func (jt *jumpTable) Search(k int) *Node {
	println("walkPreviousNode")
	node, count := walkPreviousNode(jt.header, k)
	println("共需要", count, "步")
	return node
}

func (jt *jumpTable) Insert(k int, v interface{}) {
	sn := jt.header
	newN := newNode(k, v)
	node, _ := walkPreviousNode(sn, k)
	if node.key == k {

		node.value = v
		return
	}
	currentLevel := 0
	newN.level = currentLevel
	jt.setNode(newN, node)
	lowNode := newN
	for jt.isPromotion() {
		println("isPromotion")
		currentLevel++
		upNewN := setUpNewDownNode(currentLevel, k, newN)
		if jt.header.level < currentLevel {
			updateHeader(jt, upNewN)
		}
		leftUpNode := findLeftUpNode(lowNode, upNewN)
		if leftUpNode != nil {
			jt.setNode(upNewN, leftUpNode)
		}
		newN = upNewN
	}
}

func updateHeader(jt *jumpTable, upNew *Node) {
	jt.header = upNew
}

func setUpNewDownNode(level int, k int, v interface{}, newN *Node) *Node {
	upNew := newNode(k, v)
	upNew.level = level
	newN.up = upNew
	upNew.down = newN
	return upNew
}

func findLeftUpNode(newN *Node, upNew *Node) *Node {
	var leftUpNode *Node
	leftNewNode := newN.left
leftBreak:
	for leftNewNode != nil {
		leftNewUpNode := leftNewNode.up
		for leftNewUpNode != nil {
			if leftNewUpNode.level == upNew.level {

				leftUpNode = leftNewUpNode
				break leftBreak
			}
			leftNewNode = leftNewNode.left
		}
	}
	return leftUpNode
}

func (jt *jumpTable) setNode(q *Node, p *Node) {
	q.left = p
	if p.right != nil {
		q.right = p.right
		p.right.left = q
	}
	p.right = q
}

func walkPreviousNode(curNode *Node, k int) (*Node, int) {
	println("k:", k, " level", curNode.level)
	count := 0
	for curNode.key < k {
		count++
		if curNode.right == nil {
			break
		}
		println("curNode.key < k ", curNode.key, "-->", curNode.right.key)
		curNode = curNode.right
	}
	for curNode.key > k {
		count++
		if curNode.left == nil {
			break
		}
		println("curNode.key > k ", curNode.key, "-->", curNode.left.key)
		curNode = curNode.left
	}
	if curNode.down != nil {
		var newCount int
		println("curNode.down ", curNode.key, "-->", curNode.down.key)
		curNode, newCount = walkPreviousNode(curNode.down, k)
		count += newCount
	}
	return curNode, count
}

func (jt *jumpTable) isPromotion() bool {
	n := jt.r.Intn(2)
	if n == 0 {
		return false
	}
	return true
}

本主题指南

技术实践与开发文档
  • 深入探究一下Kubernetes Operator Pattern,为CustomResourceDefinition使用贡献有效经验

    Kubernetes让部署和无感知扩容变的异常简单。如果实操,基本上只需要在YAML文件中把相关联的应用的参数做下指定即可,然后提交给Kubernetes系统识别你的声明式指令,Kubernetes内建的状态循环机制就会自动的创建或者销毁相应资源,来把集群调整到我预设的状态上来,一切都如此轻松!

  • 如何从头创建一个KubernetesOperator

    对于什么是`controller`什么是`operator`可能大家有比较多的迷惑,特别对于你不是做`Kubernetes`领域相关工作的,可能就更像听天书。简明扼要给出我的理解,`operators`是一种特别的`controller`。区别在于`operators`中针对于`controller`可能会包含进更多特定的负载相关的知识。 那么下个问题就出现了,什么是`controller`?

  • Client Go四种交互模式之 DynamicClient实战案例详解

    Client Go四种交互模式之 DynamicClient实战案例详解

  • 对于kubernetes体系课的录制自己的一些思考

    由于天天要搞的事情太多,所以准备录云原生kubernetes课程的事情一拖再拖!但好消息是这个周末终于录了网络接口(CNI)第三方厂商中的佼佼者flannel和calico的实践!以及istio的实践!虽然都只是一部分,但是能迈出这一步,感觉已经是巨大的进步了,因为如果找借口可能天天都有借口,但是时间嘛,挤一挤总是有的!

Avatar

Aisen

Be water,my friend.