快速排序的基本思想是:设立一个基准值pivot(以左边第一个元素为例),以及两个指针low和high,low指针从左往右移动,high指针从右往左移动;在经历一轮排序后使得pivot左边的元素都比它小,右边的元素都比他大。
int pivot=a[left];
//low从左边往右,high从右边往左,二者相遇时退出循环
//给low和high附初始值left和right
int low=left;
int high=right;
1.如何让左指针右移的同时让右指针左移
若high指向的值大于枢轴元素pivot,则继续向左移;若low指向的值小于枢轴元素pivot,则继续右移,直到high向左遍历时指向的值小于pivot,跳转到low开始向右遍历
while(low<high) {
while(low<high&&a[high]>=pivot){
high--;
}
while(low<high&&a[low]<=pivot){
low++;
}
//若low的值小于pivot,则继续向右遍历;若high的值大于pivot,则继续向左遍历
//只有high向右遍历时指向的值小于pivot,跳转到low开始向右遍历
if(low<high) {
int tempt=a[low];
a[low]=a[high];
a[high]=tempt;
}
}
出现low指向的值大于pivot时,交换low和high的值,并再一次跳转到high向左遍历。
2.让low和high相遇时指向的数组值跟数轴元素交换
因为是high先开始往左移,所以二者相遇时指向的数组值一定是小于枢轴元素的
if (low!=left) {
int t = a[low];
a[low] = pivot;
a[left] = t;//这里交换的是位置,而不能给变量赋值
}
3.最后进行递归
经过上面的步骤后,用pivot将数组分成两部分,pivot左侧的元素都比它小,pivot右侧的元素都比它大,在对新得到的两个数组进行递归排序
quiksort(a,left,low-1);
quiksort(a,low+1,right);
4.完整代码
public static void main(String[] args) {
int[] c=new int []{80,3,698,14,78,32,100,5,20,99,54};
quiksort(c,0,c.length-1);
System.out.println(Arrays.toString(c));
}
/*public static void quiksort(int[] a){
quiksort(a,0,a.length-1);
}*/
public static void quiksort(int[] a,int left,int right) {
if(left>=right) {
return;
}
int pivot=a[left];
//low从左边往右,high从右边往左,二者相遇时退出循环
//给low和high附初始值left和right
int low=left;
int high=right;
while(low<high) {
while(low<high&&a[high]>=pivot){
high--;
}
while(low<high&&a[low]<=pivot){
low++;
}
//若low的值小于pivot,则继续向右遍历;若high的值大于pivot,则继续向左遍历
//只有high向右遍历时指向的值小于pivot,跳转到low开始向右遍历
if(low<high) {
int tempt=a[low];
a[low]=a[high];
a[high]=tempt;
}
}
//当不满足low<high的条件时,跳出while循环
//此时肯定是low=high的,low和high指向同一个值,且这个值一定小于pivot
//因为是high指针先动的,想想就知道了
//为什么跟a[left]交换而不跟pivot交换??二者的值是一样的
if (low!=left) {
int t = a[low];
a[low] = pivot;
a[left] = t;//这里交换的是位置,而不能给变量赋值
}
//one last step
quiksort(a,left,low-1);
quiksort(a,low+1,right);
}