C# 编写一个简单的快速排序例程
这个程序用随机数字组成的同一序列填充一个大型数组,然后使用快速排序例程对这些数字进行排序,并报告所用时间。
图 3 快速排序
- using System;
- using System.Threading;
- using System.Threading.Tasks;
- using System.Diagnostics;
- namespace ParallelSort {
- class Program {
- // For small arrays, use Insertion Sort
- private static void InsertionSort(
- int[] list, int left, int right) {
- for (int i = left; i < right; i++) {
- int temp = list[i];
- int j = i;
- while ((j > 0) && (list[j - 1] > temp)) {
- list[j] = list[j - 1];
- j = j - 1;
- }
- list[j] = temp;
- }
- }
- private static int Partition(
- int[] array, int i, int j) {
- int pivot = array[i];
- while (i < j) {
- while (array[j] >= pivot && i < j) {
- j--;
- }
- if (i < j) {
- array[i++] = array[j];
- }
- while (array[i] <= pivot && i < j) {
- i++;
- }
- if (i < j) {
- array[j--] = array[i];
- }
- }
- array[i] = pivot;
- return i;
- }
- static void QuickSort(
- int[] array, int left, int right) {
- // Single or 0 elements are already sorted
- if (left >= right)
- return;
- // For small arrays, use a faster serial routine
- if ( right-left <= 32) {
- InsertionSort(array, left, right);
- return;
- }
- // Select a pivot, then quicksort each sub-array
- int pivot = Partition(array, left, right);
- QuickSort(array, left, pivot - 1);
- QuickSort(array, pivot + 1, right);
- }
- static void Main(string[] args) {
- const int ArraySize = 50000000;
- for (int iters = 0; iters < 1; iters++) {
- int[] array;
- Stopwatch stopwatch;
- array = new int[ArraySize];
- Random random1 = new Random(5);
- for (int i = 0; i < array.Length; ++i) {
- array[i] = random1.Next();
- }
- stopwatch = Stopwatch.StartNew();
- QuickSort(array, 0, array.Length - 1);
- stopwatch.Stop();
- // Verify it is sorted
- for (int i = 1; i < array.Length; ++i)
- if (array[i - 1] > array[i - 1])
- throw new ApplicationException("Sort Failed");
- Console.WriteLine("Serialt: {0} ms",
- stopwatch.ElapsedMilliseconds);
- }
- }
- }
- }
如果看一下 QuicSort 函数,您会发现它是以递归方式将数组一分为二,直到达到某个阈值,这时便不再进行细分,而开始对列表进行排序。 如果将这种方式变为并行版本,您只需要更改以下两行即可:
- QuickSort( array, lo, pivot - 1);
- QuickSort( array, pivot + 1, hi);
以下是并行版本:
- Parallel.Invoke(
- delegate { QuickSort(array, left, pivot - 1); },
- delegate { QuickSort(array, pivot + 1, right); }
- );
Parallel.Invoke 接口是 .NET 任务并行库中 Systems.Threading.Tasks 命名空间的组成部分。 使用该接口,您可以指定一个以异步方式运行的函数。 在本例中,我通过它将每个排序函数放在单独的线程上运行。
尽管有更高效的方法(只生成一个新线程并使用现有的执行线程对其他子列表进行排序),但我希望保持对称性并说明将串行程序转换为并行程序是多么简单。
posted on 2011-11-18 18:24 thankchunzi 阅读(501) 评论(0) 编辑 收藏 举报