|
|
- package common
-
- import ()
-
- // This immutable balanced binary tree happens to be an
- // immutable AVL+ tree, adapted from tendermint/merkle.
- // Unlike that one, this is in-memory, non-merkleized,
- // and nodes can be nil to signify an empty tree.
- type IBBSTree struct {
- key uint64
- value interface{}
- size uint64
- height uint8
- left *IBBSTree
- right *IBBSTree
- }
-
- // Creates an empty tree.
- func NewIBBSTree() *IBBSTree {
- return nil
- }
-
- // Creates a single tree node from key and value.
- func NewIBBSTreeNode(key uint64, value interface{}) *IBBSTree {
- return &IBBSTree{
- key: key,
- value: value,
- size: 1,
- }
- }
-
- func (self *IBBSTree) Copy() *IBBSTree {
- if self == nil {
- return nil
- }
- return &IBBSTree{
- key: self.key,
- value: self.value,
- size: self.size,
- height: self.height,
- left: self.left,
- right: self.right,
- }
- }
-
- func (self *IBBSTree) Size() uint64 {
- if self == nil {
- return 0
- }
- return self.size
- }
-
- func (self *IBBSTree) Height() uint8 {
- if self == nil {
- return 0
- }
- return self.height
- }
-
- func (self *IBBSTree) Has(key uint64) (has bool) {
- if self == nil {
- return false
- }
- if self.key == key {
- return true
- }
- if self.height == 0 {
- return false
- } else {
- if key < self.key {
- return self.left.Has(key)
- } else {
- return self.right.Has(key)
- }
- }
- }
-
- func (self *IBBSTree) Get(key uint64) (value interface{}) {
- if self == nil {
- return nil
- }
- if self.height == 0 {
- if self.key == key {
- return self.value
- } else {
- return nil
- }
- } else {
- if key < self.key {
- return self.left.Get(key)
- } else {
- return self.right.Get(key)
- }
- }
- }
-
- func (self *IBBSTree) Set(key uint64, value interface{}) (_ *IBBSTree, updated bool) {
- if self == nil {
- return NewIBBSTreeNode(key, value), false
- }
- if self.height == 0 {
- if key < self.key {
- return &IBBSTree{
- key: self.key,
- height: 1,
- size: 2,
- left: NewIBBSTreeNode(key, value),
- right: self,
- }, false
- } else if self.key == key {
- return NewIBBSTreeNode(key, value), true
- } else {
- return &IBBSTree{
- key: key,
- height: 1,
- size: 2,
- left: self,
- right: NewIBBSTreeNode(key, value),
- }, false
- }
- } else {
- self = self.Copy()
- if key < self.key {
- self.left, updated = self.left.Set(key, value)
- } else {
- self.right, updated = self.right.Set(key, value)
- }
- if updated {
- return self, updated
- } else {
- self.calcHeightAndSize()
- return self.balance(), updated
- }
- }
- }
-
- func (self *IBBSTree) Remove(key uint64) (newSelf *IBBSTree, value interface{}, removed bool) {
- newSelf, _, _, value, removed = self.remove(key)
- return
- }
-
- // newKey: new leftmost leaf key for tree after successfully removing 'key' if changed.
- func (self *IBBSTree) remove(key uint64) (newSelf *IBBSTree, hasNewKey bool, newKey uint64, value interface{}, removed bool) {
- if self == nil {
- return nil, false, 0, nil, false
- }
- if self.height == 0 {
- if self.key == key {
- return nil, false, 0, self.value, true
- } else {
- return self, false, 0, nil, false
- }
- } else {
- if key < self.key {
- var newLeft *IBBSTree
- newLeft, hasNewKey, newKey, value, removed = self.left.remove(key)
- if !removed {
- return self, false, 0, value, false
- } else if newLeft == nil { // left node held value, was removed
- return self.right, true, self.key, value, true
- }
- self = self.Copy()
- self.left = newLeft
- } else {
- var newRight *IBBSTree
- newRight, hasNewKey, newKey, value, removed = self.right.remove(key)
- if !removed {
- return self, false, 0, value, false
- } else if newRight == nil { // right node held value, was removed
- return self.left, false, 0, value, true
- }
- self = self.Copy()
- self.right = newRight
- if hasNewKey {
- self.key = newKey
- hasNewKey = false
- newKey = 0
- }
- }
- self.calcHeightAndSize()
- return self.balance(), hasNewKey, newKey, value, true
- }
- }
-
- func (self *IBBSTree) rotateRight() *IBBSTree {
- self = self.Copy()
- sl := self.left.Copy()
- slr := sl.right
-
- sl.right = self
- self.left = slr
-
- self.calcHeightAndSize()
- sl.calcHeightAndSize()
-
- return sl
- }
-
- func (self *IBBSTree) rotateLeft() *IBBSTree {
- self = self.Copy()
- sr := self.right.Copy()
- srl := sr.left
-
- sr.left = self
- self.right = srl
-
- self.calcHeightAndSize()
- sr.calcHeightAndSize()
-
- return sr
- }
-
- func (self *IBBSTree) calcHeightAndSize() {
- self.height = MaxUint8(self.left.Height(), self.right.Height()) + 1
- self.size = self.left.Size() + self.right.Size()
- }
-
- func (self *IBBSTree) calcBalance() int {
- return int(self.left.Height()) - int(self.right.Height())
- }
-
- func (self *IBBSTree) balance() (newSelf *IBBSTree) {
- balance := self.calcBalance()
- if balance > 1 {
- if self.left.calcBalance() >= 0 {
- // Left Left Case
- return self.rotateRight()
- } else {
- // Left Right Case
- self = self.Copy()
- self.left = self.left.rotateLeft()
- //self.calcHeightAndSize()
- return self.rotateRight()
- }
- }
- if balance < -1 {
- if self.right.calcBalance() <= 0 {
- // Right Right Case
- return self.rotateLeft()
- } else {
- // Right Left Case
- self = self.Copy()
- self.right = self.right.rotateRight()
- //self.calcHeightAndSize()
- return self.rotateLeft()
- }
- }
- // Nothing changed
- return self
- }
-
- // Iteration stops when stop is returned.
- func (self *IBBSTree) Iterate(cb func(uint64, interface{}) bool) bool {
- if self == nil {
- return false
- }
- if self.height == 0 {
- return cb(self.key, self.value)
- } else {
- stop := self.left.Iterate(cb)
- if stop {
- return stop
- }
- return self.right.Iterate(cb)
- }
- }
|