第一种方法:(从数组右边开始)
1.选择一个比较值c,以数组的第一个为例。
2.从右边开始查找比c小的值,再从左边开始查找比c大的值,进行互换。
3.当左边和右边同时指向一个值v(比c小,因为是从右边开始递减的),会退出当前循环。
4.交换c和v的值,返回v所在的地址。
5.递归,以此类推
public class QuickSort {
public static int[] quickSort(int[] a,int first,int last){
if(first<last){ //至少两个位置
int pivotIndex=partition(a,first,last); //定义pivotIndex中间位置。partition是检索这个方法
quickSort(a,first,pivotIndex-1); //排序左半边
quickSort(a,pivotIndex+1,last); //排序右半边
}
return a;
}
public static int partition(int[] a,int left,int right){//对数组A下标从first到last中选一个主元,确定其位置,左边小于,右边大于。
int pivot=a[left];//先定义区间数组第一个元素为主元
int i=left; //定义最低的索引low是first+1。比主元大一位
int j=right; //定义最高的索引high是last
while(i!=j){ //当low小于high的位置时,执行以下循环
while(a[j]>pivot&&i<j){//当high的索引上的值比主元大时,且索引大于low时
j--; //寻找比主元小的值的位置索引
}
while(a[i]<=pivot&&i<j){//当low的索引上的值比主元小时,索引小于high时
i++; //寻找比主元大的值的位置索引。
}
if(i<j){ //交换low和high的值
int t=a[i];
a[i]=a[j];
a[j]=t;
}
}
a[left]=a[j];
a[j]=pivot;
return j;
}
public static void main(String[] args) {
int[]a=new int[]{50,10,90,30,70,40,80,60,20};
int [] k=quickSort(a,0,a.length-1);
for(int i=0;i<k.length;i++){
System.out.print(k[i]+" ");
}
}
}
第二种方法:(从数组左边开始数)
public static int partition(int[] a,int left,int right){//对数组A下标从first到last中选一个主元,确定其位置,左边小于,右边大于。
int pivot=a[right];//先定义区间数组第一个元素为主元
int i=left; //定义最低的索引low是first+1。比主元大一位
int j=right; //定义最高的索引high是last
while(i!=j){ //当low小于high的位置时,执行以下循环
while(a[i]<=pivot&&i<j){//当low的索引上的值比主元小时,索引小于high时
i++; //寻找比主元大的值的位置索引。
}
while(a[j]>=pivot&&i<j){//当high的索引上的值比主元大时,且索引大于low时
j--; //寻找比主元小的值的位置索引
}
if(i<j){ //交换low和high的值
int t=a[i];
a[i]=a[j];
a[j]=t;
}
}
a[right]=a[i];
a[i]=pivot;
return i;
}
有同学可能就要问了,为什么第一种方法数组一定要从右边开始呢。
while(arr[j]>=temp&&i<j){
j–;
}
while(arr[i]<=temp&&i<j){
i++;
}
这里两个while的顺序是不能改变的,想一想:
假设对如下进行排序:
如上图,6在左,9在右 我们将6作为基数。
假设从左边开始(与正确程序正好相反)
于是i 就会移动到现在的 数字 7 那个位置停下来,而 j 原来在 数字 9 那个位置 ,因为
while(arr[j]>=temp&&i<j)
于是,j 也会停留在数字7 那个位置,于是问题来了。当你最后交换基数6与7时,不对呀!!。
问题在于当我们先从在边开始时,那么 i 所停留的那个位置肯定是大于基数6的,而在上述例子中,为了满足 i<j 于是 j也停留在7的位置
但最后交换回去的时候,7就到了左边,不行,因为我们原本 交换后数字6在边应该是全部小于6,右边全部大于6.但现在不行了。
于是,我们必须从右边开始,也就是从基数的对面开始。
第三种方法:(基于第一种,从左边开始数的修正算法)