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;
class MultiwayLongMerger {
private static final long UNSET = Long.MIN_VALUE;
private static final long UNSET = Long.MAX_VALUE;
private static class LongQueue {
private static final LongQueue EMPTY = new LongQueue(LongList.of());
final LongList wrapped;
int offset = 0;
@@ -32,13 +34,17 @@ class MultiwayLongMerger {
return wrapped.get(offset);
}
public long peekLast() {
return wrapped.get(wrapped.size() - 1);
}
@Override
public String toString() {
return wrapped.sublist(offset).toString();
}
public int size() {
return wrapped.size()-offset;
return wrapped.size() - offset;
}
}
@@ -50,13 +56,13 @@ class MultiwayLongMerger {
boolean hasValueUNSET = initQueues(longLists, queues);
final LongList result = new LongList();
if (hasValueUNSET) {
result.add(UNSET);
}
if (!queues.isEmpty()) {
mergeQueues(queues, result);
}
if (hasValueUNSET) {
result.add(UNSET);
}
return result;
}
@@ -76,16 +82,14 @@ class MultiwayLongMerger {
private static boolean initQueues(Collection<LongList> longLists, final List<LongQueue> queues) {
boolean hasValueUNSET = false;
for (LongList longList : longLists) {
for (final LongList longList : longLists) {
if (!longList.isEmpty()) {
final LongQueue queue = new LongQueue(longList);
while (!queue.isEmpty() && queue.peek() == UNSET) {
queue.pop();
if (!queue.isEmpty() && queue.peekLast() == UNSET) {
hasValueUNSET = true;
}
if (!queue.isEmpty()) {
queues.add(queue);
}
queues.add(queue);
}
}
return hasValueUNSET;
@@ -125,6 +129,14 @@ class MultiwayLongMerger {
firstLeafIndex = heap.length / 2;
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();
}
@@ -139,7 +151,9 @@ class MultiwayLongMerger {
*/
public long pop() {
long result = heap[0];
fillWithMinOfChildren(0);
if (result != UNSET) {
fillWithMinOfChildren(0);
}
return result;
}
@@ -197,37 +211,23 @@ class MultiwayLongMerger {
}
private void fillWithMinOfChildren(int index) {
final int leftChildIndex = index * 2 + 1; //leftChildIndex(index);
final int rightChildIndex = leftChildIndex+1;//rightChildIndex(index);
final int leftChildIndex = index * 2 + 1; // leftChildIndex(index);
final int rightChildIndex = leftChildIndex + 1;// rightChildIndex(index);
final long valueOfLeftChild = heap[leftChildIndex];
final long valueOfRightChild = heap[rightChildIndex];
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
if (valueOfLeftChild < valueOfRightChild) {
// left < right
heap[index] = valueOfLeftChild;
chosenValue = leftChildIndex;
} else {
if (valueOfLeftChild < valueOfRightChild) {
// left < right
heap[index] = valueOfLeftChild;
chosenValue = leftChildIndex;
} else {
// left >= right
heap[index] = valueOfRightChild;
chosenValue = rightChildIndex;
}
// left >= right
heap[index] = valueOfRightChild;
chosenValue = rightChildIndex;
}
refillValue(chosenValue);
@@ -235,7 +235,7 @@ class MultiwayLongMerger {
private void refillValue(int index) {
if (isLeaf(index)) {
final int listIndex = index - firstLeafIndex; //leafIndexToListIndex(index);
final int listIndex = index - firstLeafIndex; // leafIndexToListIndex(index);
final LongQueue queue = longQueues.get(listIndex);
heap[index] = queue.isEmpty() ? UNSET : queue.pop();
return;