Improvement of BinaryHeap.remove() with a HashMap to avoid iterating through the list

This commit is contained in:
Yohan Simard 2020-05-19 18:33:46 +02:00
parent db095f9ea9
commit a2db6d26a5

View file

@ -1,13 +1,15 @@
package org.insa.graphs.algorithm.utils; package org.insa.graphs.algorithm.utils;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
/** /**
* Implements a binary heap containing elements of type E. * Implements a binary heap containing elements of type E.
* * <p>
* Note that all comparisons are based on the compareTo method, hence E must * Note that all comparisons are based on the compareTo method, hence E must
* implement Comparable * implement Comparable
* *
* @author Mark Allen Weiss * @author Mark Allen Weiss
* @author DLB * @author DLB
*/ */
@ -15,6 +17,7 @@ public class BinaryHeap<E extends Comparable<E>> implements PriorityQueue<E> {
// Number of elements in heap. // Number of elements in heap.
private int currentSize; private int currentSize;
private Map<E, Integer> elementIndexes = new HashMap<>();
// The heap array. // The heap array.
protected final ArrayList<E> array; protected final ArrayList<E> array;
@ -29,16 +32,18 @@ public class BinaryHeap<E extends Comparable<E>> implements PriorityQueue<E> {
/** /**
* Construct a copy of the given heap. * Construct a copy of the given heap.
* *
* @param heap Binary heap to copy. * @param heap Binary heap to copy.
*/ */
public BinaryHeap(BinaryHeap<E> heap) { public BinaryHeap(BinaryHeap<E> heap) {
this.currentSize = heap.currentSize; this.currentSize = heap.currentSize;
this.array = new ArrayList<E>(heap.array); this.array = new ArrayList<E>(heap.array);
this.elementIndexes = new HashMap<>(heap.elementIndexes);
} }
/** /**
* Check if each element is lower than its children * Check if each element is lower than its children
*
* @return true if valid, false otherwise * @return true if valid, false otherwise
*/ */
public boolean isValid() { public boolean isValid() {
@ -62,15 +67,15 @@ public class BinaryHeap<E extends Comparable<E>> implements PriorityQueue<E> {
/** /**
* Set an element at the given index. * Set an element at the given index.
* *
* @param index Index at which the element should be set. * @param index Index at which the element should be set.
* @param value Element to set. * @param value Element to set.
*/ */
private void arraySet(int index, E value) { private void arraySet(int index, E value) {
elementIndexes.put(value, index);
if (index == this.array.size()) { if (index == this.array.size()) {
this.array.add(value); this.array.add(value);
} } else {
else {
this.array.set(index, value); this.array.set(index, value);
} }
} }
@ -98,15 +103,13 @@ public class BinaryHeap<E extends Comparable<E>> implements PriorityQueue<E> {
/** /**
* Internal method to percolate up in the heap. * Internal method to percolate up in the heap.
* *
* @param index Index at which the percolate begins. * @param index Index at which the percolate begins.
*/ */
private void percolateUp(int index) { private void percolateUp(int index) {
E x = this.array.get(index); E x = this.array.get(index);
for (; index > 0 for (; index > 0 && x.compareTo(this.array.get(indexParent(index))) < 0; index = indexParent(index)) {
&& x.compareTo(this.array.get(indexParent(index))) < 0; index = indexParent(
index)) {
E moving_val = this.array.get(indexParent(index)); E moving_val = this.array.get(indexParent(index));
this.arraySet(index, moving_val); this.arraySet(index, moving_val);
} }
@ -116,7 +119,7 @@ public class BinaryHeap<E extends Comparable<E>> implements PriorityQueue<E> {
/** /**
* Internal method to percolate down in the heap. * Internal method to percolate down in the heap.
* *
* @param index Index at which the percolate begins. * @param index Index at which the percolate begins.
*/ */
private void percolateDown(int index) { private void percolateDown(int index) {
@ -136,8 +139,7 @@ public class BinaryHeap<E extends Comparable<E>> implements PriorityQueue<E> {
this.arraySet(ileft, current); this.arraySet(ileft, current);
this.percolateDown(ileft); this.percolateDown(ileft);
} }
} } else {
else {
// Right is smaller // Right is smaller
if (right.compareTo(current) < 0) { if (right.compareTo(current) < 0) {
this.arraySet(index, right); this.arraySet(index, right);
@ -167,21 +169,14 @@ public class BinaryHeap<E extends Comparable<E>> implements PriorityQueue<E> {
@Override @Override
public void remove(E x) throws ElementNotFoundException { public void remove(E x) throws ElementNotFoundException {
int index = 0; Integer index = elementIndexes.remove(x);
// We avoid array.indexOf(x) because we don't need to search if (index == null) throw new ElementNotFoundException(x);
// through the whole list, we can stop at indexSize. currentSize--;
boolean found = false; if (currentSize != 0 && index != currentSize) {
while(!found && index < currentSize) { arraySet(index, array.get(currentSize));
if (array.get(index) == x) percolateUp(index);
found =true; percolateDown(index);
else
index++;
} }
if (!found) throw new ElementNotFoundException(x);
arraySet(index, array.get(--currentSize));
percolateUp(index);
percolateDown(index);
} }
@Override @Override
@ -194,15 +189,19 @@ public class BinaryHeap<E extends Comparable<E>> implements PriorityQueue<E> {
@Override @Override
public E deleteMin() throws EmptyPriorityQueueException { public E deleteMin() throws EmptyPriorityQueueException {
E minItem = findMin(); E minItem = findMin();
E lastItem = this.array.get(--this.currentSize); elementIndexes.remove(minItem);
this.arraySet(0, lastItem); currentSize--;
this.percolateDown(0); if (currentSize != 0) {
E lastItem = this.array.get(this.currentSize);
this.arraySet(0, lastItem);
this.percolateDown(0);
}
return minItem; return minItem;
} }
/** /**
* Creates a multi-lines string representing a sorted view of this binary heap. * Creates a multi-lines string representing a sorted view of this binary heap.
* *
* @return a string containing a sorted view this binary heap. * @return a string containing a sorted view this binary heap.
*/ */
public String toStringSorted() { public String toStringSorted() {
@ -211,10 +210,9 @@ public class BinaryHeap<E extends Comparable<E>> implements PriorityQueue<E> {
/** /**
* Creates a multi-lines string representing a sorted view of this binary heap. * Creates a multi-lines string representing a sorted view of this binary heap.
* *
* @param maxElement Maximum number of elements to display. or {@code -1} to * @param maxElement Maximum number of elements to display. or {@code -1} to
* display all the elements. * display all the elements.
*
* @return a string containing a sorted view this binary heap. * @return a string containing a sorted view this binary heap.
*/ */
public String toStringSorted(int maxElement) { public String toStringSorted(int maxElement) {
@ -223,7 +221,7 @@ public class BinaryHeap<E extends Comparable<E>> implements PriorityQueue<E> {
/** /**
* Creates a multi-lines string representing a tree view of this binary heap. * Creates a multi-lines string representing a tree view of this binary heap.
* *
* @return a string containing a tree view of this binary heap. * @return a string containing a tree view of this binary heap.
*/ */
public String toStringTree() { public String toStringTree() {
@ -232,9 +230,8 @@ public class BinaryHeap<E extends Comparable<E>> implements PriorityQueue<E> {
/** /**
* Creates a multi-lines string representing a tree view of this binary heap. * Creates a multi-lines string representing a tree view of this binary heap.
* *
* @param maxDepth Maximum depth of the tree to display. * @param maxDepth Maximum depth of the tree to display.
*
* @return a string containing a tree view of this binary heap. * @return a string containing a tree view of this binary heap.
*/ */
public String toStringTree(int maxDepth) { public String toStringTree(int maxDepth) {