基本介绍
快速排序是对冒泡排序的一种改进,基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一个部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列;
图解
流程分析
1.原始数组以11为基准进行分解,11左边的数据都比11小,而11右边的数据都比11大;
2.然后左边的数据又以5为基准进行分割,比5小的在左边,比5大的在右边(向左递归),以次类推直到全部完成;
3.右边的数据以21为基准进行分割,比21小的在左边,比21大的在右边(向右递归),以次类推直到全部完成;
4.最终即得到了我们的有序序列。
代码实现
public static void main(String[] args) {
/* int arr[] = {1,41,78,-1,0,99,37};*/
int arr[] = new int [50000];
for (int i = 0; i < arr.length; i++) {
arr[i]=BubbleSort.getRandom();
}
System.out.println("50000条随机数快速排序结果如下");
System.out.println();
long beginTime = System.currentTimeMillis();
getQuickSort(arr,0,arr.length-1);
long endTime = System.currentTimeMillis();
System.out.println("总共耗时"+(endTime-beginTime)+"毫秒");
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]+" ");
}
}
/**
*
* @Author: Strine
* 快速排序算法
* */
public static void getQuickSort(int arr[],int left,int right){
int l = left; // 左下标
int r = right; //右下标
int mid = arr[(right+left)/2]; //中间值
int oldVal = 0; //临时变量
while (l<r){
//进行分割操作
while (arr[l]<mid){
l++;
}
while (arr[r]>mid){
r--;
}
//通过上面两个循环找到一个小于等于中间值的元素以及一个大于等于中间值的元素
if (l>=r){
//如果循环完了发现者两个找到的都是中间值(说明分割完成了,直接退出循环)
break;
}
//否则则进行交换
oldVal=arr[l];
arr[l]=arr[r];
arr[r]=oldVal;
//如果交换完了发现左边的元素等于mid那么就让r往前移动一位
if (arr[l]==mid){
r--;
}
//如果发现右边的元素等于mid那么就让l往前移动一位;
if (arr[r]==mid){
l++;
}
}
//防止栈溢出
if (l==r){
l++;
r--;
}
//向左进行递归
if (left<r){
getQuickSort(arr,left,r);
}
if (right>l){
getQuickSort(arr,l,right);
}
}
代码简述
1.循环分割,在while循环中,以中间值为轴,每一次循环在左边找出一个小于等于中间值的数,在右边找出一个大于等于中间值的数;
2.如果左右下标都循环到了中轴的位置,则说明已经完成了分割,则退出循环;
3.否则则交换两个数的位置,如果交换完之后,其中左右两个数有一个是等于中间值,那么为了防止死循环,则将其对立的下标(交换前的下标)进行前移或者后移;
4.在整个while循环完成之后,说明分割完成;
5.退出while循环后的左右下标就会相等(都为中轴的下标),因此我们需要防止栈溢出,就必须让左下标后移一位,让右下标前移一位(让原来数组的右/左下标变为左侧数组的右/左下标),否则就会出现下面这种情况:
6.最后则将原来位置的左下标(0),和分割完成后的右下标(左侧数组的最后一个位置,也就是中轴前的下标),传入当前方法,向左递归;
7.同样的再进行向右递归,最终排序完成
效果展示
性能测试
同样的我们使用50000条随机数数组来进行耗时统计,发现快速排序非常非常快:
甚至我们使用50000000条数据进行耗时统计,发现它的速度依旧不会太慢: