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