Source code: org/media/mn8/util/cron/BinaryHeap.java
1 package org.media.mn8.util.cron;
2
3 import java.util.Comparator;
4 import java.util.NoSuchElementException;
5
6
7 public final class BinaryHeap {
8 private static final class MinComparator implements Comparator {
9 public final int compare( final Object lhs, final Object rhs ) {
10 return ( (Comparable)lhs ).compareTo( rhs );
11 }
12 }
13
14
15 private static final class MaxComparator implements Comparator {
16 public final int compare( final Object lhs, final Object rhs ) {
17 return ( (Comparable)rhs ).compareTo( lhs );
18 }
19 }
20
21
22 public static final Comparator MIN_COMPARATOR = new MinComparator();
23 public static final Comparator MAX_COMPARATOR = new MaxComparator();
24 private static final int DEFAULT_CAPACITY = 13;
25 private static final Comparator DEFAULT_COMPARATOR = MIN_COMPARATOR;
26 private int m_size;
27 private Object[] m_elements;
28 private Comparator m_comparator;
29
30
31 public BinaryHeap() {
32 this( DEFAULT_CAPACITY, DEFAULT_COMPARATOR );
33 }
34
35
36 public BinaryHeap( final int capacity, final Comparator comparator ) {
37 //+1 as 0 is noop
38 m_elements = new Object[ capacity + 1 ];
39 m_comparator = comparator;
40 }
41
42
43 /**
44 * Clear all elements from queue.
45 */
46 public void clear() {
47 m_size = 0;
48 }
49
50 /**
51 * Test if queue is empty.
52 *
53 * @return true if queue is empty else false.
54 */
55 public boolean isEmpty() {
56 return ( 0 == m_size );
57 }
58
59
60 /**
61 * Test if queue is full.
62 *
63 * @return true if queue is full else false.
64 */
65 public boolean isFull() {
66 //+1 as element 0 is noop
67 return ( m_elements.length == m_size + 1 );
68 }
69
70
71 /**
72 * Returns the number of elements currently on the heap.
73 *
74 * @return the size of the heap.
75 */
76 public int size() {
77 return m_size;
78 }
79
80 /**
81 * Insert an element into queue.
82 *
83 * @param element the element to be inserted
84 */
85 public void insert( final Object element ) {
86 if( isFull() ) {
87 grow();
88 }
89 percolateUpHeap( element );
90 }
91
92
93 /**
94 * Return element on top of heap but don't remove it.
95 *
96 * @return the element at top of heap
97 * @throws NoSuchElementException if isEmpty() == true
98 */
99 public Object peek() throws NoSuchElementException {
100 if( isEmpty() ) {
101 throw new NoSuchElementException();
102 } else {
103 return m_elements[ 1 ];
104 }
105 }
106
107
108 /**
109 * Return element on top of heap and remove it.
110 *
111 * @return the element at top of heap
112 * @throws NoSuchElementException if isEmpty() == true
113 */
114 public Object pop() throws NoSuchElementException {
115 final Object result = peek();
116 m_elements[ 1 ] = m_elements[ m_size-- ];
117
118 //set the unused element to 'null' so that the garbage collector
119 //can free the object if not used anywhere else.(remove reference)
120 m_elements[ m_size + 1 ] = null;
121
122 if( m_size != 0 ) {
123 percolateDownHeap( 1 );
124 }
125 return result;
126 }
127
128
129 /**
130 * Percolate element down heap from top.
131 *
132 * @param element the element
133 */
134 private void percolateDownHeap( final int index ) {
135 final Object element = m_elements[ index ];
136
137 int hole = index;
138 int child = hole << 1;
139
140 while( child <= m_size ) {
141 //if we have a right child and that child can not be percolated
142 //up then move onto other child
143 if( child != m_size &&
144 m_comparator.compare( m_elements[ child + 1 ], m_elements[ child ] ) < 0 )
145 {
146 child++;
147 }
148
149 //if we found resting place of bubble then terminate search
150 if( m_comparator.compare( m_elements[ child ], element ) >= 0 ) {
151 break;
152 }
153
154 m_elements[ hole ] = m_elements[ child ];
155 hole = child;
156 child = hole << 1;
157 }
158
159 m_elements[ hole ] = element;
160 }
161
162
163 /**
164 * Percolate element up heap from bottom.
165 *
166 * @param element the element
167 */
168 private void percolateUpHeap( final Object element ) {
169 int hole = ++m_size;
170 int next = hole >> 1;
171
172 m_elements[ hole ] = element;
173
174 while( hole > 1 &&
175 m_comparator.compare( element, m_elements[ next ] ) < 0 )
176 {
177 m_elements[ hole ] = m_elements[ next ];
178 hole = next;
179 next = hole >> 1;
180 }
181
182 m_elements[ hole ] = element;
183 }
184
185
186 /**
187 * Grows the heap by a factor of 2.
188 */
189 private void grow() {
190 final Object[] elements = new Object[ m_elements.length * 2 ];
191 System.arraycopy( m_elements, 0, elements, 0, m_elements.length );
192 m_elements = elements;
193 }
194
195
196 /**
197 * Create a string representing heap
198 * and all elements in heap.
199 *
200 * @return the string representing heap
201 */
202 public String toString() {
203 final StringBuffer sb = new StringBuffer();
204 sb.append( "[ " );
205 for( int i = 1; i < m_size + 1; i++ ) {
206 if( i != 1 ) {
207 sb.append( ", " );
208 }
209 sb.append( m_elements[ i ] );
210 }
211 sb.append( " ]" );
212 return sb.toString();
213 }
214 }
215