github.com/songzhibin97/go-baseutils@v0.0.2-0.20240302024150-487d8ce9c082/structure/trees/binaryheap/iterator.go (about) 1 package binaryheap 2 3 import ( 4 "github.com/songzhibin97/go-baseutils/structure/containers" 5 ) 6 7 // Assert Iterator implementation 8 var _ containers.ReverseIteratorWithIndex[any] = (*Iterator[any])(nil) 9 10 // Iterator returns a stateful iterator whose values can be fetched by an index. 11 type Iterator[E any] struct { 12 heap *Heap[E] 13 index int 14 } 15 16 // Iterator returns a stateful iterator whose values can be fetched by an index. 17 func (heap *Heap[E]) Iterator() Iterator[E] { 18 return Iterator[E]{heap: heap, index: -1} 19 } 20 21 // Next moves the iterator to the next element and returns true if there was a next element in the container. 22 // If Next() returns true, then next element's index and value can be retrieved by Index() and Value(). 23 // If Next() was called for the first time, then it will point the iterator to the first element if it exists. 24 // Modifies the state of the iterator. 25 func (iterator *Iterator[E]) Next() bool { 26 if iterator.index < iterator.heap.Size() { 27 iterator.index++ 28 } 29 return iterator.heap.withinRange(iterator.index) 30 } 31 32 // Prev moves the iterator to the previous element and returns true if there was a previous element in the container. 33 // If Prev() returns true, then previous element's index and value can be retrieved by Index() and Value(). 34 // Modifies the state of the iterator. 35 func (iterator *Iterator[E]) Prev() bool { 36 if iterator.index >= 0 { 37 iterator.index-- 38 } 39 return iterator.heap.withinRange(iterator.index) 40 } 41 42 // Value returns the current element's value. 43 // Does not modify the state of the iterator. 44 func (iterator *Iterator[E]) Value() E { 45 start, end := evaluateRange(iterator.index) 46 if end > iterator.heap.Size() { 47 end = iterator.heap.Size() 48 } 49 tmpHeap := NewWith(iterator.heap.Comparator) 50 for n := start; n < end; n++ { 51 value, _ := iterator.heap.list.Get(n) 52 tmpHeap.Push(value) 53 } 54 for n := 0; n < iterator.index-start; n++ { 55 tmpHeap.Pop() 56 } 57 value, _ := tmpHeap.Pop() 58 return value 59 } 60 61 // Index returns the current element's index. 62 // Does not modify the state of the iterator. 63 func (iterator *Iterator[E]) Index() int { 64 return iterator.index 65 } 66 67 // Begin resets the iterator to its initial state (one-before-first) 68 // Call Next() to fetch the first element if any. 69 func (iterator *Iterator[E]) Begin() { 70 iterator.index = -1 71 } 72 73 // End moves the iterator past the last element (one-past-the-end). 74 // Call Prev() to fetch the last element if any. 75 func (iterator *Iterator[E]) End() { 76 iterator.index = iterator.heap.Size() 77 } 78 79 // First moves the iterator to the first element and returns true if there was a first element in the container. 80 // If First() returns true, then first element's index and value can be retrieved by Index() and Value(). 81 // Modifies the state of the iterator. 82 func (iterator *Iterator[E]) First() bool { 83 iterator.Begin() 84 return iterator.Next() 85 } 86 87 // Last moves the iterator to the last element and returns true if there was a last element in the container. 88 // If Last() returns true, then last element's index and value can be retrieved by Index() and Value(). 89 // Modifies the state of the iterator. 90 func (iterator *Iterator[E]) Last() bool { 91 iterator.End() 92 return iterator.Prev() 93 } 94 95 // NextTo moves the iterator to the next element from current position that satisfies the condition given by the 96 // passed function, and returns true if there was a next element in the container. 97 // If NextTo() returns true, then next element's index and value can be retrieved by Index() and Value(). 98 // Modifies the state of the iterator. 99 func (iterator *Iterator[E]) NextTo(f func(index int, value E) bool) bool { 100 for iterator.Next() { 101 index, value := iterator.Index(), iterator.Value() 102 if f(index, value) { 103 return true 104 } 105 } 106 return false 107 } 108 109 // PrevTo moves the iterator to the previous element from current position that satisfies the condition given by the 110 // passed function, and returns true if there was a next element in the container. 111 // If PrevTo() returns true, then next element's index and value can be retrieved by Index() and Value(). 112 // Modifies the state of the iterator. 113 func (iterator *Iterator[E]) PrevTo(f func(index int, value E) bool) bool { 114 for iterator.Prev() { 115 index, value := iterator.Index(), iterator.Value() 116 if f(index, value) { 117 return true 118 } 119 } 120 return false 121 } 122 123 // numOfBits counts the number of bits of an int 124 func numOfBits(n int) uint { 125 var count uint 126 for n != 0 { 127 count++ 128 n >>= 1 129 } 130 return count 131 } 132 133 // evaluateRange evaluates the index range [start,end) of same level nodes in the heap as the index 134 func evaluateRange(index int) (start int, end int) { 135 bits := numOfBits(index+1) - 1 136 start = 1<<bits - 1 137 end = start + 1<<bits 138 return 139 }