Nerfed/Nerfed.Runtime/Util/SpanExtensions.cs

147 lines
4.4 KiB
C#

namespace Nerfed.Runtime;
public static class SpanExtensions
{
public static void QuickSort<T>(this Span<T> span, Comparison<T> comparison) {
QuickSort(span, 0, span.Length - 1, comparison);
}
private static void QuickSort<T>(this Span<T> span, int leftIndex, int rightIndex, Comparison<T> comparison) {
for(;;) {
int i = leftIndex;
int j = rightIndex;
T pivot = span[leftIndex];
while(i <= j) {
while(comparison(span[i], pivot) < 0) {
i++;
}
while(comparison(span[j], pivot) > 0) {
j--;
}
if(i <= j) {
(span[i], span[j]) = (span[j], span[i]);
i++;
j--;
}
}
if(leftIndex < j) {
QuickSort(span, leftIndex, j, comparison);
}
if(i < rightIndex) {
leftIndex = i;
continue;
}
break;
}
}
public static void HeapSort<T>(this Span<T> span, Comparison<T> comparison) {
if(span.Length <= 1) {
return;
}
for(int i = span.Length / 2 - 1; i >= 0; i--) {
Heapify(span, span.Length, i, comparison);
}
for(int i = span.Length - 1; i >= 0; i--) {
(span[0], span[i]) = (span[i], span[0]);
Heapify(span, i, 0, comparison);
}
}
private static void Heapify<T>(Span<T> span, int size, int index, Comparison<T> comparison) {
for(;;) {
int largestIndex = index;
int leftChild = 2 * index + 1;
int rightChild = 2 * index + 2;
if(leftChild < size && comparison(span[leftChild], span[largestIndex]) > 0) {
largestIndex = leftChild;
}
if(rightChild < size && comparison(span[rightChild], span[largestIndex]) > 0) {
largestIndex = rightChild;
}
if(largestIndex != index) {
(span[index], span[largestIndex]) = (span[largestIndex], span[index]);
index = largestIndex;
continue;
}
break;
}
}
public static void MergeSort<T>(this Span<T> span, T[] leftArray, T[] rightArray, Comparison<T> comparison) {
MergeSort(span, leftArray, rightArray, 0, span.Length - 1, comparison);
}
private static void MergeSort<T>(this Span<T> span, T[] leftArray, T[] rightArray, int left, int right, Comparison<T> comparison) {
if(left < right) {
int middle = left + (right - left) / 2;
MergeSort(span, leftArray, rightArray, left, middle, comparison);
MergeSort(span, leftArray, rightArray, middle + 1, right, comparison);
MergeArray(span, leftArray, rightArray, left, middle, right, comparison);
}
}
private static void MergeArray<T>(Span<T> span, T[] leftArray, T[] rightArray, int left, int middle, int right, Comparison<T> comparison) {
int leftArrayLength = middle - left + 1;
int rightArrayLength = right - middle;
int i, j;
for(i = 0; i < leftArrayLength; ++i) {
leftArray[i] = span[left + i];
}
for(j = 0; j < rightArrayLength; ++j) {
rightArray[j] = span[middle + 1 + j];
}
i = 0;
j = 0;
int k = left;
while(i < leftArrayLength && j < rightArrayLength) {
if(comparison(leftArray[i], rightArray[j]) <= 0) {
span[k++] = leftArray[i++];
}
else {
span[k++] = rightArray[j++];
}
}
while(i < leftArrayLength) {
span[k++] = leftArray[i++];
}
while(j < rightArrayLength) {
span[k++] = rightArray[j++];
}
}
public static void InsertionSort<T>(this Span<T> span, Comparison<T> comparison) {
for(int i = 1; i < span.Length; i++) {
T key = span[i];
int flag = 0;
for(int j = i - 1; j >= 0 && flag != 1;) {
if(comparison(key, span[j]) < 0) {
span[j + 1] = span[j];
j--;
span[j + 1] = key;
}
else {
flag = 1;
}
}
}
}
}