Skip to content

Instantly share code, notes, and snippets.

@a3geek
Created August 31, 2021 04:04
Show Gist options
  • Save a3geek/995f21a0fa2bc057edc8e77df42a5226 to your computer and use it in GitHub Desktop.
Save a3geek/995f21a0fa2bc057edc8e77df42a5226 to your computer and use it in GitHub Desktop.
Span index merge sort.
private void MergeSort<T>(Span<T> arr, Span<int> indexs, Func<T, T, int> comparer) where T : struct
{
var loop = Mathf.CeilToInt(Mathf.Log(arr.Length, 2));
Span<int> indexs1 = stackalloc int[arr.Length];
Span<int> indexs2 = stackalloc int[arr.Length];
for(var i = 0; i < arr.Length; i++)
{
indexs1[i] = i;
indexs2[i] = i;
}
for(var i = 1; i <= loop; i++)
{
var block = (int)Mathf.Pow(2, i);
var splitCount = Mathf.CeilToInt((float)arr.Length / block);
var rbuf = i % 2 == 0 ? indexs1 : indexs2;
var wbuf = i % 2 == 1 ? indexs1 : indexs2;
for(var j = 0; j < splitCount; j++)
{
var offset = block * j;
var threshold = block / 2;
int idx = offset, idx1 = offset, idx2 = offset + threshold;
while(idx1 < offset + threshold && idx2 < offset + block && idx2 < arr.Length)
{
if(comparer(arr[rbuf[idx1]], arr[rbuf[idx2]]) <= 0)
{
wbuf[idx++] = rbuf[idx1];
idx1++;
}
else
{
wbuf[idx++] = rbuf[idx2];
idx2++;
}
}
var isLeftBlock = idx1 < offset + threshold;
for(var k = isLeftBlock ? idx1 : idx2; k < offset + (isLeftBlock ? threshold : block); k++)
{
if(idx >= arr.Length)
{
break;
}
wbuf[idx++] = rbuf[k];
}
}
}
var index = loop % 2 == 1 ? indexs1 : indexs2;
for(var i = 0; i < index.Length; i++)
{
indexs[i] = index[i];
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment