我们先来了解一下什么是指针交换法的快速排序。
在一个数组里任意选择一个数作为支点,方便起见选取第一个数为支点。把所有比支点小的数都放在支点的左侧,而所有比支点大的数都放在支点的右侧,这样一个数组就分成了三个部分:
【比支点小的部分】 | 【支点】 | 【比支点大的部分】 |
---|
然后我们继续对支点两边凌乱的数组调用该方法,直到数组只有一个数,即支点两侧无数为止。
你可能会说,我知道这样可我还是不会敲代码
别急咱一步一步慢慢来,我们先分析单次的执行
- 定义一个支点pivot保存着第一个元素的值
- 定义一个索引i指向第一个数往后遍历找到比支点大的值
- 定义一个索引j指向最后一个数往前遍历找到比支点小的值
- 重复步骤2 3,直到i,j相遇
图示如下:
i开始找比pivot大的数,就开始找比pivot小的数,找到后交换两数
下来就出了一点问题,我们是先移动i呢,还是先移动j呢。其实很简单因为最后要使pivot与arr[i]进行交换所以那就移动j,i保持不动。之后我们就得到了如下结果
这个例子可能对先移动谁不够鲜明,我们试想一下下面这种情况。
升序排列的数组j连一次移动的机会都没有,便会得到如下结果:
然后1跟6再交换一下emmm很显然做不到pivot的左边比pivot小
图也哔哔了半天了,上代码吧
public static void quickSort(int[] arr,int left,int right){
int i = left;//向右索引
int j = right;//向左索引
int temp;
if(right<left){return;}
int pivot = arr[left];//选取第一个数为支点
while(i<j){
while(i<j&&arr[j]>=pivot){//获取比支点小的元素下标
j--;
}
while(i<j&&arr[i]<=pivot){//获取比支点大的元素下标
i++;
}
//把两个数交换
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
arr[left] = arr[i];
arr[i] = pivot;
//现在数组被分为了三个部分
// 【比支点小的部分】【支点arr[i]】【比支点大的部分】
quickSort(arr,left,i-1);//分别对两侧进行同样操作即可
quickSort(arr,i+1,right);
}
}
然后我们发现这个参数实在好长啊,我们要给arr排序还得这么写
quickSort(arr,0,arr.length-1)。这种重复的无意义的工作就交给计算机去做吧,程序员该做的就应该是偷懒。我们把它再封装到一个方法里。
public static void quickSort(int arr[]){
quickSort(arr,0,arr.length-1);
}
这样看起来是不是就清爽了很多~