ziggs/vendor/github.com/plar/go-adaptive-radix-tree/tree.go

239 lines
5.2 KiB
Go

package art
type tree struct {
// version field is updated by each tree modification
version int
root *artNode
size int
}
// make sure that tree implements all methods from the Tree interface
var _ Tree = &tree{}
func (t *tree) Insert(key Key, value Value) (Value, bool) {
oldValue, updated := t.recursiveInsert(&t.root, key, value, 0)
if !updated {
t.version++
t.size++
}
return oldValue, updated
}
func (t *tree) Delete(key Key) (Value, bool) {
value, deleted := t.recursiveDelete(&t.root, key, 0)
if deleted {
t.version++
t.size--
return value, true
}
return nil, false
}
func (t *tree) Search(key Key) (Value, bool) {
current := t.root
depth := uint32(0)
for current != nil {
if current.isLeaf() {
leaf := current.leaf()
if leaf.match(key) {
return leaf.value, true
}
return nil, false
}
curNode := current.node()
if curNode.prefixLen > 0 {
prefixLen := current.match(key, depth)
if prefixLen != min(curNode.prefixLen, MaxPrefixLen) {
return nil, false
}
depth += curNode.prefixLen
}
next := current.findChild(key.charAt(int(depth)), key.valid(int(depth)))
if *next != nil {
current = *next
} else {
current = nil
}
depth++
}
return nil, false
}
func (t *tree) Minimum() (value Value, found bool) {
if t == nil || t.root == nil {
return nil, false
}
leaf := t.root.minimum()
return leaf.value, true
}
func (t *tree) Maximum() (value Value, found bool) {
if t == nil || t.root == nil {
return nil, false
}
leaf := t.root.maximum()
return leaf.value, true
}
func (t *tree) Size() int {
if t == nil || t.root == nil {
return 0
}
return t.size
}
func (t *tree) recursiveInsert(curNode **artNode, key Key, value Value, depth uint32) (Value, bool) {
current := *curNode
if current == nil {
replaceRef(curNode, factory.newLeaf(key, value))
return nil, false
}
if current.isLeaf() {
leaf := current.leaf()
// update exists value
if leaf.match(key) {
oldValue := leaf.value
leaf.value = value
return oldValue, true
}
// new value, split the leaf into new node4
newLeaf := factory.newLeaf(key, value)
leaf2 := newLeaf.leaf()
leafsLCP := t.longestCommonPrefix(leaf, leaf2, depth)
newNode := factory.newNode4()
newNode.setPrefix(key[depth:], leafsLCP)
depth += leafsLCP
newNode.addChild(leaf.key.charAt(int(depth)), leaf.key.valid(int(depth)), current)
newNode.addChild(leaf2.key.charAt(int(depth)), leaf2.key.valid(int(depth)), newLeaf)
replaceRef(curNode, newNode)
return nil, false
}
node := current.node()
if node.prefixLen > 0 {
prefixMismatchIdx := current.matchDeep(key, depth)
if prefixMismatchIdx >= node.prefixLen {
depth += node.prefixLen
goto NEXT_NODE
}
newNode := factory.newNode4()
node4 := newNode.node()
node4.prefixLen = prefixMismatchIdx
for i := 0; i < int(min(prefixMismatchIdx, MaxPrefixLen)); i++ {
node4.prefix[i] = node.prefix[i]
}
if node.prefixLen <= MaxPrefixLen {
node.prefixLen -= (prefixMismatchIdx + 1)
newNode.addChild(node.prefix[prefixMismatchIdx], true, current)
for i, limit := uint32(0), min(node.prefixLen, MaxPrefixLen); i < limit; i++ {
node.prefix[i] = node.prefix[prefixMismatchIdx+i+1]
}
} else {
node.prefixLen -= (prefixMismatchIdx + 1)
leaf := current.minimum()
newNode.addChild(leaf.key.charAt(int(depth+prefixMismatchIdx)), leaf.key.valid(int(depth+prefixMismatchIdx)), current)
for i, limit := uint32(0), min(node.prefixLen, MaxPrefixLen); i < limit; i++ {
node.prefix[i] = leaf.key[depth+prefixMismatchIdx+i+1]
}
}
// Insert the new leaf
newNode.addChild(key.charAt(int(depth+prefixMismatchIdx)), key.valid(int(depth+prefixMismatchIdx)), factory.newLeaf(key, value))
replaceRef(curNode, newNode)
return nil, false
}
NEXT_NODE:
// Find a child to recursive to
next := current.findChild(key.charAt(int(depth)), key.valid(int(depth)))
if *next != nil {
return t.recursiveInsert(next, key, value, depth+1)
}
// No Child, artNode goes with us
current.addChild(key.charAt(int(depth)), key.valid(int(depth)), factory.newLeaf(key, value))
return nil, false
}
func (t *tree) recursiveDelete(curNode **artNode, key Key, depth uint32) (Value, bool) {
if t == nil || *curNode == nil || len(key) == 0 {
return nil, false
}
current := *curNode
if current.isLeaf() {
leaf := current.leaf()
if leaf.match(key) {
replaceRef(curNode, nil)
return leaf.value, true
}
return nil, false
}
node := current.node()
if node.prefixLen > 0 {
prefixLen := current.match(key, depth)
if prefixLen != min(node.prefixLen, MaxPrefixLen) {
return nil, false
}
depth += node.prefixLen
}
next := current.findChild(key.charAt(int(depth)), key.valid(int(depth)))
if *next == nil {
return nil, false
}
if (*next).isLeaf() {
leaf := (*next).leaf()
if leaf.match(key) {
current.deleteChild(key.charAt(int(depth)), key.valid(int(depth)))
return leaf.value, true
}
return nil, false
}
return t.recursiveDelete(next, key, depth+1)
}
func (t *tree) longestCommonPrefix(l1 *leaf, l2 *leaf, depth uint32) uint32 {
l1key, l2key := l1.key, l2.key
idx, limit := depth, min(uint32(len(l1key)), uint32(len(l2key)))
for ; idx < limit; idx++ {
if l1key[idx] != l2key[idx] {
break
}
}
return idx - depth
}