changed the value of UNSET from Long.MIN_VALUE to LONG.MAX_VALUE

That made the code in fillWithMinOfChildren() easier. We lost an early
out, though. But that should be negligible.
This commit is contained in:
2020-11-06 19:41:48 +01:00
parent 8a5309fbe8
commit a427df09aa

View File

@@ -6,9 +6,11 @@ import java.util.Collection;
import java.util.List; import java.util.List;
class MultiwayLongMerger { class MultiwayLongMerger {
private static final long UNSET = Long.MIN_VALUE; private static final long UNSET = Long.MAX_VALUE;
private static class LongQueue { private static class LongQueue {
private static final LongQueue EMPTY = new LongQueue(LongList.of());
final LongList wrapped; final LongList wrapped;
int offset = 0; int offset = 0;
@@ -32,6 +34,10 @@ class MultiwayLongMerger {
return wrapped.get(offset); return wrapped.get(offset);
} }
public long peekLast() {
return wrapped.get(wrapped.size() - 1);
}
@Override @Override
public String toString() { public String toString() {
return wrapped.sublist(offset).toString(); return wrapped.sublist(offset).toString();
@@ -50,13 +56,13 @@ class MultiwayLongMerger {
boolean hasValueUNSET = initQueues(longLists, queues); boolean hasValueUNSET = initQueues(longLists, queues);
final LongList result = new LongList(); final LongList result = new LongList();
if (hasValueUNSET) {
result.add(UNSET);
}
if (!queues.isEmpty()) { if (!queues.isEmpty()) {
mergeQueues(queues, result); mergeQueues(queues, result);
} }
if (hasValueUNSET) {
result.add(UNSET);
}
return result; return result;
} }
@@ -76,18 +82,16 @@ class MultiwayLongMerger {
private static boolean initQueues(Collection<LongList> longLists, final List<LongQueue> queues) { private static boolean initQueues(Collection<LongList> longLists, final List<LongQueue> queues) {
boolean hasValueUNSET = false; boolean hasValueUNSET = false;
for (LongList longList : longLists) { for (final LongList longList : longLists) {
if (!longList.isEmpty()) { if (!longList.isEmpty()) {
final LongQueue queue = new LongQueue(longList); final LongQueue queue = new LongQueue(longList);
while (!queue.isEmpty() && queue.peek() == UNSET) { if (!queue.isEmpty() && queue.peekLast() == UNSET) {
queue.pop();
hasValueUNSET = true; hasValueUNSET = true;
} }
if (!queue.isEmpty()) {
queues.add(queue); queues.add(queue);
} }
} }
}
return hasValueUNSET; return hasValueUNSET;
} }
@@ -125,6 +129,14 @@ class MultiwayLongMerger {
firstLeafIndex = heap.length / 2; firstLeafIndex = heap.length / 2;
Arrays.fill(heap, UNSET); Arrays.fill(heap, UNSET);
// fill the longQueues list with empty queues, so that we
// have a queue for every leaf in the heap. This makes fillWithMinOfChildren()
// easier, because it removes special cases.
for (int i = size ; i < nextPowOfTwo(size); i++) {
this.longQueues.add(LongQueue.EMPTY);
}
init(); init();
} }
@@ -139,7 +151,9 @@ class MultiwayLongMerger {
*/ */
public long pop() { public long pop() {
long result = heap[0]; long result = heap[0];
if (result != UNSET) {
fillWithMinOfChildren(0); fillWithMinOfChildren(0);
}
return result; return result;
} }
@@ -205,20 +219,7 @@ class MultiwayLongMerger {
final int chosenValue; final int chosenValue;
if (valueOfLeftChild == UNSET) {
if (valueOfRightChild == UNSET) {
heap[index] = UNSET;
return;
} else {
//left < right
heap[index] = valueOfRightChild;
chosenValue = rightChildIndex;
}
} else if (valueOfRightChild == UNSET) {
// left > right
heap[index] = valueOfLeftChild;
chosenValue = leftChildIndex;
} else {
if (valueOfLeftChild < valueOfRightChild) { if (valueOfLeftChild < valueOfRightChild) {
// left < right // left < right
heap[index] = valueOfLeftChild; heap[index] = valueOfLeftChild;
@@ -228,7 +229,6 @@ class MultiwayLongMerger {
heap[index] = valueOfRightChild; heap[index] = valueOfRightChild;
chosenValue = rightChildIndex; chosenValue = rightChildIndex;
} }
}
refillValue(chosenValue); refillValue(chosenValue);
} }