快速排序又被称为分割交换排序,是目前公认最佳的排序方法。它的原理和冒泡排序一样都是用交换的方式,不过它会现在数据中找到一个虚拟的中间值作为基准数,把小于这个基准数的数据放到它的左边,大于这个基准数的数据放到它的右边,再以递归的方式处理这个基准数左右两边的数据,直到完成为止。
假设我们有一组数56,18,6,3,97,66,8,26,88,30,99,93
第一轮,我们将56视为基准数
将大于它的数据放到它的右边,小于它的数据放到它的左边
再将最左侧的8视为基准数,将大于它的数据放到它的右边,小于它的数据放到它的左边
再选定6为基准数
左侧只剩一个3,不用排它也已经归为
我们再来排8的右侧,以18为基准数
这样,18就归归位了,它的左侧没有其它数字,那么我们再看它的右边,以30为基准数
排序过后左边就完成了
右边同理
不断的把左侧第一个数据当作基准数,一个一个地归为
通过上述图解,我们应该理解了快速排序的基本思路,这样我们就可以写出一个大致的框架:
//将索引left到right区间的下标元素进行快速排序
public static void quickSort(int[] arr,int left,int right) {
if(left>=right)return;//如果left大于等于right,方法结束
int p = arr[left];//设置最左边的元素为基准点
··· ···//把序列当中比p大的放到右边,比p小的
··· ···//放到左边,p放置在下标为i的位置
quickSort(arr,left,i-1);//对序列中i左边的元素实施快速排序
quickSort(arr,i+1,right);//对序列中i右边的元素实施快速排序
}
大致框架写好了,我们所要研究的就是中间的代码,怎样做到基准数的左侧都小于它,右侧都大于它呢?我们先用图片的方式来看一下:
首先我们设置两个循环变量,i 指向最左边,j 指向最右边,变量 p 的值为最左边的元素的值
先让 j 向左移动,一直到碰到一个比 p 的值小的元素
再让 i 向右移动,一直到碰到一个比 p 的值大的元素
这两个元素交换一下位置
接着我们重复之前的行为,让 j 继续向左移动,一直到它再次碰到一个比 p 值小的元素
然后,i 再向右移动,一直到它再次碰到一个比 p 值大的元素
找到之后,再交换一下
接着我们继续让 j 去找比p小的值,让 i 去找比p大的值
当我们发现,i 等于 j 时,交换 p 和 j 的元素,
这样,我们的第一轮排序就完成了
我们通过代码来实现一下这一轮所进行的行为:
//设置最左边的元素为基准点
int p = arr[left];
//把要排序的序列中比p大的放到右边,比p小的放到左边,p的下标位置为i
int i = left,j=right;
while(i!=j) {
//j向左移动,找到一个比p小的元素
while(arr[j]>=p && i<j) {
j--;
}
//i向右移动,找到一个比p大的元素
while(arr[i]<=p && i<j) {
i++;
}
//i和j交换,如果i>j则不交换
if(i<j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
//将j找到的最后一个比p小的值与基准值交换
arr[left] = arr[i];
arr[i] = p;
我们再将这段代码套入之前的框架
public static void quickSort(int[] arr,int left,int right) {
//如果left大于等于right,则需要排序的部分至多只有一个元素,方法结束
if(left>=right) {
return;
}
//设置最左边的元素为基准点
int p = arr[left];
//把要排序的序列中比p大的放到右边,比p小的放到左边,p的下标位置为i
int i = left,j=right;
while(i!=j) {
//j向左移动,找到一个比p小的元素
while(arr[j]>=p && i<j) {
j--;
}
//i向右移动,找到一个比p大的元素
while(arr[i]<=p && i<j) {
i++;
}
//i和j交换,如果i等于j则不用再交换
if(i<j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
//将j找到的最后一个比p小的值与基准值交换
arr[left] = arr[i];
arr[i] = p;
//对序列中,j左边的元素实施快速排序
quickSort(arr,left,i-1);
//对序列中,j右边的元素实施快速排序
quickSort(arr,i+1,right);35 }
这样,我们的快速排序算法就写完啦
我们将举例的一组数据输入,来测试一下: