private static IList <TSource> Sort <TSource, TKey>(IList <TSource> items, IList <TKey> keys, int begin, int end, int insertionSortCount, IComparer <TKey> comparer) { for (int i = begin; i < end; i += insertionSortCount) { InsertionSort.Sort(items, keys, i, Math.Min(i + insertionSortCount, end), comparer); } IList <TSource> srcValues = items; IList <TKey> srcKeys = keys; IList <TSource> destValues = new TSource[items.Count]; IList <TKey> destKeys = new TKey[items.Count]; for (int i = insertionSortCount; i < end - begin; i *= 2) { for (int j = begin; j < end; j += i * 2) { Merge(srcValues, srcKeys, destValues, destKeys, j, i, end, comparer); } StdUtils.Swap(ref srcValues, ref destValues); StdUtils.Swap(ref srcKeys, ref destKeys); } return(srcValues); }
public static IList <TSource> Sort <TSource>(IList <TSource> items, int begin, int end, int insertionSortCount, IComparer <TSource> comparer) { for (int i = begin; i < end; i += insertionSortCount) { InsertionSort.Sort(items, i, Math.Min(i + insertionSortCount, end), comparer); } IList <TSource> src = items; IList <TSource> dest = new TSource[items.Count]; for (int i = insertionSortCount; i < end - begin; i *= 2) { for (int j = begin; j < end; j += i * 2) { Merge(src, dest, j, i, end, comparer); } StdUtils.Swap(ref src, ref dest); } return(src); }
public static async Task <IList <TSource> > Sort <TSource>(IList <TSource> items, int begin, int end, int insertionSortCount, int threadCount, IComparer <TSource> comparer) { int insertionSortActionsCount = (int)Math.Ceiling((end - begin) / (double)insertionSortCount); int depth = (int)Math.Ceiling(Math.Log(insertionSortActionsCount, 2)); int donesCount = 0; IList <bool> dones = new bool[2 * insertionSortActionsCount + depth]; Queue <Action> queue = new Queue <Action>(); for (int i = begin; i < end; i += insertionSortCount) { int index = donesCount++; int insertionBegin = i; int insertionEnd = Math.Min(i + insertionSortCount, end); queue.Enqueue(() => InsertionSort(index, insertionBegin, insertionEnd)); } IList <TSource> items1 = items; IList <TSource> items2 = new TSource[items.Count]; for (int range = insertionSortCount; range < end - begin; range *= 2) { int lastActionsCount = (int)Math.Ceiling((end - begin) / (double)range); int lastActionsBegin = queue.Count - lastActionsCount; int currentRange = range; IList <TSource> src = items1, dest = items2; for (int j = 0, rangeBegin = begin; rangeBegin < end; j++, rangeBegin += range * 2) { int leftNodeIndex = lastActionsBegin + j * 2; int rightNodeIndex = lastActionsBegin + Math.Min(j * 2 + 1, lastActionsCount); int index = donesCount++; int currentBegin = rangeBegin; queue.Enqueue(() => Merge(leftNodeIndex, rightNodeIndex, index, src, dest, currentBegin, currentRange)); } StdUtils.Swap(ref items1, ref items2); } await AsyncUtils.ParallelForEach(queue, threadCount); return(items1); void InsertionSort(int thisIndex, int insertionSortBegin, int insertionSortEnd) { Linq.Sort.InsertionSort.Sort(items, insertionSortBegin, insertionSortEnd, comparer); lock (dones) { dones[thisIndex] = true; Monitor.PulseAll(dones); } } void Merge(int leftIndex, int rightIndex, int thisIndex, IList <TSource> mergeSrc, IList <TSource> mergeDest, int mergeBegin, int size) { lock (dones) { while (!dones[leftIndex]) { Monitor.Wait(dones); } while (!dones[rightIndex]) { Monitor.Wait(dones); } } MergeSort.Merge(mergeSrc, mergeDest, mergeBegin, size, end, comparer); lock (dones) { dones[thisIndex] = true; Monitor.PulseAll(dones); } } }