基本思路:通过一趟排序,将要排序的数据分割成独立的2个部分,其中一部分的数据要比另一部分的所有数据都要小,再对这2个部分递归进行该分割,最后达到整个序列有序。

1 class Program 2 { 3 static void Main(string[] args) 4 { 5 var list2Sort = new List<int>(); 6 for (int i = 9000000; i > 0; i--) 7 { 8 list2Sort.Add(i); 9 } 10 var time =new Stopwatch(); 11 time.Start(); 12 Quicksort(list2Sort, 0, list2Sort.Count - 1); 13 //Quicksort(list2Sort, 0, list2Sort.Count - 1); 14 //QuicksortParallel(list2Sort, 0, list2Sort.Count - 1); 15 time.Stop(); 16 Console.WriteLine(time.ElapsedMilliseconds); 17 18 } 19 20 /// <summary> 21 /// Swaps the two values of the specified indexes 22 /// </summary> 23 /// <param name="arr">An IList where elements need to be swapped</param> 24 /// <param name="i">The first index to be swapped</param> 25 /// <param name="j">The second index to be swapped</param> 26 private static void Swap<T>(IList<T> arr, int i, int j) 27 { 28 var tmp = arr[i]; 29 arr[i] = arr[j]; 30 arr[j] = tmp; 31 } 32 33 /// <summary> 34 /// Partitions an IList by defining a pivot and then comparing the other members to this pivot. 35 /// </summary> 36 /// <param name="arr">The IList to partition</param> 37 /// <param name="low">The lowest index of the partition</param> 38 /// <param name="high">The highest index of the partition</param> 39 /// <returns>Returns the index of the chosen pivot</returns> 40 private static int Partition<T>(IList<T> arr, int low, int high) 41 where T : IComparable<T> 42 { 43 /* 44 * Defining the pivot position, here the middle element is used but the choice of a pivot 45 * is a rather complicated issue. Choosing the left element brings us to a worst-case performance, 46 * which is quite a common case, that's why it's not used here. 47 */ 48 var pivotPos = (high + low) / 2; 49 var pivot = arr[pivotPos]; 50 // Putting the pivot on the left of the partition (lowest index) to simplify the loop 51 Swap(arr, low, pivotPos); 52 53 /** The pivot remains on the lowest index until the end of the loop 54 * The left variable is here to keep track of the number of values 55 * that were compared as "less than" the pivot. 56 */ 57 var left = low; 58 for (var i = low + 1; i <= high; i++) 59 { 60 // If the value is greater than the pivot value we continue to the next index. 61 if (arr[i].CompareTo(pivot) >= 0) continue; 62 63 // If the value is less than the pivot, we increment our left counter (one more element below the pivot) 64 left++; 65 // and finally we swap our element on our left index. 66 Swap(arr, i, left); 67 } 68 69 // The pivot is still on the lowest index, we need to put it back after all values found to be "less than" the pivot. 70 Swap(arr, low, left); 71 72 // We return the new index of our pivot 73 return left; 74 } 75 76 /// <summary> 77 /// Realizes a Quicksort on an IList of IComparable items in a sequential way. 78 /// </summary> 79 /// <param name="arr">The IList of IComaparable to Quicksort</param> 80 /// <param name="left">The minimum index of the IList to Quicksort</param> 81 /// <param name="right">The maximum index of the IList to Quicksort</param> 82 private static void Quicksort<T>(IList<T> arr, int left, int right) where T : IComparable<T> 83 { 84 // If the list contains one or less element: no need to sort! 85 if (right <= left) return; 86 87 // Partitioning our list 88 var pivot = Partition(arr, left, right); 89 90 // Sorting the left of the pivot 91 Quicksort(arr, left, pivot - 1); 92 // Sorting the right of the pivot 93 Quicksort(arr, pivot + 1, right); 94 } 95 96 /// <summary> 97 /// Realizes a Quicksort on an IList of IComparable items. 98 /// Left and right side of the pivot are processed in parallel. 99 /// </summary> 100 /// <param name="arr">The IList of IComaparable to Quicksort</param> 101 /// <param name="left">The minimum index of the IList to Quicksort</param> 102 /// <param name="right">The maximum index of the IList to Quicksort</param> 103 private static void QuicksortParallel<T>(IList<T> arr, int left, int right) 104 where T : IComparable<T> 105 { 106 // Defining a minimum length to use parallelism, over which using parallelism 107 // got better performance than the sequential version. 108 const int threshold = 2048*8; 109 110 // If the list to sort contains one or less element, the list is already sorted. 111 if (right <= left) return; 112 113 // If the size of the list is under the threshold, sequential version is used. 114 if (right - left < threshold) 115 Quicksort(arr, left, right); 116 117 else 118 { 119 // Partitioning our list and getting a pivot. 120 var pivot = Partition(arr, left, right); 121 122 // Sorting the left and right of the pivot in parallel 123 Parallel.Invoke( 124 () => QuicksortParallel(arr, left, pivot - 1), 125 () => QuicksortParallel(arr, pivot + 1, right)); 126 } 127 } 128 }


浙公网安备 33010602011771号