1.快速排序的原理
如何判断一个数的位置是正确?
如果一个数左边的数都比他小,右边的数都比他大,那么这么数的位置一定是正确的。
所以我们只需要让需要排序的数和其他数比较,把小于这个数的数放到左边,大于这个数的数放到
右边就可以了。
那快速排序中是怎么实现的呢?
假如现在有一个数组:
【3, 7, 4, 9, 5, 1, 6】
1. 假如我们要排好的数 3,那么3右边的数必须是比他大的。
2.用3和最右边的数6比较,6大于3,没问题。
3.继续往左找,1小于3,所以我们要做的就是把1放到3的左边,如果在生
活中把1放到到3左边的任何一个位置都可以,可是在数组中不同,3的左
边等着你的是ArrayIndexOutOfBounds。
4.快速排序选择的方法是交换,当然我们也可以把3 7 4 9 5 整体往后移动一位,如果再把1放到3以
前的位置,这样显然太浪费时间了,交换才是最快的。
交换后我们的数组就变成:
【1, 7, 4, 9, 5, 3, 6】
5. 现在3右边的数都比他大了,没比较过的就剩下3左边的除了1以外的数了,3左边的数必须是比3
小的。
6. 7大于3,位置不对,交换
交换后我们的数组就变成:
【1, 3, 4, 9, 5, 7, 6】
7.从3的位置又往后比较,不符合条件的就交换,重复步骤直到所有的数都比较完,那么我们就给3排好位置了。
在上面的例子中,我们都是用脑子记住需要排序的数,左边排到了哪里,右边排到了哪里,因
此需要三个变量来存储,代码实现如下:
int[] arr = {3, 7, 4, 9, 5, 1, 6};
//保存左边排到了哪里,左指针
int start = 0;
//保存右边排到了哪里,右指针
int end = arr.length-1;
//保存需要排的数,基准值
int key = arr[0];
//左右走到一起了,说明每一个数都比较过了,位置不正确的也交换了,结束循环
while(end>start) {
//从后往前比较,右边的数如果比基准值大说明其位置正确
while(end>start&&arr[end]>=key) {
//右指针往左挪
end--;
}
//减小右索引的时候 ,一种极端情况是右边的数都比基准值大,那么左右指针的值相等了
//要不就是右索引位置的值小于这个基准值了,那它得放在左边,所以要交换
if(arr[end] < key) {
//一个数被同一个数异或俩次,值不变
arr[end] = arr[end] ^ arr[start];
arr[start] = arr[end] ^ arr[start];
arr[end] = arr[end] ^ arr[start];
}
//因为直接交换是具有跳跃性的,也就是跳跃了俩个索引中间的值
//交换之后及右索引往右的都比较过了,基准数到了未比较的最右边, 左边理论上要比基准小
//所以大的数就要进行交换
while(end>start && arr[start] <= key) {
start++;
}
if(arr[start] < key) {
arr[end] = arr[end] ^ arr[start];
arr[start] = arr[end] ^ arr[start];
arr[end] = arr[end] ^ arr[start];
}
上面的代码只实现了一个排好一个数,如果需要排好所有数,我们需要用到递归。代码如下:
public static void quickSort(int[] arr,int low,int high) {
int start = low;
int end = high;
int key = arr[low];
while(end>start) {
while(end>start&&arr[end]>=key)
end--;
if(arr[end] < key ) {
arr[end] = arr[end] ^ arr[start];
arr[start] = arr[end] ^ arr[start];
arr[end] = arr[end] ^ arr[start];
}
while(end>start && arr[start] <= key)
start++;
if(arr[start] > key) {
arr[end] = arr[end] ^ arr[start];
arr[start] = arr[end] ^ arr[start];
arr[end] = arr[end] ^ arr[start];
}
}
//基准值左边
if(start > low) {
quickSort(arr,low,start-1);
}
//基准值右边
if(end < high) {
quickSort(arr,end+1,high);
}
}
本人第一次写博客,有点地方太过啰嗦,主要是记录一下自己的学习,也希望能帮到需要帮助像我一样的新手,不到之处,还请谅解。