基本思路:通过一趟排序,将要排序的数据分割成独立的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     }