From a427df09aaab492e1004b3688aee90060461fbbb Mon Sep 17 00:00:00 2001 From: Andreas Huber Date: Fri, 6 Nov 2020 19:41:48 +0100 Subject: [PATCH] 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. --- .../collections/MultiwayLongMerger.java | 72 +++++++++---------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/primitiveCollections/src/main/java/org/lucares/collections/MultiwayLongMerger.java b/primitiveCollections/src/main/java/org/lucares/collections/MultiwayLongMerger.java index a6deecd..92dc945 100644 --- a/primitiveCollections/src/main/java/org/lucares/collections/MultiwayLongMerger.java +++ b/primitiveCollections/src/main/java/org/lucares/collections/MultiwayLongMerger.java @@ -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,31 +34,35 @@ 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; } } static LongList unionSorted(Collection longLists) { assertAllListsAreSorted(longLists); - + final List queues = new ArrayList(); 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 longLists, final List 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;