快速排序(QuickSort)
选择序列中的某个元素,将序列一分为2,小于该元素的放在前面,大于该元素的放在后面,相等的随便前后。那么这个元素就是 轴点元素(pivot)
快速排序的流程:
- 选择一个元素作为pivot。
- 用pivot将序列一分为2。
- 重复1~2直到不能再分割,即子序列元素个数为1(也可以认为此时的子序列中的元素也是自己的pivot)。
下图中带颜色的都是轴点元素
快速排序算法拆分思路:
- 如果轴点元素是取第一个,那么从数组的最后一位取值,找到第一个比轴点元素小的元素,将高指针位置的元素放在低指针的位置;low指针++
- 从低指针位置开始找一个比轴点元素大的元素,将低指针位置上的元素放在高指针的位置;high指针++
- 重复上面两个操作直到高低指针位置重合,则将轴点元素放在该位置,自此第一轮比较结束
- 重复上面三个步骤,直至数据排序完成
核心算法如下:
//快速排序 31 21 59 68 12 40
// x=31
public static void quickSort(int[] array,int begin,int end){
if(end-begin<=0) return;
int x=array[begin];
int low=begin;//0
int high=end;//5
//由于会从两头取数据,需要一个方向
boolean direction=true;
L1: //设置一个标示位,当方向发生改变时,跳出到当前该位置
while(low<high){
if(direction){//从右往左找
for(int i=high;i>low;i--){
if(array[i]<=x){
array[low++]=array[i];
high=i;
direction=!direction;
continue L1;
}
}
high=low;//如果上面的if从未进入,让两个指针重合
}else{
for(int i=low;i<high;i++){
if(array[i]>=x){
array[high--]=array[i];
low=i;
direction=!direction;
continue L1;
}
}
low=high;
}
}
//把最后找到的值 放入中间位置
array[low]=x;
//开始完成左右两边的操作
quickSort(array,begin,low-1);
quickSort(array,low+1,end);
}
项目运行;
@Test
public void addition_isCorrect() throws Exception {
int[] array=new int[]{6,11,8,2,9,4,1,5,7,10,3};
for (int i : array) {
System.out.print(i+" ");
}
System.out.println("");
quickSort(array,0,array.length-1);
for (int i : array) {
System.out.print(i+" ");
}
}
时间复杂度: 如果轴点两边数据比较均匀,那么时间复杂度是O(NlogN)。
如果轴点两边数据极度不均匀,那么最坏情况是O(N²)