1 16 package org.apache.commons.collections; 17 18 import java.util.AbstractCollection ; 19 import java.util.Comparator ; 20 import java.util.Iterator ; 21 import java.util.NoSuchElementException ; 22 23 62 public final class BinaryHeap extends AbstractCollection 63 implements PriorityQueue, Buffer { 64 65 68 private final static int DEFAULT_CAPACITY = 13; 69 72 int m_size; 76 Object [] m_elements; 82 boolean m_isMinHeap; 86 Comparator m_comparator; 88 91 public BinaryHeap() { 92 this(DEFAULT_CAPACITY, true); 93 } 94 95 102 public BinaryHeap(Comparator comparator) { 103 this(); 104 m_comparator = comparator; 105 } 106 107 115 public BinaryHeap(int capacity) { 116 this(capacity, true); 117 } 118 119 128 public BinaryHeap(int capacity, Comparator comparator) { 129 this(capacity); 130 m_comparator = comparator; 131 } 132 133 139 public BinaryHeap(boolean isMinHeap) { 140 this(DEFAULT_CAPACITY, isMinHeap); 141 } 142 143 151 public BinaryHeap(boolean isMinHeap, Comparator comparator) { 152 this(isMinHeap); 153 m_comparator = comparator; 154 } 155 156 167 public BinaryHeap(int capacity, boolean isMinHeap) { 168 if (capacity <= 0) { 169 throw new IllegalArgumentException ("invalid capacity"); 170 } 171 m_isMinHeap = isMinHeap; 172 173 m_elements = new Object [capacity + 1]; 175 } 176 177 188 public BinaryHeap(int capacity, boolean isMinHeap, Comparator comparator) { 189 this(capacity, isMinHeap); 190 m_comparator = comparator; 191 } 192 193 197 public void clear() { 198 m_elements = new Object [m_elements.length]; m_size = 0; 200 } 201 202 208 public boolean isEmpty() { 209 return m_size == 0; 210 } 211 212 218 public boolean isFull() { 219 return m_elements.length == m_size + 1; 221 } 222 223 228 public void insert(Object element) { 229 if (isFull()) { 230 grow(); 231 } 232 if (m_isMinHeap) { 234 percolateUpMinHeap(element); 235 } else { 236 percolateUpMaxHeap(element); 237 } 238 } 239 240 246 public Object peek() throws NoSuchElementException { 247 if (isEmpty()) { 248 throw new NoSuchElementException (); 249 } else { 250 return m_elements[1]; 251 } 252 } 253 254 260 public Object pop() throws NoSuchElementException { 261 final Object result = peek(); 262 m_elements[1] = m_elements[m_size--]; 263 264 m_elements[m_size + 1] = null; 267 268 if (m_size != 0) { 269 if (m_isMinHeap) { 271 percolateDownMinHeap(1); 272 } else { 273 percolateDownMaxHeap(1); 274 } 275 } 276 277 return result; 278 } 279 280 287 protected void percolateDownMinHeap(final int index) { 288 final Object element = m_elements[index]; 289 int hole = index; 290 291 while ((hole * 2) <= m_size) { 292 int child = hole * 2; 293 294 if (child != m_size && compare(m_elements[child + 1], m_elements[child]) < 0) { 297 child++; 298 } 299 300 if (compare(m_elements[child], element) >= 0) { 302 break; 303 } 304 305 m_elements[hole] = m_elements[child]; 306 hole = child; 307 } 308 309 m_elements[hole] = element; 310 } 311 312 319 protected void percolateDownMaxHeap(final int index) { 320 final Object element = m_elements[index]; 321 int hole = index; 322 323 while ((hole * 2) <= m_size) { 324 int child = hole * 2; 325 326 if (child != m_size && compare(m_elements[child + 1], m_elements[child]) > 0) { 329 child++; 330 } 331 332 if (compare(m_elements[child], element) <= 0) { 334 break; 335 } 336 337 m_elements[hole] = m_elements[child]; 338 hole = child; 339 } 340 341 m_elements[hole] = element; 342 } 343 344 351 protected void percolateUpMinHeap(final int index) { 352 int hole = index; 353 Object element = m_elements[hole]; 354 while (hole > 1 && compare(element, m_elements[hole / 2]) < 0) { 355 final int next = hole / 2; 358 m_elements[hole] = m_elements[next]; 359 hole = next; 360 } 361 m_elements[hole] = element; 362 } 363 364 371 protected void percolateUpMinHeap(final Object element) { 372 m_elements[++m_size] = element; 373 percolateUpMinHeap(m_size); 374 } 375 376 383 protected void percolateUpMaxHeap(final int index) { 384 int hole = index; 385 Object element = m_elements[hole]; 386 387 while (hole > 1 && compare(element, m_elements[hole / 2]) > 0) { 388 final int next = hole / 2; 391 m_elements[hole] = m_elements[next]; 392 hole = next; 393 } 394 395 m_elements[hole] = element; 396 } 397 398 405 protected void percolateUpMaxHeap(final Object element) { 406 m_elements[++m_size] = element; 407 percolateUpMaxHeap(m_size); 408 } 409 410 418 private int compare(Object a, Object b) { 419 if (m_comparator != null) { 420 return m_comparator.compare(a, b); 421 } else { 422 return ((Comparable ) a).compareTo(b); 423 } 424 } 425 426 429 protected void grow() { 430 final Object [] elements = new Object [m_elements.length * 2]; 431 System.arraycopy(m_elements, 0, elements, 0, m_elements.length); 432 m_elements = elements; 433 } 434 435 441 public String toString() { 442 final StringBuffer sb = new StringBuffer (); 443 444 sb.append("[ "); 445 446 for (int i = 1; i < m_size + 1; i++) { 447 if (i != 1) { 448 sb.append(", "); 449 } 450 sb.append(m_elements[i]); 451 } 452 453 sb.append(" ]"); 454 455 return sb.toString(); 456 } 457 458 459 464 public Iterator iterator() { 465 return new Iterator () { 466 467 private int index = 1; 468 private int lastReturnedIndex = -1; 469 470 public boolean hasNext() { 471 return index <= m_size; 472 } 473 474 public Object next() { 475 if (!hasNext()) throw new NoSuchElementException (); 476 lastReturnedIndex = index; 477 index++; 478 return m_elements[lastReturnedIndex]; 479 } 480 481 public void remove() { 482 if (lastReturnedIndex == -1) { 483 throw new IllegalStateException (); 484 } 485 m_elements[ lastReturnedIndex ] = m_elements[ m_size ]; 486 m_elements[ m_size ] = null; 487 m_size--; 488 if( m_size != 0 && lastReturnedIndex <= m_size) { 489 int compareToParent = 0; 490 if (lastReturnedIndex > 1) { 491 compareToParent = compare(m_elements[lastReturnedIndex], 492 m_elements[lastReturnedIndex / 2]); 493 } 494 if (m_isMinHeap) { 495 if (lastReturnedIndex > 1 && compareToParent < 0) { 496 percolateUpMinHeap(lastReturnedIndex); 497 } else { 498 percolateDownMinHeap(lastReturnedIndex); 499 } 500 } else { if (lastReturnedIndex > 1 && compareToParent > 0) { 502 percolateUpMaxHeap(lastReturnedIndex); 503 } else { 504 percolateDownMaxHeap(lastReturnedIndex); 505 } 506 } 507 } 508 index--; 509 lastReturnedIndex = -1; 510 } 511 512 }; 513 } 514 515 516 522 public boolean add(Object object) { 523 insert(object); 524 return true; 525 } 526 527 533 public Object get() { 534 try { 535 return peek(); 536 } catch (NoSuchElementException e) { 537 throw new BufferUnderflowException(); 538 } 539 } 540 541 547 public Object remove() { 548 try { 549 return pop(); 550 } catch (NoSuchElementException e) { 551 throw new BufferUnderflowException(); 552 } 553 } 554 555 560 public int size() { 561 return m_size; 562 } 563 564 } 565 | Popular Tags |