1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
public override IEnumerable<T> Sort<T>(IComparer<T> sortFunction, IEnumerable<T> collection) { List<T> objectList = collection.ToList(); //Calculate an efficient step size. //Ofc it depends on many factors and it won't be perfect in every case. int divideValue = (int)Math.Pow(objectList.Count, 1 / 3); for (int partCount = divideValue; partCount > 0; partCount--) { //Split the objectList up into smaller lists and sort them parallel. List<List<T>> listParts = new List<List<T>>(); int elementsPerPart = objectList.Count / partCount; bool isEvenCollection = ((float)(objectList.Count / partCount)) % 1 == 0; for (int listPartIndex = 0; listPartIndex < partCount; listPartIndex++) { listParts.Add(objectList.GetRange(listPartIndex * elementsPerPart, elementsPerPart)); if (!isEvenCollection && listPartIndex == partCount - 1) //It is not an even number. We have to handle the uneven element. listParts[listParts.Count - 1].Add(objectList.ElementAt((listPartIndex * elementsPerPart) + elementsPerPart)); } //Sort all the lists with the bubblesort. Parallel.ForEach(listParts, (currentCollection) => { listParts[listParts.IndexOf(listParts.Where(currentListPart => currentListPart.Equals(currentCollection)).Single())] = SortFactory.Sort(sortFunction, currentCollection, SortMethod.Bubble).ToList(); }); //Create a temporary array which will get all the sorted results. T[] newObjectArray = new T[listParts.Sum(currentListPart => currentListPart.Count)]; for (int listPartIndex = 0; listPartIndex < partCount; listPartIndex++) Array.Copy(listParts[listPartIndex].ToArray(), 0, newObjectArray, listPartIndex * elementsPerPart, listParts[listPartIndex].Count); objectList = newObjectArray.ToList(); } return objectList; } } |