快速排序

  快速排序也是分治算法,先选择一个元素Pivot作为主元,将此主元放到数组的最右边,然后从最左边开始扫描,当扫描到一个元素比Pivot小,则将此元素往左边置换。一次扫描过后,会把整个数组分成两个部分,比Pivot大的元素在右边,比Pivot小的元素在左边。然后递归这个过程

  考虑以下数组:

13

6

15

2

11

10

 

  这里直接选择最右边的元素10作为主元Pivot,从13开始扫描,比Pivot大,直接跳过,然后扫描到6,比Pivot小则把6跟最左边元素交换位置,结束如下:

6

13

15

2

11

10


  继续往右扫描,扫到15,比Pivot要大,跳过,然后扫到了2,比Pivot小,则把2也往左边置换,注意之前已经置换过6了,直接置换到6后面的位置,结果如下:

6

2

15

13

11

10


  扫描到11后,已经没有元素可以继续的了,那么这个时候,将10置换到前面置换了的最后一个元素的后面,结果如下:

6

2

10

13

11

15


  这样一来,就将整个数组分成了三个部分,比Pivot大的在Pivot右边(绿色),比Pivot小的在左边(黄色),
然后继续递归对左右两部分执行上面的操作,最后的结果就一定是排好序的了。

 1 void QuickSort(int* pArr, int l, int r) {
 2     if (r > l) {
 3         int n = _Partition(pArr, l, r);
 4         QuickSort(pArr, l, n - 1);
 5         QuickSort(pArr, n + 1, r);
 6     }
 7 }
 8 
 9 int _Partition(int* pArr, int l, int r) {
10     //比pivot小的数,都全部移到左边,如果刚好pivot是最大的元素,则所有元素都将移动一遍
11     //此种分区法,比Pivot小的元素往左移,这没问题,而比Pivot大的元素,则会被反复的往前面移动,造成可能要移动多次,这种单向处理是此算法较慢的主要原因
12     int pivot = pArr[r];
13     int j = l - 1;
14     for (int i = l; i < r; ++i) {
15         if (pArr[i] < pivot) {
16             ++j;
17             Swap(pArr + i, pArr + j);
18         }
19     }
20     Swap(pArr + (++j), pArr + r);
21     return j;
22 }
23 
24 void Swap(int* num1, int* num2) {
25     int temp = *num1;
26     *num1 = *num2;
27     *num2 = temp;
28 }

  第20行就是把Pivot置换过去,至此整个待排序序列被分成三个部分,小于Kye,等于Key,大于Key的了

  快速排序的时间复杂度为O(NlogN)

posted on 2018-04-07 11:38  凄夜  阅读(174)  评论(0编辑  收藏  举报

导航