目录
快速排序概念
快速排序是对冒泡排序的一种改进。基本思想是:通过一趟排序将数据分成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
(基准值的选择有很多,比如第一个数,最后一个数,或者数组的中间值)
基准值就是Pivot中心轴,建议选择第一个数为中心轴,这样编程更简单,基本思想如下
代码实现(中值为pivot)(不推荐)
import java.util.Arrays;
public class QuickSort {
public static void main(String[] args) {
int[] arr = {-9,78,0,0,23,23,-67,50};
quickSort(arr,0, arr.length-1);
System.out.println("arr="+ Arrays.toString(arr));
}
public static void quickSort(int[] arr, int left, int right){
int l = left; //左下标
int r = right; //右下标
int pivot = arr[(left+right)/2]; //中值
int temp;
//让比pivot小的值放到左边,比pivot大的值放到右边
while(l<r){
// 在pivot的左边一直找,找到大于等于pivot的值才退出
while(arr[l]<pivot){
l += 1 ;
}
// 在pivot的右边一直找,找到小于等于pivot的值才退出
while(arr[r]>pivot){
r -= 1 ;
}
// l最大等于pivot的index,r最小等于pivot的index
// 如果满足l>=r说明pivot的两边已经找完了
if(l>=r){
break;
}
// pivot两边的需要交换的值 交换
temp = arr[l];
arr[l] = arr[r];
arr[r] = temp;
//如果交换完,发现这个arr[l] == pivot值,避免死循环
if(arr[l] == pivot){
r -= 1 ;
}
//如果交换完,发现这个arr[r] == pivot值,避免死循环
if(arr[r] == pivot){
l += 1 ;
}
}
//避免栈溢出,如果l=r,则不会进入while循环,l和r的值就不会改变,会一直递归下去
if(l==r){
l += 1;
r -= 1;
}
// 向左递归
if (left<r){
quickSort(arr, left, r);
}
// 向右递归
if (right>l){
quickSort(arr, l, right);
}
}
}
运行结果:
代码实现(第一个值为pivot)
public static void quickSort2(int[] arr, int left, int right){
//判断合法性
if (left >= right){
return;
}
int l = left;
int r = right;
int pivot = arr[left];
int temp;
while(l!=r){
//第一个数为pivot时,必须先从右开始找,否则会错
//直到找到比pivot小的值
while(arr[r]>=pivot && l<r){
r--;
}
//直到找到比pivot大的值
while(arr[l]<=pivot && l<r){
l++;
}
temp = arr[l];
arr[l] = arr[r];
arr[r] = temp;
}
//当l和r相等时,就可以将pivot值拿过来放到l和r相等的地方,即中间,实现了左边都小于pivot,右边都大于pivot
arr[left] = arr[l];
arr[l] = pivot;
quickSort2(arr,left,l-1);
quickSort2(arr,r+1,right);
}
代码实现(最后一个值为pivot)
public static void quickSort3(int[] arr, int left, int right){
//判断合法性
if (left >= right){
return;
}
int l = left;
int r = right;
int pivot = arr[right];
int temp;
while(l!=r){
//最后一个数为pivot,则必须先从左开始找,否则会错
//直到找到比pivot大的值
while(arr[l]<=pivot && l<r){
l++;
}
//直到找到比pivot小的值
while(arr[r]>=pivot && l<r){
r--;
}
temp = arr[l];
arr[l] = arr[r];
arr[r] = temp;
}
//当l和r相等时,就可以将pivot值拿过来放到l和r相等的地方,即中间,实现了左边都小于pivot,右边都大于pivot
arr[right] = arr[l];
arr[l] = pivot;
quickSort3(arr,left,l-1);
quickSort3(arr,r+1,right);
}
(1)选中值为pivot要考虑过多的特殊情况,所以推荐把第一个值为pivot
(2)第一个数为pivot时,必须先从右开始找,否则会错;同理,最后一个数为pivot,则必须先从左开始找,否则会错