快速排序的基本思想:
通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。
算法描述:
- 选择基准
- 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。
- 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。
代码实现
import java.util.Scanner;
public class QuickSort {
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
int n=Integer.parseInt(scanner.nextLine());
String str=scanner.nextLine();
String[]strs=str.split(" ");
int[]arr=new int[n];
for (int i=0;i<n;i++){
arr[i]=Integer.parseInt(strs[i]);
}
quicksort(arr,0,arr.length-1);
for (int i=0;i<n;i++){
System.out.print(arr[i]+" ");
}
}
static void quicksort(int []arr,int start,int end){
//当开始索引大于等于结束索引的时候不用排了
//必须是大于等于,因为low+1有可能大于end
if (start>=end)return;
//以左边为基准
int temp=arr[start];
int low=start;
int high=end;
//相遇就停下来
while (low<high){
//先从右边开始找,找到比基准小的数或者相遇停下来,至于为什么先从右边,后面解释
while (low<high&&arr[high]>=temp)
high--;
//从左边找,找到比基准大的数或者相遇停下来
while (low<high&&arr[low]<=temp)
low++;
//交换小的跟大的
swap(arr,low,high);
}
//low跟high相遇的时候,交换相遇的值跟基准值
swap(arr,start,low);
//排序两个子数列
quicksort(arr,start,low-1);
quicksort(arr,low+1,end);
}
//交换位置
static void swap(int []arr,int i,int j){
int temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
}
下面解释一下为什么先从右边开始
因为我们是从小到大排,从右边开始找所有比基准大的,遇到小的停下来,左边都是比基准小的,遇到大的停下来如果先从左边开始找,可能只找到一个比基准大的,而从右边找的因为相遇就停下来了,那么交换的基准与相遇点就是把一个大的交换到了开头,这显然不对。而先从左边开始,必然遇到比基准小的,或者相遇,相遇的要么比基准小,要么等于基准。