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  }