快速排序学习

175 阅读3分钟

快速排序(Quick Sort)

​ 在平均状况下,排序 n 个项目要 Ο(nlogn) 次比较。在最坏状况下则需要 Ο(n2) 次比较,但这种状况并不常见。事实上,快速排序通常明显比其他 Ο(nlogn) 算法更快,因为它的内部循环(inner loop)可以在大部分的架构上很有效率地被实现出来。

​ 快速排序使用分治法(Divide and conquer)策略来把一个串行(list)分为两个子串行(sub-lists)。

​ 快速排序又是一种分而治之思想在排序算法上的典型应用。本质上来看,快速排序应该算是在冒泡排序基础上的递归分治法。

算法描述
  1. 从数列中挑出一个元素,称为 “基准”(pivot);
  2. 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;
  3. 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。
例子
数组: 72  6  57  88  60  42  83  73  48  85
pivot = 72
i - 72
j - 85 向左读取
从j开始向左读取遍历,找到小于等于pivot替换i
第一次: 48  6  57  88  60  42  83  73  48  85
i - 48
j - 48
从i开始向右读取遍历,找到大于等于pivot替换j
第二次: 48  6  57  88  60  42  83  73  88  85
重复以上两次
第三次: 48  6  57  42  60  42  83  73  88  85
第四次: 48  6  57  42  60  72  83  73  88  85
按照pivot = 72分为两个分区按照上面的步骤进行
最终 6  42  48  57  60  72  73  83  85  88
结束
算法复杂度

空间复杂度:

O(nlog2n)O(nlog_2n)

时间复杂度:

O(n2)最坏结果O(n²) 最坏结果
O(nlog2n)平均结果O(nlog_2n) 平均结果
O(nlog2n)最好结果O(nlog_2n) 最好结果

排序不稳定,原来相等的两个参数排在前面的可能排在后面。

代码实现
 public static void quick_sort(int[] s, int l, int r) {
   System.out.println(Arrays.toString(s));
   if (l < r){
     //Swap(s[l], s[(l + r) / 2]); //将中间的这个数和第一个数交换 参见注1
     int i = l, j = r, x = s[l];
     while (i < j){
       while(i < j && s[j] >= x) // 从右向左找第一个小于x的数
         j--;
       if(i < j)
         s[i++] = s[j]; 
       while(i < j && s[i] < x) // 从左向右找第一个大于等于x的数
         i++;
       if(i < j)
         s[j--] = s[i];
     }
     s[i] = x;
     quick_sort(s, l, i - 1); // 递归调用
     quick_sort(s, i + 1, r);
   }
 }

运行结果

输入数组:int[] arr = {72,6,57,88,60,42,83,73,48,85};
[72, 6, 57, 88, 60, 42, 83, 73, 48, 85]
[48, 6, 57, 42, 60, 72, 83, 73, 88, 85]
[42, 6, 48, 57, 60, 72, 83, 73, 88, 85]
[6, 42, 48, 57, 60, 72, 83, 73, 88, 85]
[6, 42, 48, 57, 60, 72, 83, 73, 88, 85]
[6, 42, 48, 57, 60, 72, 83, 73, 88, 85]
[6, 42, 48, 57, 60, 72, 83, 73, 88, 85]
[6, 42, 48, 57, 60, 72, 83, 73, 88, 85]
[6, 42, 48, 57, 60, 72, 83, 73, 88, 85]
[6, 42, 48, 57, 60, 72, 73, 83, 88, 85]
[6, 42, 48, 57, 60, 72, 73, 83, 88, 85]
[6, 42, 48, 57, 60, 72, 73, 83, 85, 88]
[6, 42, 48, 57, 60, 72, 73, 83, 85, 88]

但是按照上面的步骤,这时候我们可以看到和演算结果一致。

快速排序还有很多改进版本,如随机选择基准数,区间内数据较少时直接用另的方法排序以减小递归深度。有时间我这再进行统计学习。