Add more PriorityQueue AddRange overloads

This commit is contained in:
Marek Lemańczyk committed 2025-09-16 13:52:21 +02:00
1 parent 6d80b36d70
commit ff38aa302a
2 files changed
+445

No files matched your search

@@ -448,6 +448,352 @@ namespace Recyclable.Collections
}
queue._size = newCount;
int half = newCount >> 1;
for (int i = half - 1; i >= 0; i--)
{
int index = i;
T item = queue._heap[index];
while (index < half)
{
int child = (index << 1) + 1;
int right = child + 1;
if (right < newCount && queue._comparer.Compare(queue._heap[right], queue._heap[child]) < 0)
{
child = right;
}
if (queue._comparer.Compare(queue._heap[child], item) >= 0)
{
break;
}
queue._heap[index] = queue._heap[child];
index = child;
}
queue._heap[index] = item;
}
}
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
internal static void AddRange<T>(this RecyclablePriorityQueue<T> queue, RecyclableQueue<T> items)
{
long longCount = items._count;
if (longCount == 0)
{
return;
}
int count = checked((int)longCount);
int startIndex = queue._size;
int newCount = startIndex + count;
EnsureCapacity(queue, newCount);
var sourceChunk = items._head;
int destIndex = startIndex;
while (sourceChunk != null)
{
int sourceIndex = sourceChunk.Bottom;
int sourceTop = sourceChunk.Top;
T[] source = sourceChunk.Value;
while (sourceIndex < sourceTop)
{
queue._heap[destIndex++] = source[sourceIndex++];
}
sourceChunk = sourceChunk.Next;
}
queue._size = newCount;
int half = newCount >> 1;
for (int i = half - 1; i >= 0; i--)
{
int index = i;
T item = queue._heap[index];
while (index < half)
{
int child = (index << 1) + 1;
int right = child + 1;
if (right < newCount && queue._comparer.Compare(queue._heap[right], queue._heap[child]) < 0)
{
child = right;
}
if (queue._comparer.Compare(queue._heap[child], item) >= 0)
{
break;
}
queue._heap[index] = queue._heap[child];
index = child;
}
queue._heap[index] = item;
}
}
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
internal static void AddRange<T>(this RecyclablePriorityQueue<T> queue, RecyclableStack<T> items)
{
long longCount = items._count;
if (longCount == 0)
{
return;
}
int count = checked((int)longCount);
int startIndex = queue._size;
int newCount = startIndex + count;
EnsureCapacity(queue, newCount);
var sourceChunk = items._current;
while (sourceChunk.Previous != null)
{
sourceChunk = sourceChunk.Previous;
}
int destIndex = startIndex;
while (sourceChunk != null)
{
T[] source = sourceChunk.Value;
int sourceCount = sourceChunk.Index;
int sourceIndex = 0;
while (sourceIndex < sourceCount)
{
queue._heap[destIndex++] = source[sourceIndex++];
}
sourceChunk = sourceChunk.Next;
}
queue._size = newCount;
int half = newCount >> 1;
for (int i = half - 1; i >= 0; i--)
{
int index = i;
T item = queue._heap[index];
while (index < half)
{
int child = (index << 1) + 1;
int right = child + 1;
if (right < newCount && queue._comparer.Compare(queue._heap[right], queue._heap[child]) < 0)
{
child = right;
}
if (queue._comparer.Compare(queue._heap[child], item) >= 0)
{
break;
}
queue._heap[index] = queue._heap[child];
index = child;
}
queue._heap[index] = item;
}
}
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
internal static void AddRange<T>(this RecyclablePriorityQueue<T> queue, RecyclableLinkedList<T> items)
{
long longCount = items._count;
if (longCount == 0)
{
return;
}
int count = checked((int)longCount);
int startIndex = queue._size;
int newCount = startIndex + count;
EnsureCapacity(queue, newCount);
var sourceChunk = items._head;
int destIndex = startIndex;
while (sourceChunk != null)
{
int sourceIndex = sourceChunk.Bottom;
int sourceTop = sourceChunk.Top;
T[] source = sourceChunk.Value;
while (sourceIndex < sourceTop)
{
queue._heap[destIndex++] = source[sourceIndex++];
}
sourceChunk = sourceChunk.Next;
}
queue._size = newCount;
int half = newCount >> 1;
for (int i = half - 1; i >= 0; i--)
{
int index = i;
T item = queue._heap[index];
while (index < half)
{
int child = (index << 1) + 1;
int right = child + 1;
if (right < newCount && queue._comparer.Compare(queue._heap[right], queue._heap[child]) < 0)
{
child = right;
}
if (queue._comparer.Compare(queue._heap[child], item) >= 0)
{
break;
}
queue._heap[index] = queue._heap[child];
index = child;
}
queue._heap[index] = item;
}
}
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
internal static void AddRange<T>(this RecyclablePriorityQueue<T> queue, RecyclableSortedSet<T> items)
{
int count = items._count;
if (count == 0)
{
return;
}
int startIndex = queue._size;
int newCount = startIndex + count;
EnsureCapacity(queue, newCount);
T[] source = items._items;
for (int i = 0; i < count; i++)
{
queue._heap[startIndex + i] = source[i];
}
queue._size = newCount;
int half = newCount >> 1;
for (int i = half - 1; i >= 0; i--)
{
int index = i;
T item = queue._heap[index];
while (index < half)
{
int child = (index << 1) + 1;
int right = child + 1;
if (right < newCount && queue._comparer.Compare(queue._heap[right], queue._heap[child]) < 0)
{
child = right;
}
if (queue._comparer.Compare(queue._heap[child], item) >= 0)
{
break;
}
queue._heap[index] = queue._heap[child];
index = child;
}
queue._heap[index] = item;
}
}
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
internal static void AddRange<T>(this RecyclablePriorityQueue<T> queue, RecyclableHashSet<T> items)
{
int count = items._count;
if (count == 0)
{
return;
}
int startIndex = queue._size;
int newCount = startIndex + count;
EnsureCapacity(queue, newCount);
var entries = items._entries;
int shift = items._blockShift,
mask = items._blockSizeMinus1;
for (int i = 0; i < count; i++)
{
queue._heap[startIndex + i] = entries[i >> shift][i & mask].Value;
}
queue._size = newCount;
int half = newCount >> 1;
for (int i = half - 1; i >= 0; i--)
{
int index = i;
T item = queue._heap[index];
while (index < half)
{
int child = (index << 1) + 1;
int right = child + 1;
if (right < newCount && queue._comparer.Compare(queue._heap[right], queue._heap[child]) < 0)
{
child = right;
}
if (queue._comparer.Compare(queue._heap[child], item) >= 0)
{
break;
}
queue._heap[index] = queue._heap[child];
index = child;
}
queue._heap[index] = item;
}
}
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
internal static void AddRange<T>(this RecyclablePriorityQueue<T> queue, RecyclableLongList<T> items)
{
long longCount = items._longCount;
if (longCount == 0)
{
return;
}
int blockSize = items._blockSize;
int fullBlocks = (int)(longCount >> items._blockSizePow2BitShift);
int lastBlockLength = (int)(longCount & items._blockSizeMinus1);
int startIndex = queue._size;
int newCount = startIndex + checked((int)longCount);
EnsureCapacity(queue, newCount);
int destIndex = startIndex;
for (int blockIndex = 0; blockIndex < fullBlocks; blockIndex++)
{
T[] block = items._memoryBlocks[blockIndex];
int sourceIndex = 0;
while (sourceIndex < blockSize)
{
queue._heap[destIndex++] = block[sourceIndex++];
}
}
if (lastBlockLength > 0)
{
T[] block = items._memoryBlocks[fullBlocks];
int sourceIndex = 0;
while (sourceIndex < lastBlockLength)
{
queue._heap[destIndex++] = block[sourceIndex++];
}
}
queue._size = newCount;
int half = newCount >> 1;
for (int i = half - 1; i >= 0; i--)
{
@@ -532,6 +878,30 @@ namespace Recyclable.Collections
{
AddRange(queue, priorityQueue);
}
else if (items is RecyclableQueue<T> recyclableQueue)
{
AddRange(queue, recyclableQueue);
}
else if (items is RecyclableStack<T> recyclableStack)
{
AddRange(queue, recyclableStack);
}
else if (items is RecyclableLinkedList<T> linkedList)
{
AddRange(queue, linkedList);
}
else if (items is RecyclableSortedSet<T> sortedSet)
{
AddRange(queue, sortedSet);
}
else if (items is RecyclableHashSet<T> hashSet)
{
AddRange(queue, hashSet);
}
else if (items is RecyclableLongList<T> longList)
{
AddRange(queue, longList);
}
else if (items is T[] array)
{
AddRange(queue, array);
@@ -148,6 +148,81 @@ namespace Recyclable.CollectionsTests
_ = queue.Should().HaveCount(2).And.Contain((long?)null);
}
[Fact]
public void AddRangeQueueShouldAddItemsInSortedOrder()
{
using var source = new RecyclableQueue<int>(_testData);
using var queue = new RecyclablePriorityQueue<int>();
queue.AddRange(source);
var result = new List<int>();
while (queue.LongCount > 0)
{
result.Add(queue.Dequeue());
}
_ = result.Should().Equal(_testData.Order());
}
[Fact]
public void AddRangeQueueShouldNotOverrideItems()
{
using var source = new RecyclableQueue<int>(_testData);
using var queue = new RecyclablePriorityQueue<int>();
queue.AddRange(source);
queue.AddRange(source);
var expected = _testData.Concat(_testData).Order().ToArray();
var result = new List<int>();
while (queue.LongCount > 0)
{
result.Add(queue.Dequeue());
}
_ = result.Should().Equal(expected);
}
[Fact]
public void AddRangeStackShouldAddItemsInSortedOrder()
{
using var source = new RecyclableStack<int>(_testData);
using var queue = new RecyclablePriorityQueue<int>();
queue.AddRange(source);
var result = new List<int>();
while (queue.LongCount > 0)
{
result.Add(queue.Dequeue());
}
_ = result.Should().Equal(_testData.Order());
}
[Fact]
public void AddRangeSortedSetShouldAddItemsInSortedOrder()
{
using var source = new RecyclableSortedSet<int>();
foreach (int item in _testData)
{
source.Add(item);
}
using var queue = new RecyclablePriorityQueue<int>();
queue.AddRange(source);
var result = new List<int>();
while (queue.LongCount > 0)
{
result.Add(queue.Dequeue());
}
_ = result.Should().Equal(_testData.Order());
}
}
}