基本思想:
选择一个基准元素,比如选择最后一个元素,通过一趟扫描,将待排序列分成两部分,一部分比基准元素小,一部分大于等于基准元素,此时基准元素在其排好序后的正确位置,又称为轴位置,此位置的元素确定后不再参与排序,然后再用同样的方法递归地排序划分的两部分。
分析:
快速排序是不稳定的排序。
快速排序的时间复杂度为O(nlogn)。
当n较大时使用快排比较好,当序列基本有序时用快排反而不好。
代码实现:
递归实现
int[] quickSort(int arr[],int left,int right){
if(Objects.isNull(arr)){
return arr;
}
if(left<right){
//获取排序轴索引,该索引本身不再参与排序
int middle=findMiddlePartion(arr,left,right);
//从左到中排序
quickSort(arr,left,middle-1);
//从中到右排序
quickSort(arr,middle+1,right);
}
return arr;
}
//该算法实现 绝对优于多层while循环的那种实现
int findMiddlePartion(int arr[],int left,int right){
//以最右的数 为基准元素
int baseMiddleNum=arr[right];
//从最左位开始 记录替换索引
int low=left-1;
//遍历中不包含基准元素
for(int i=left;i<right;i++){
//比基准元素小的 从最左位开始放
if(arr[i]<=baseMiddleNum){
//记录最左位已替换的索引
low++;
if(i==low){
continue;
}
//交换
int temp=arr[low];
arr[low]=arr[i];
arr[i]=temp;
}
}
//基准元素放到轴位置
if((low)+1!=right){
int temp=arr[low+1];
arr[low+1]=baseMiddleNum;
arr[right]=temp;
}
//返回下一次遍历位置 以该位置为轴分别向两侧排序
return low+1;
}
非递归实现:
int[] quickSortNonRecursive(int arr[],int left,int right){
if(Objects.isNull(arr)){
return arr;
}
//通过栈实现
Stack<Integer> stack=new Stack<>();
stack.push(left);
stack.push(right);
while(!stack.isEmpty()){
int rightNew=stack.peek();
stack.pop();
int leftNew=stack.peek();
stack.pop();
//获取排序轴索引,该索引本身不再参与排序
int middle=findMiddlePartion(arr,leftNew,rightNew);
if(middle-1>leftNew){
stack.push(left);
stack.push(middle-1);
}
if(middle+1<rightNew){
stack.push(middle+1);
stack.push(rightNew);
}
}
return arr;
}