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 }