public WrappedBinaryMinHeap(int maxSize, int fanout, boolean classicalRemove) { this.delegate = new BinaryMinHeap<>(maxSize, fanout, classicalRemove); this.map = new IdentityHashMap<>(maxSize); }
/** * Increases the priority (=decrease the given double value) of the element. * If the element ins not part of the queue, it is added. If the new priority * is lower than the existing one, the method returns <tt>false</tt> * * @return <tt>true</tt> if the elements priority was decreased. */ @Override public boolean decreaseKey(E value, double cost) { // If the element is not yet present in the heap, simply add it. int index = indices[this.getIndex(value)]; if (index < 0) { return this.add(value, cost); } /* * If the cost should be increased, we cannot do this. Therefore we * return false. */ double oldCost = costs[index]; if (oldCost < cost) return false; // update costs in array siftUp(index, value, cost); return true; }
private void siftUp(int index, E newEntry, double newCost) { while (index > 0) { int parentIndex = getParentIndex(index); double parentCost = costs[parentIndex]; if (newCost > parentCost) break; if (newCost == parentCost && this.getIndex(newEntry) > this.getIndex(data[parentIndex])) break; this.copyData(index, parentIndex); // for next iteration index = parentIndex; } data[index] = newEntry; costs[index] = newCost; indices[this.getIndex(newEntry)] = index; }
@Override /*package*/ RouterPriorityQueue<? extends Node> createRouterPriorityQueue() { /* * Re-use existing BinaryMinHeap instead of creating a new one. For large networks (> 10^6 nodes and links) this reduced * the computation time by 40%! cdobler, oct'15 */ if (this.routingNetwork instanceof ArrayRoutingNetwork) { int size = this.routingNetwork.getNodes().size(); if (this.heap == null || this.maxSize != size) { this.maxSize = size; this.heap = new BinaryMinHeap<>(maxSize); return this.heap; } else { this.heap.reset(); return this.heap; } // int maxSize = this.routingNetwork.getNodes().size(); // return new BinaryMinHeap<ArrayRoutingNetworkNode>(maxSize); } else { return super.createRouterPriorityQueue(); } }
/** * Retrieves and removes the head of this queue, or <tt>null</tt> if this * queue is empty. * * @return the head of this queue, or <tt>null</tt> if this queue is empty. */ @Override public E poll() { E minValue; if (isEmpty()) return null; else { this.modCount++; minValue = data[0]; if (classicalRemove) { data[0] = data[heapSize - 1]; costs[0] = costs[heapSize - 1]; indices[this.getIndex(data[0])] = 0; indices[this.getIndex(minValue)] = -1; heapSize--; if (heapSize > 0) siftDown(0); } else { siftDownUp(0); indices[this.getIndex(minValue)] = -1; } return minValue; } }
int index = indices[this.getIndex(value)]; if (index < 0) { return false; if (classicalRemove) { boolean decreasedKey = decreaseKey(value, Double.NEGATIVE_INFINITY); if (decreasedKey && data[0] == value) { this.poll(); return true; } else return false; } else { siftDownUp(index); indices[this.getIndex(value)] = -1; this.modCount++; return true;
private void siftDown(int nodeIndex) { int leftChildIndex = getLeftChildIndex(nodeIndex); if (leftChildIndex >= heapSize) return; int minIndex = -1; double minCosts = Double.POSITIVE_INFINITY; int limitChildIndex = Math.min(leftChildIndex + fanout, heapSize + 1); for (int childIndex = leftChildIndex; childIndex < limitChildIndex; childIndex++) { /* * If the costs are equal, use the array indices to define the sort order. * Doing so should guarantee a deterministic order of the heap entries. */ double childCosts = costs[childIndex]; if (childCosts <= minCosts) { if (childCosts < minCosts || this.getIndex(data[childIndex]) < this.getIndex(data[minIndex])) { minIndex = childIndex; minCosts = childCosts; } } } if (minIndex >= 0) { swapData(nodeIndex, minIndex); siftDown(minIndex); } }
private int removeSiftDown(int nodeIndex) { while(true) { int leftChildIndex = getLeftChildIndex(nodeIndex); if (leftChildIndex >= heapSize) break; double leftCosts = costs[leftChildIndex]; int limitChildIndex = Math.min(leftChildIndex + fanout, heapSize); for (int rightChildIndex = leftChildIndex + 1; rightChildIndex < limitChildIndex; rightChildIndex++) { /* * We use the sentinel values Double.MAX_VALUE to protect * ourselves from looking beyond the heap's true size */ double rightCosts = costs[rightChildIndex]; if (leftCosts >= rightCosts && (leftCosts > rightCosts || this.getIndex(data[leftChildIndex]) > this.getIndex(data[rightChildIndex]))) { leftChildIndex = rightChildIndex; leftCosts = rightCosts; } } copyData(nodeIndex, leftChildIndex); nodeIndex = leftChildIndex; } return nodeIndex; }
/** * Adds the specified element to this priority queue, with the given priority. * If the element is already present in the queue, it is not added a second * time. * @param value * @param priority * @return <tt>true</tt> if the element was added to the collection. */ @Override public boolean add(E value, double priority) { if (value == null) { throw new NullPointerException("null values are not supported!"); } // if the element is already present in the queue, return false if (indices[this.getIndex(value)] >= 0) { return false; } else { if (heapSize == data.length) throw new RuntimeException("Heap's underlying storage is overflow!"); this.modCount++; siftUp(heapSize, value, priority); heapSize++; return true; } }
private void copyData(int indexTarget, int indexSource) { // copy HeapEntries E entry = data[indexSource]; data[indexTarget] = entry; // copy costs costs[indexTarget] = costs[indexSource]; // copy indices indices[this.getIndex(entry)] = indexTarget; }
@Override public boolean isEmpty() { return this.delegate.isEmpty(); }
@Override public Iterator<E> iterator() { return new ArrayIterator(this.delegate.iterator()); }
@Override public boolean add(E value, double priority) { return this.delegate.add(this.getOrCreateWrappedEntry(value), priority); }
@Override public boolean decreaseKey(E value, double priority) { return this.delegate.decreaseKey(this.getWrappedEntry(value), priority); }
@Override /*package*/ RouterPriorityQueue<? extends Node> createRouterPriorityQueue() { /* * Re-use existing BinaryMinHeap instead of creating a new one. For large networks (> 10^6 nodes and links) this reduced * the computation time by 40%! cdobler, oct'15 */ if (this.routingNetwork instanceof ArrayRoutingNetwork) { int size = this.routingNetwork.getNodes().size(); if (this.heap == null || this.maxSize != size) { this.maxSize = size; this.heap = new BinaryMinHeap<>(maxSize); return this.heap; } else { this.heap.reset(); return this.heap; } // int maxSize = this.routingNetwork.getNodes().size(); // return new BinaryMinHeap<ArrayRoutingNetworkNode>(maxSize); } else { return super.createRouterPriorityQueue(); } }
private void swapData(int index1, int index2) { // swap HeapEntries E entry1 = data[index1]; E entry2 = data[index2]; data[index1] = entry2; data[index2] = entry1; // swap costs double tmpCost = costs[index1]; costs[index1] = costs[index2]; costs[index2] = tmpCost; // swap indices indices[this.getIndex(entry1)] = index2; indices[this.getIndex(entry2)] = index1; }
@Override /*package*/ RouterPriorityQueue<? extends Node> createRouterPriorityQueue() { /* * Re-use existing BinaryMinHeap instead of creating a new one. For large networks (> 10^6 nodes and links) this reduced * the computation time by 40%! cdobler, oct'15 */ if (this.routingNetwork instanceof ArrayRoutingNetwork) { int size = this.routingNetwork.getNodes().size(); if (this.heap == null || this.maxSize != size) { this.maxSize = size; this.heap = new BinaryMinHeap<>(maxSize); return this.heap; } else { this.heap.reset(); return this.heap; } // int maxSize = this.routingNetwork.getNodes().size(); // return new BinaryMinHeap<ArrayRoutingNetworkNode>(maxSize); } else { return super.createRouterPriorityQueue(); } }
public WrappedBinaryMinHeap(int maxSize) { this.delegate = new BinaryMinHeap<>(maxSize); this.map = new IdentityHashMap<>(maxSize); }
/** * Resets the queue to its initial state. */ @Override public void reset() { /* * For a small number of remaining entries in the heap, only removing * them might be faster than overwriting all entries. However, when doing so, * we have to do twice as much array accesses. */ if (heapSize < indices.length / 10) { for (int i = 0; i < heapSize; i++) { indices[this.getIndex(data[i])] = -1; } } else { for (int i = 0; i < indices.length; i++) { indices[i] = -1; } } for (int i = 0; i < heapSize; i++) { costs[i] = Double.MAX_VALUE; } this.heapSize = 0; this.modCount = 0; }