Во-первых, речь идет не о массиве с подпоследовательностями, которые могут быть в некотором порядке, прежде чем мы начнем сортировку, это о массиве специальной структуры.Быстрый сортировать частично отсортированный массив
Я пишу сейчас простой метод, который сортирует данные. До сих пор я использовал Array.Sort
, но PLINQ
OrderBy
превосходит стандарт Array.Sort
на больших массивах.
Поэтому я решил написать собственную реализацию многопоточности. Идея была простой: разбивать массив на разделы, параллельно сортировать каждый раздел, а затем объединять все результаты в один массив.
Теперь я делаюсь с разделения и сортировки:
public class PartitionSorter
{
public static void Sort(int[] arr)
{
var ranges = Range.FromArray(arr);
var allDone = new ManualResetEventSlim(false, ranges.Length*2);
int completed = 0;
foreach (var range in ranges)
{
ThreadPool.QueueUserWorkItem(r =>
{
var rr = (Range) r;
Array.Sort(arr, rr.StartIndex, rr.Length);
if (Interlocked.Increment(ref completed) == ranges.Length)
allDone.Set();
}, range);
}
allDone.Wait();
}
}
public class Range
{
public int StartIndex { get; }
public int Length { get; }
public Range(int startIndex, int endIndex)
{
StartIndex = startIndex;
Length = endIndex;
}
public static Range[] FromArray<T>(T[] source)
{
int processorCount = Environment.ProcessorCount;
int partitionLength = (int) (source.Length/(double) processorCount);
var result = new Range[processorCount];
int start = 0;
for (int i = 0; i < result.Length - 1; i++)
{
result[i] = new Range(start, partitionLength);
start += partitionLength;
}
result[result.Length - 1] = new Range(start, source.Length - start);
return result;
}
}
В результате я получаю массив с особой структурой, например
[1 3 5 | 2 4 7 | 6 8 9]
Теперь, как я могу использовать эту информацию и закончить сортировку ? Сортировки вставки и другие не используют информацию о том, что данные в блоках уже отсортированы, и нам просто нужно объединить их вместе. Я попытался применить некоторые алгоритмы от Merge sort
, но не смог.
Поскольку вы по сути делаете Merge-Sort, вам следует продолжить в этом направлении! Почему вы не смогли реализовать Merge-Sort? – MrPaulch
@MrPaulch, потому что трудно реализовать сортировку слияния 'in-place'. До того, как я использовал qsort, который хорош на месте, но его производительность хуже, чем наивный singlethread 'Array.Sort' из-за случайного доступа к памяти. –
Затем вы должны адаптировать алгоритм к [Quicksort] (https://en.wikipedia.org/wiki/Quicksort) - 'Array.Sort' фактически использует Introsort, который является гибридом * Quicksort * и * Heapsort * - Я когда-то реализовал высокоспециализированный алгоритм Quicksort, который превзошел «Array.Sort», поскольку он знал, какие данные он должен сортировать. – MrPaulch