github.com/gnolang/gno@v0.0.0-20240520182011-228e9d0192ce/examples/gno.land/p/demo/avl/node.gno (about)

     1  package avl
     2  
     3  //----------------------------------------
     4  // Node
     5  
     6  // Node represents a node in an AVL tree.
     7  type Node struct {
     8  	key       string      // key is the unique identifier for the node.
     9  	value     interface{} // value is the data stored in the node.
    10  	height    int8        // height is the height of the node in the tree.
    11  	size      int         // size is the number of nodes in the subtree rooted at this node.
    12  	leftNode  *Node       // leftNode is the left child of the node.
    13  	rightNode *Node       // rightNode is the right child of the node.
    14  }
    15  
    16  // NewNode creates a new node with the given key and value.
    17  func NewNode(key string, value interface{}) *Node {
    18  	return &Node{
    19  		key:    key,
    20  		value:  value,
    21  		height: 0,
    22  		size:   1,
    23  	}
    24  }
    25  
    26  // Size returns the size of the subtree rooted at the node.
    27  func (node *Node) Size() int {
    28  	if node == nil {
    29  		return 0
    30  	}
    31  	return node.size
    32  }
    33  
    34  // IsLeaf checks if the node is a leaf node (has no children).
    35  func (node *Node) IsLeaf() bool {
    36  	return node.height == 0
    37  }
    38  
    39  // Key returns the key of the node.
    40  func (node *Node) Key() string {
    41  	return node.key
    42  }
    43  
    44  // Value returns the value of the node.
    45  func (node *Node) Value() interface{} {
    46  	return node.value
    47  }
    48  
    49  // _copy creates a copy of the node (excluding value).
    50  func (node *Node) _copy() *Node {
    51  	if node.height == 0 {
    52  		panic("Why are you copying a value node?")
    53  	}
    54  	return &Node{
    55  		key:       node.key,
    56  		height:    node.height,
    57  		size:      node.size,
    58  		leftNode:  node.leftNode,
    59  		rightNode: node.rightNode,
    60  	}
    61  }
    62  
    63  // Has checks if a node with the given key exists in the subtree rooted at the node.
    64  func (node *Node) Has(key string) (has bool) {
    65  	if node == nil {
    66  		return false
    67  	}
    68  	if node.key == key {
    69  		return true
    70  	}
    71  	if node.height == 0 {
    72  		return false
    73  	}
    74  	if key < node.key {
    75  		return node.getLeftNode().Has(key)
    76  	}
    77  	return node.getRightNode().Has(key)
    78  }
    79  
    80  // Get searches for a node with the given key in the subtree rooted at the node
    81  // and returns its index, value, and whether it exists.
    82  func (node *Node) Get(key string) (index int, value interface{}, exists bool) {
    83  	if node == nil {
    84  		return 0, nil, false
    85  	}
    86  
    87  	if node.height == 0 {
    88  		if node.key == key {
    89  			return 0, node.value, true
    90  		}
    91  		if node.key < key {
    92  			return 1, nil, false
    93  		}
    94  		return 0, nil, false
    95  	}
    96  
    97  	if key < node.key {
    98  		return node.getLeftNode().Get(key)
    99  	}
   100  
   101  	rightNode := node.getRightNode()
   102  	index, value, exists = rightNode.Get(key)
   103  	index += node.size - rightNode.size
   104  	return index, value, exists
   105  }
   106  
   107  // GetByIndex retrieves the key-value pair of the node at the given index
   108  // in the subtree rooted at the node.
   109  func (node *Node) GetByIndex(index int) (key string, value interface{}) {
   110  	if node.height == 0 {
   111  		if index == 0 {
   112  			return node.key, node.value
   113  		}
   114  		panic("GetByIndex asked for invalid index")
   115  	}
   116  	// TODO: could improve this by storing the sizes
   117  	leftNode := node.getLeftNode()
   118  	if index < leftNode.size {
   119  		return leftNode.GetByIndex(index)
   120  	}
   121  	return node.getRightNode().GetByIndex(index - leftNode.size)
   122  }
   123  
   124  // Set inserts a new node with the given key-value pair into the subtree rooted at the node,
   125  // and returns the new root of the subtree and whether an existing node was updated.
   126  //
   127  // XXX consider a better way to do this... perhaps split Node from Node.
   128  func (node *Node) Set(key string, value interface{}) (newSelf *Node, updated bool) {
   129  	if node == nil {
   130  		return NewNode(key, value), false
   131  	}
   132  
   133  	if node.height == 0 {
   134  		return node.setLeaf(key, value)
   135  	}
   136  
   137  	node = node._copy()
   138  	if key < node.key {
   139  		node.leftNode, updated = node.getLeftNode().Set(key, value)
   140  	} else {
   141  		node.rightNode, updated = node.getRightNode().Set(key, value)
   142  	}
   143  
   144  	if updated {
   145  		return node, updated
   146  	}
   147  
   148  	node.calcHeightAndSize()
   149  	return node.balance(), updated
   150  }
   151  
   152  // setLeaf inserts a new leaf node with the given key-value pair into the subtree rooted at the node,
   153  // and returns the new root of the subtree and whether an existing node was updated.
   154  func (node *Node) setLeaf(key string, value interface{}) (newSelf *Node, updated bool) {
   155  	if key == node.key {
   156  		return NewNode(key, value), true
   157  	}
   158  
   159  	if key < node.key {
   160  		return &Node{
   161  			key:       node.key,
   162  			height:    1,
   163  			size:      2,
   164  			leftNode:  NewNode(key, value),
   165  			rightNode: node,
   166  		}, false
   167  	}
   168  
   169  	return &Node{
   170  		key:       key,
   171  		height:    1,
   172  		size:      2,
   173  		leftNode:  node,
   174  		rightNode: NewNode(key, value),
   175  	}, false
   176  }
   177  
   178  // Remove deletes the node with the given key from the subtree rooted at the node.
   179  // returns the new root of the subtree, the new leftmost leaf key (if changed),
   180  // the removed value and the removal was successful.
   181  func (node *Node) Remove(key string) (
   182  	newNode *Node, newKey string, value interface{}, removed bool,
   183  ) {
   184  	if node == nil {
   185  		return nil, "", nil, false
   186  	}
   187  	if node.height == 0 {
   188  		if key == node.key {
   189  			return nil, "", node.value, true
   190  		}
   191  		return node, "", nil, false
   192  	}
   193  	if key < node.key {
   194  		var newLeftNode *Node
   195  		newLeftNode, newKey, value, removed = node.getLeftNode().Remove(key)
   196  		if !removed {
   197  			return node, "", value, false
   198  		}
   199  		if newLeftNode == nil { // left node held value, was removed
   200  			return node.rightNode, node.key, value, true
   201  		}
   202  		node = node._copy()
   203  		node.leftNode = newLeftNode
   204  		node.calcHeightAndSize()
   205  		node = node.balance()
   206  		return node, newKey, value, true
   207  	}
   208  
   209  	var newRightNode *Node
   210  	newRightNode, newKey, value, removed = node.getRightNode().Remove(key)
   211  	if !removed {
   212  		return node, "", value, false
   213  	}
   214  	if newRightNode == nil { // right node held value, was removed
   215  		return node.leftNode, "", value, true
   216  	}
   217  	node = node._copy()
   218  	node.rightNode = newRightNode
   219  	if newKey != "" {
   220  		node.key = newKey
   221  	}
   222  	node.calcHeightAndSize()
   223  	node = node.balance()
   224  	return node, "", value, true
   225  }
   226  
   227  // getLeftNode returns the left child of the node.
   228  func (node *Node) getLeftNode() *Node {
   229  	return node.leftNode
   230  }
   231  
   232  // getRightNode returns the right child of the node.
   233  func (node *Node) getRightNode() *Node {
   234  	return node.rightNode
   235  }
   236  
   237  // rotateRight performs a right rotation on the node and returns the new root.
   238  // NOTE: overwrites node
   239  // TODO: optimize balance & rotate
   240  func (node *Node) rotateRight() *Node {
   241  	node = node._copy()
   242  	l := node.getLeftNode()
   243  	_l := l._copy()
   244  
   245  	_lrCached := _l.rightNode
   246  	_l.rightNode = node
   247  	node.leftNode = _lrCached
   248  
   249  	node.calcHeightAndSize()
   250  	_l.calcHeightAndSize()
   251  
   252  	return _l
   253  }
   254  
   255  // rotateLeft performs a left rotation on the node and returns the new root.
   256  // NOTE: overwrites node
   257  // TODO: optimize balance & rotate
   258  func (node *Node) rotateLeft() *Node {
   259  	node = node._copy()
   260  	r := node.getRightNode()
   261  	_r := r._copy()
   262  
   263  	_rlCached := _r.leftNode
   264  	_r.leftNode = node
   265  	node.rightNode = _rlCached
   266  
   267  	node.calcHeightAndSize()
   268  	_r.calcHeightAndSize()
   269  
   270  	return _r
   271  }
   272  
   273  // calcHeightAndSize updates the height and size of the node based on its children.
   274  // NOTE: mutates height and size
   275  func (node *Node) calcHeightAndSize() {
   276  	node.height = maxInt8(node.getLeftNode().height, node.getRightNode().height) + 1
   277  	node.size = node.getLeftNode().size + node.getRightNode().size
   278  }
   279  
   280  // calcBalance calculates the balance factor of the node.
   281  func (node *Node) calcBalance() int {
   282  	return int(node.getLeftNode().height) - int(node.getRightNode().height)
   283  }
   284  
   285  // balance balances the subtree rooted at the node and returns the new root.
   286  // NOTE: assumes that node can be modified
   287  // TODO: optimize balance & rotate
   288  func (node *Node) balance() (newSelf *Node) {
   289  	balance := node.calcBalance()
   290  	if balance >= -1 {
   291  		return node
   292  	}
   293  	if balance > 1 {
   294  		if node.getLeftNode().calcBalance() >= 0 {
   295  			// Left Left Case
   296  			return node.rotateRight()
   297  		}
   298  		// Left Right Case
   299  		left := node.getLeftNode()
   300  		node.leftNode = left.rotateLeft()
   301  		return node.rotateRight()
   302  	}
   303  
   304  	if node.getRightNode().calcBalance() <= 0 {
   305  		// Right Right Case
   306  		return node.rotateLeft()
   307  	}
   308  
   309  	// Right Left Case
   310  	right := node.getRightNode()
   311  	node.rightNode = right.rotateRight()
   312  	return node.rotateLeft()
   313  }
   314  
   315  // Shortcut for TraverseInRange.
   316  func (node *Node) Iterate(start, end string, cb func(*Node) bool) bool {
   317  	return node.TraverseInRange(start, end, true, true, cb)
   318  }
   319  
   320  // Shortcut for TraverseInRange.
   321  func (node *Node) ReverseIterate(start, end string, cb func(*Node) bool) bool {
   322  	return node.TraverseInRange(start, end, false, true, cb)
   323  }
   324  
   325  // TraverseInRange traverses all nodes, including inner nodes.
   326  // Start is inclusive and end is exclusive when ascending,
   327  // Start and end are inclusive when descending.
   328  // Empty start and empty end denote no start and no end.
   329  // If leavesOnly is true, only visit leaf nodes.
   330  // NOTE: To simulate an exclusive reverse traversal,
   331  // just append 0x00 to start.
   332  func (node *Node) TraverseInRange(start, end string, ascending bool, leavesOnly bool, cb func(*Node) bool) bool {
   333  	if node == nil {
   334  		return false
   335  	}
   336  	afterStart := (start == "" || start < node.key)
   337  	startOrAfter := (start == "" || start <= node.key)
   338  	beforeEnd := false
   339  	if ascending {
   340  		beforeEnd = (end == "" || node.key < end)
   341  	} else {
   342  		beforeEnd = (end == "" || node.key <= end)
   343  	}
   344  
   345  	// Run callback per inner/leaf node.
   346  	stop := false
   347  	if (!node.IsLeaf() && !leavesOnly) ||
   348  		(node.IsLeaf() && startOrAfter && beforeEnd) {
   349  		stop = cb(node)
   350  		if stop {
   351  			return stop
   352  		}
   353  	}
   354  	if node.IsLeaf() {
   355  		return stop
   356  	}
   357  
   358  	if ascending {
   359  		// check lower nodes, then higher
   360  		if afterStart {
   361  			stop = node.getLeftNode().TraverseInRange(start, end, ascending, leavesOnly, cb)
   362  		}
   363  		if stop {
   364  			return stop
   365  		}
   366  		if beforeEnd {
   367  			stop = node.getRightNode().TraverseInRange(start, end, ascending, leavesOnly, cb)
   368  		}
   369  	} else {
   370  		// check the higher nodes first
   371  		if beforeEnd {
   372  			stop = node.getRightNode().TraverseInRange(start, end, ascending, leavesOnly, cb)
   373  		}
   374  		if stop {
   375  			return stop
   376  		}
   377  		if afterStart {
   378  			stop = node.getLeftNode().TraverseInRange(start, end, ascending, leavesOnly, cb)
   379  		}
   380  	}
   381  
   382  	return stop
   383  }
   384  
   385  // TraverseByOffset traverses all nodes, including inner nodes.
   386  // A limit of math.MaxInt means no limit.
   387  func (node *Node) TraverseByOffset(offset, limit int, descending bool, leavesOnly bool, cb func(*Node) bool) bool {
   388  	if node == nil {
   389  		return false
   390  	}
   391  
   392  	// fast paths. these happen only if TraverseByOffset is called directly on a leaf.
   393  	if limit <= 0 || offset >= node.size {
   394  		return false
   395  	}
   396  	if node.IsLeaf() {
   397  		if offset > 0 {
   398  			return false
   399  		}
   400  		return cb(node)
   401  	}
   402  
   403  	// go to the actual recursive function.
   404  	return node.traverseByOffset(offset, limit, descending, leavesOnly, cb)
   405  }
   406  
   407  // TraverseByOffset traverses the subtree rooted at the node by offset and limit,
   408  // in either ascending or descending order, and applies the callback function to each traversed node.
   409  // If leavesOnly is true, only leaf nodes are visited.
   410  func (node *Node) traverseByOffset(offset, limit int, descending bool, leavesOnly bool, cb func(*Node) bool) bool {
   411  	// caller guarantees: offset < node.size; limit > 0.
   412  	if !leavesOnly {
   413  		if cb(node) {
   414  			return true
   415  		}
   416  	}
   417  	first, second := node.getLeftNode(), node.getRightNode()
   418  	if descending {
   419  		first, second = second, first
   420  	}
   421  	if first.IsLeaf() {
   422  		// either run or skip, based on offset
   423  		if offset > 0 {
   424  			offset--
   425  		} else {
   426  			cb(first)
   427  			limit--
   428  			if limit <= 0 {
   429  				return false
   430  			}
   431  		}
   432  	} else {
   433  		// possible cases:
   434  		// 1 the offset given skips the first node entirely
   435  		// 2 the offset skips none or part of the first node, but the limit requires some of the second node.
   436  		// 3 the offset skips none or part of the first node, and the limit stops our search on the first node.
   437  		if offset >= first.size {
   438  			offset -= first.size // 1
   439  		} else {
   440  			if first.traverseByOffset(offset, limit, descending, leavesOnly, cb) {
   441  				return true
   442  			}
   443  			// number of leaves which could actually be called from inside
   444  			delta := first.size - offset
   445  			offset = 0
   446  			if delta >= limit {
   447  				return true // 3
   448  			}
   449  			limit -= delta // 2
   450  		}
   451  	}
   452  
   453  	// because of the caller guarantees and the way we handle the first node,
   454  	// at this point we know that limit > 0 and there must be some values in
   455  	// this second node that we include.
   456  
   457  	// => if the second node is a leaf, it has to be included.
   458  	if second.IsLeaf() {
   459  		return cb(second)
   460  	}
   461  	// => if it is not a leaf, it will still be enough to recursively call this
   462  	// function with the updated offset and limit
   463  	return second.traverseByOffset(offset, limit, descending, leavesOnly, cb)
   464  }
   465  
   466  // Only used in testing...
   467  func (node *Node) lmd() *Node {
   468  	if node.height == 0 {
   469  		return node
   470  	}
   471  	return node.getLeftNode().lmd()
   472  }
   473  
   474  // Only used in testing...
   475  func (node *Node) rmd() *Node {
   476  	if node.height == 0 {
   477  		return node
   478  	}
   479  	return node.getRightNode().rmd()
   480  }
   481  
   482  func maxInt8(a, b int8) int8 {
   483  	if a > b {
   484  		return a
   485  	}
   486  	return b
   487  }