快速排序是由东尼·霍尔所发展的一种排序算法。在平均状况下,排序 n 个项目要 Ο(nlogn) 次比较。在最坏状况下则需要 Ο(n²) 次比较,但这种状况并不常见。事实上,快速排序通常明显比其他 Ο(nlogn) 算法更快,因为它的内部循环(inner loop)可以在大部分的架构上很有效率地被实现出来。快速排序使用分治法(Divide and conquer)策略来把一个串行(list)分为两个子串行(sub-lists)。快速排序又是一种分而治之思想在排序算法上的典型应用。本质上来看,快速排序应该算是在冒泡排序基础上的递归分治法。
快速排序的名字起的是简单粗暴,因为一听到这个名字你就知道它存在的意义,就是快,而且效率高!它是处理大数据最快的排序算法之一了。虽然 Worst Case 的时间复杂度达到了 O(n²),但是人家就是优秀,在大多数情况下都比平均时间复杂度为 O(n logn) 的排序算法表现要更好,可是这是为什么呢,我也不知道。好在我的强迫症又犯了,查了 N 多资料终于在《算法艺术与信息学竞赛》
上找到了满意的答案
快速排序的最坏运行情况是 O(n²),比如说顺序数列的快排。
但它的平摊期望时间是 O(nlogn),且 O(nlogn) 记号中隐含的常数因子很小,
比复杂度稳定等于 O(nlogn) 的归并排序要小很多。
所以,对绝大多数顺序性较弱的随机数列而言,快速排序总是优于归并排序。
1. 算法步骤
- 先从数列中取出一个数作为基准数。
- 分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边。
- 再对左右区间重复第二步,直到各区间只有一个数。
2. 动图演示
代码实现
package com.data.algorithm;
/**
* 排序类型: 快速排序
* 性质:
* */
public class QuickSortDEMO {
public static void main(String[] args) {
int[] ins = {100,2,3,5,1,23,6,78,34};
int[] ins2 = quickSort(ins,0,8);
for(int in: ins2){
System.out.print(in+",");
}
}
/**
* s 待排序数组
* markNum1: 基准数1 取数组的起始位置
* markNum2:基准数2 取数组的结束位置
* 提高基准数数目可以降低遍历深度
* */
public static int[] quickSort(int s[], int rightNum, int leftNum)
{
if (rightNum < leftNum)
{
//右基准变量
int i = rightNum,
//左基准变量
j = leftNum,
//中间变量
temp = s[rightNum];
while (i < j)
{
//从右向左找第一个小于temp的数
while(i < j && s[j] >= temp)
j--;
if(i < j)
s[i++] = s[j];
//从左向右找第一个大于等于temp的数
while(i < j && s[i] < temp)
i++;
if(i < j)
s[j--] = s[i];
}
s[i] = temp;
quickSort(s, rightNum, i - 1); // 递归调用
quickSort(s, i + 1, leftNum);
}
return s;
}
}
本代码案例是2个基数的,多基数实现与其类似有兴趣的可以自己实现。基数适当增加可以降低遍历深度提高排序效率。