github.com/songzhibin97/go-baseutils@v0.0.2-0.20240302024150-487d8ce9c082/structure/trees/btree/iterator.go (about)

     1  package btree
     2  
     3  import "github.com/songzhibin97/go-baseutils/structure/containers"
     4  
     5  // Assert Iterator implementation
     6  var _ containers.ReverseIteratorWithKey[any, any] = (*Iterator[any, any])(nil)
     7  
     8  // Iterator holding the iterator's state
     9  type Iterator[K, V any] struct {
    10  	tree     *Tree[K, V]
    11  	node     *Node[K, V]
    12  	entry    *Entry[K, V]
    13  	position position
    14  }
    15  
    16  type position byte
    17  
    18  const (
    19  	begin, between, end position = 0, 1, 2
    20  )
    21  
    22  // Iterator returns a stateful iterator whose elements are key/value pairs.
    23  func (tree *Tree[K, V]) Iterator() Iterator[K, V] {
    24  	return Iterator[K, V]{tree: tree, node: nil, position: begin}
    25  }
    26  
    27  // Next moves the iterator to the next element and returns true if there was a next element in the container.
    28  // If Next() returns true, then next element's key and value can be retrieved by Key() and Value().
    29  // If Next() was called for the first time, then it will point the iterator to the first element if it exists.
    30  // Modifies the state of the iterator.
    31  func (iterator *Iterator[K, V]) Next() bool {
    32  	// If already at end, go to end
    33  	if iterator.position == end {
    34  		goto end
    35  	}
    36  	// If at beginning, get the left-most entry in the tree
    37  	if iterator.position == begin {
    38  		left := iterator.tree.Left()
    39  		if left == nil {
    40  			goto end
    41  		}
    42  		iterator.node = left
    43  		iterator.entry = left.Entries[0]
    44  		goto between
    45  	}
    46  	{
    47  		// Find current entry position in current node
    48  		e, _ := iterator.tree.search(iterator.node, iterator.entry.Key)
    49  		// Try to go down to the child right of the current entry
    50  		if e+1 < len(iterator.node.Children) {
    51  			iterator.node = iterator.node.Children[e+1]
    52  			// Try to go down to the child left of the current node
    53  			for len(iterator.node.Children) > 0 {
    54  				iterator.node = iterator.node.Children[0]
    55  			}
    56  			// Return the left-most entry
    57  			iterator.entry = iterator.node.Entries[0]
    58  			goto between
    59  		}
    60  		// Above assures that we have reached a leaf node, so return the next entry in current node (if any)
    61  		if e+1 < len(iterator.node.Entries) {
    62  			iterator.entry = iterator.node.Entries[e+1]
    63  			goto between
    64  		}
    65  	}
    66  	// Reached leaf node and there are no entries to the right of the current entry, so go up to the parent
    67  	for iterator.node.Parent != nil {
    68  		iterator.node = iterator.node.Parent
    69  		// Find next entry position in current node (note: search returns the first equal or bigger than entry)
    70  		e, _ := iterator.tree.search(iterator.node, iterator.entry.Key)
    71  		// Check that there is a next entry position in current node
    72  		if e < len(iterator.node.Entries) {
    73  			iterator.entry = iterator.node.Entries[e]
    74  			goto between
    75  		}
    76  	}
    77  
    78  end:
    79  	iterator.End()
    80  	return false
    81  
    82  between:
    83  	iterator.position = between
    84  	return true
    85  }
    86  
    87  // Prev moves the iterator to the previous element and returns true if there was a previous element in the container.
    88  // If Prev() returns true, then previous element's key and value can be retrieved by Key() and Value().
    89  // Modifies the state of the iterator.
    90  func (iterator *Iterator[K, V]) Prev() bool {
    91  	// If already at beginning, go to begin
    92  	if iterator.position == begin {
    93  		goto begin
    94  	}
    95  	// If at end, get the right-most entry in the tree
    96  	if iterator.position == end {
    97  		right := iterator.tree.Right()
    98  		if right == nil {
    99  			goto begin
   100  		}
   101  		iterator.node = right
   102  		iterator.entry = right.Entries[len(right.Entries)-1]
   103  		goto between
   104  	}
   105  	{
   106  		// Find current entry position in current node
   107  		e, _ := iterator.tree.search(iterator.node, iterator.entry.Key)
   108  		// Try to go down to the child left of the current entry
   109  		if e < len(iterator.node.Children) {
   110  			iterator.node = iterator.node.Children[e]
   111  			// Try to go down to the child right of the current node
   112  			for len(iterator.node.Children) > 0 {
   113  				iterator.node = iterator.node.Children[len(iterator.node.Children)-1]
   114  			}
   115  			// Return the right-most entry
   116  			iterator.entry = iterator.node.Entries[len(iterator.node.Entries)-1]
   117  			goto between
   118  		}
   119  		// Above assures that we have reached a leaf node, so return the previous entry in current node (if any)
   120  		if e-1 >= 0 {
   121  			iterator.entry = iterator.node.Entries[e-1]
   122  			goto between
   123  		}
   124  	}
   125  	// Reached leaf node and there are no entries to the left of the current entry, so go up to the parent
   126  	for iterator.node.Parent != nil {
   127  		iterator.node = iterator.node.Parent
   128  		// Find previous entry position in current node (note: search returns the first equal or bigger than entry)
   129  		e, _ := iterator.tree.search(iterator.node, iterator.entry.Key)
   130  		// Check that there is a previous entry position in current node
   131  		if e-1 >= 0 {
   132  			iterator.entry = iterator.node.Entries[e-1]
   133  			goto between
   134  		}
   135  	}
   136  
   137  begin:
   138  	iterator.Begin()
   139  	return false
   140  
   141  between:
   142  	iterator.position = between
   143  	return true
   144  }
   145  
   146  // Value returns the current element's value.
   147  // Does not modify the state of the iterator.
   148  func (iterator *Iterator[K, V]) Value() V {
   149  	return iterator.entry.Value
   150  }
   151  
   152  // Key returns the current element's key.
   153  // Does not modify the state of the iterator.
   154  func (iterator *Iterator[K, V]) Key() K {
   155  	return iterator.entry.Key
   156  }
   157  
   158  // Node returns the current element's node.
   159  // Does not modify the state of the iterator.
   160  func (iterator *Iterator[K, V]) Node() *Node[K, V] {
   161  	return iterator.node
   162  }
   163  
   164  // Begin resets the iterator to its initial state (one-before-first)
   165  // Call Next() to fetch the first element if any.
   166  func (iterator *Iterator[K, V]) Begin() {
   167  	iterator.node = nil
   168  	iterator.position = begin
   169  	iterator.entry = nil
   170  }
   171  
   172  // End moves the iterator past the last element (one-past-the-end).
   173  // Call Prev() to fetch the last element if any.
   174  func (iterator *Iterator[K, V]) End() {
   175  	iterator.node = nil
   176  	iterator.position = end
   177  	iterator.entry = nil
   178  }
   179  
   180  // First moves the iterator to the first element and returns true if there was a first element in the container.
   181  // If First() returns true, then first element's key and value can be retrieved by Key() and Value().
   182  // Modifies the state of the iterator
   183  func (iterator *Iterator[K, V]) First() bool {
   184  	iterator.Begin()
   185  	return iterator.Next()
   186  }
   187  
   188  // Last moves the iterator to the last element and returns true if there was a last element in the container.
   189  // If Last() returns true, then last element's key and value can be retrieved by Key() and Value().
   190  // Modifies the state of the iterator.
   191  func (iterator *Iterator[K, V]) Last() bool {
   192  	iterator.End()
   193  	return iterator.Prev()
   194  }
   195  
   196  // NextTo moves the iterator to the next element from current position that satisfies the condition given by the
   197  // passed function, and returns true if there was a next element in the container.
   198  // If NextTo() returns true, then next element's key and value can be retrieved by Key() and Value().
   199  // Modifies the state of the iterator.
   200  func (iterator *Iterator[K, V]) NextTo(f func(key K, value V) bool) bool {
   201  	for iterator.Next() {
   202  		key, value := iterator.Key(), iterator.Value()
   203  		if f(key, value) {
   204  			return true
   205  		}
   206  	}
   207  	return false
   208  }
   209  
   210  // PrevTo moves the iterator to the previous element from current position that satisfies the condition given by the
   211  // passed function, and returns true if there was a next element in the container.
   212  // If PrevTo() returns true, then next element's key and value can be retrieved by Key() and Value().
   213  // Modifies the state of the iterator.
   214  func (iterator *Iterator[K, V]) PrevTo(f func(key K, value V) bool) bool {
   215  	for iterator.Prev() {
   216  		key, value := iterator.Key(), iterator.Value()
   217  		if f(key, value) {
   218  			return true
   219  		}
   220  	}
   221  	return false
   222  }