快速排序
- 算法介绍
- 原理分析
- 代码
- 复杂度分析
一、算法介绍
快速排序(Quicksort),是对冒泡排序的一种改进,由C. A. R. Hoare在1960年提出。
二、原理分析
快速排序算法的思想是:分治+排序。
在这里我们先介绍它的整体过程:
1、我们先从数组中选取一个数x(可随机选取)。
2、将数组分为三个区域:<x区域、=x的区域和>x的区域(各个区域内部不要求有序)。
3、找到=x的边界,并对x<区域和>x区域的数分别进行“2”操作(通常采用递归),每次递归确定一个数的位置(若有相等则为相等的一类数)
那第2步是如何进行排序的呢,我们现将这一步命名为partition过程。
假设我们要排序的数组为arr:[3,5,4,0,4,6,7,2],他的左边界为0,右边界为7,index为下标,
less为小于区域右边界,more为大于区域左边界
接下来遍历arr,进行如下条件判断:
①arr[index] == value------------------->index++
②arr[index] < value------------------->arr[index]与arr[less+1]交换,index++,less++
③arr[index] > value------------------->arr[index]与arr[more-1]交换,more- -
具体步骤如下:
此时arr数组分为三部分。
三、代码
public class QuickSort1 {
public static void main(String[] args) {
int[] arr= {6,3,2,1,4,3};
int L=0;
int R=arr.length-1;
QuickSort(arr);
for(int i:arr) {
System.out.print(i+" ");
}
}
//三色国旗问题 默认num=arr最后一个
public static int[] partition(int[] arr,int L,int R) {
if(L>R) {
return new int[] {-1,-1};
}
if(L==R) {
return new int[] {L,R};
}
int less=L-1; //小于区域右边界
int more=R; //大于区域左边界
int index=L;
int value=arr[R];
while(index<more) {
if(arr[index]==value) {
index++;
}else if(arr[index]<value) {
swap(arr, index++, ++less);
}else {
swap(arr, index, --more);
}
}
swap(arr, more, R); //别忘了把num换到
return new int[] {less+1, more};
}
//快排
public static void QuickSort(int[]arr) {
if(arr==null||arr.length<2) {
return;
}
process3(arr, 0, arr.length-1);
}
public static void process3(int[] arr,int L,int R) {
if(L>=R) {
return;
}
int value=arr[R];
swap(arr, L+(int)(Math.random()*(R-L+1)), R); //随机选一个数与最后一个数交换
int[] equalArea=partition(arr, L, R);
process3(arr, L, equalArea[0]-1);
process3(arr, equalArea[1]+1, R);
}
//交换arr[i]和arr[j]
public static void swap(int[] arr,int i,int j) {
int temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
}
四、复杂度分析
1、时间复杂度
每进行一次【划分区间】操作,会递归调用处理一半大小的数列。因此,在递归结束前,我们要作O ( log n ) 次嵌套的调用,即调用树的深度是O(log n)。程序调用的每一层次结构总共全部仅需要O ( n ) 的时间。结果是这个算法仅需使用O ( n log n ) 时间。
2、空间复杂度
算法在进行每一次递归时,需要记住划分点的位置,即它的空间复杂度取决于递归树的高度O(log n)
参考博文:https://blog.csdn.net/weixin_43864567/article/details/113753440