1. // --------------------------------------------------------------------------------------------------------------------  
  2. // 
  3. //  
  4. // Respect the work.  
  5. //  
  6. // </copyright>  
  7. // <summary>  
  8. //  
  9. // The quick sort.  
  10. //  
  11. // 高速排序(QuickSort)是对冒泡排序的一种改进。它的基本思想是:通过一趟排序将要排序的数据切割成独立的两部分,当中一部分的全部数据都比另外一部分的全部数据要小,然后再按此方法对这两部分数据分别进行高速排序。整个排序过程能够递归进行,以此达到整个数据变成有序序列。  
  12. //  
  13. // 设要排序的数组是a[0]...a[N-1],首先随意选取一个数据(通常选用数组的首元素)作为重要数据,然后将全部比它小的数都放到它的前面,全部比它大的数都放到它的后面,这个过程称为一趟高速排序。

    值得注意的是,高速排序不是一种稳定的排序算法。也就是说,多个同样的值的相对位置或许会在算法结束时产生变动。  

  14. // 一趟高速排序的算法是:  
  15. // 1)设置两个变量i、j,排序開始的时候:i=0,j=N-1。  
  16. // 2)以数组首元素作为重要数据,赋值给pivot,即pivot=a[0]。  
  17. // 3)从j開始向前搜索,即由后開始向前搜索(j--),找到第一个小于pivot的值a[j],将a[j]赋值给a[i];  
  18. // 4)从i開始向后搜索,即由前開始向后搜索(i++),找到第一个大于pivot的值a[i],将a[i]赋值给a[j];  
  19. // 5)反复第3、4步,直到i==j;(在3、4步中。若没找到符合条件的值,即3中a[j]不小于pivot,4中a[i]不大于pivot的时候改变j、i的值,使得j=j-1,i=i+1,直至找到为止。

    若找到符合条件的值,进行替换的时候i、j指针位置不变。

      

  20. //  
  21. // 高速排序的平均时间复杂度是:O(nlog<sub>2</sub>n)。  
  22. //  
  23. // </summary>  
  24. // --------------------------------------------------------------------------------------------------------------------  
  25.   
  26. namespace CSharpLearning  
  27. {  
  28.     using System;  
  29.   
  30.     /// <summary>  
  31.     /// The program.  
  32.     /// </summary>  
  33.     public static class Program  
  34.     {  
  35.         /// <summary>  
  36.         /// The main.  
  37.         /// </summary>  
  38.         public static void Main()  
  39.         {  
  40.             int[] a = { 101, 93, 856, 7, 62, 15, 84, 3, 298, 1256 };  
  41.             Console.WriteLine("Before Quick Sort:");  
  42.             foreach (int i in a)  
  43.             {  
  44.                 Console.Write(i + " ");  
  45.             }  
  46.   
  47.             Console.WriteLine("\r\n");  
  48.             Console.WriteLine("In Quick Sort:");  
  49.             QuickSort(a, 0, 9);  
  50.             Console.WriteLine("\r\nAfter Quick Sort:");  
  51.             foreach (int i in a)  
  52.             {  
  53.                 Console.Write(i + " ");  
  54.             }  
  55.   
  56.             Console.WriteLine(string.Empty);  
  57.         }  
  58.   
  59.         /// <summary>  
  60.         /// 高速排序。  
  61.         /// </summary>  
  62.         /// <param name="a">  
  63.         /// 待排序数组。  
  64.         /// </param>  
  65.         /// <param name="low">  
  66.         /// 待排序数组的排序起始位置。  
  67.         /// </param>  
  68.         /// <param name="high">  
  69.         /// 待排序数组的排序终止位置。  
  70.         /// </param>  
  71.         private static void QuickSort(int[] a, int low, int high)  
  72.         {  
  73.             if (low >= high)  
  74.             {  
  75.                 return;  
  76.             }  
  77.   
  78.             int pivot = QuickSortOnce(a, low, high);  
  79.   
  80.             // 输出每一次排序。  
  81.             foreach (int i in a)  
  82.             {  
  83.                 Console.Write(i + " ");  
  84.             }  
  85.   
  86.             Console.WriteLine(string.Empty);  
  87.   
  88.             // 对枢轴的左端进行排序。

      

  89.             QuickSort(a, low, pivot - 1);  
  90.   
  91.             // 对枢轴的右端进行排序。  
  92.             QuickSort(a, pivot + 1, high);  
  93.         }  
  94.   
  95.         /// <summary>  
  96.         /// 一趟高速排序。

      

  97.         /// </summary>  
  98.         /// <param name="a">  
  99.         /// 待排序数组。

      

  100.         /// </param>  
  101.         /// <param name="low">  
  102.         /// 待排序数组的排序起始位置。  
  103.         /// </param>  
  104.         /// <param name="high">  
  105.         /// 待排序数组的排序终止位置。  
  106.         /// </param>  
  107.         /// <returns>  
  108.         /// 返回枢轴的位置。  
  109.         /// </returns>  
  110.         private static int QuickSortOnce(int[] a, int low, int high)  
  111.         {  
  112.             // 将首元素作为枢轴。  
  113.             int pivot = a[low];  
  114.             int i = low, j = high;  
  115.   
  116.             while (i < j)  
  117.             {  
  118.                 // 从右到左,寻找首个小于pivot的元素。

      

  119.                 while (a[j] >= pivot && i < j)  
  120.                 {  
  121.                     j--;  
  122.                 }  
  123.   
  124.                 // 运行到此,j一定指向从右端起首个小于或等于pivot的元素。运行替换。  
  125.                 a[i] = a[j];  
  126.   
  127.                 // 从左到右,寻找首个大于pivot的元素。

      

  128.                 while (a[i] <= pivot && i < j)  
  129.                 {  
  130.                     i++;  
  131.                 }  
  132.   
  133.                 // 运行到此。i一定指向从左端起首个大于或等于pivot的元素。

    运行替换。

      

  134.                 a[j] = a[i];  
  135.             }  
  136.   
  137.             // 退出while循环,运行至此,必然是i==j的情况。i(或j)指向的即是枢轴的位置,定位该趟排序的枢轴并将该位置返回。  
  138.             a[i] = pivot;  
  139.             return i;  
  140.         }  
  141.     }  
  142. }  
  143.   
  144. // Output:  
  145. /* 
  146. Before Quick Sort: 
  147. 101 93 856 7 62 15 84 3 298 1256 
  148.  
  149. In Quick Sort: 
  150. 3 93 84 7 62 15 101 856 298 1256 
  151. 3 93 84 7 62 15 101 856 298 1256 
  152. 3 15 84 7 62 93 101 856 298 1256 
  153. 3 7 15 84 62 93 101 856 298 1256 
  154. 3 7 15 62 84 93 101 856 298 1256 
  155. 3 7 15 62 84 93 101 298 856 1256 
  156.  
  157. After Quick Sort: 
  158. 3 7 15 62 84 93 101 298 856 1256 
  159. */