今天使用别人的案例来理解三路快速排序,看了许多的案例,也尝试copy过来运行,但始终会出现“0”这种原始数组中不存在的数,我仔细看过,代码本身并没有什么问题,因为大家写的都是几乎一样的,唯一的问题最后发现竟然出现在swap上!
换成用临时变量实现的swap之后,就不存在这个问题了。
private static void swap(int[] a, int i, int j) {
a[i] = a[i] ^ a[j];
a[j] = a[i] ^ a[j];
a[i] = a[i] ^ a[j];
}
这个方式是通过位运算来交换数值的,不使用临时变量,看起来很高大上,所以我就使用了。
但是,在这种情况下,它会出现数据变成“0”问题,不知道是什么原因造成的。
可能是这个交换方式不适用于递归吧。
import java.util.Arrays;
import java.util.Random;
public class MySort {
public static void main(String[] args) {
Random random = new Random();
int arrLen = 20;
int[] arr = new int[arrLen];
for (int i = 0; i < arrLen; i++) {
arr[i] = random.nextInt(400);
}
int[] array = new int[]{112, 155, 147, 111, 335, 31, 259, 24, 351, 375, 321, 333, 146, 167, 367, 384, 252, 184, 268, 48, 390, 132, 299, 364, 351, 149, 271, 18, 301, 85};
System.out.printf("待排序的原始数组:%s\n", Arrays.toString(array));
quickSort3(array);
System.out.printf("排序完成后的数组:%s\n", Arrays.toString(array));
}
//交换
private static void swap(int[] a, int i, int j) {
a[i] = a[i] ^ a[j];
a[j] = a[i] ^ a[j];
a[i] = a[i] ^ a[j];
}
// private static void swap(int[] a, int i, int j) {
// int temp = a[i];
// a[i] = a[j];
// a[j] = temp;
// }
private static void quickSort3(int[] a) {
quickSort3(a, 0, a.length - 1);
}
private static void quickSort3(int[] a, int left, int right) {
if (right <= left)
return;
/*
* 工作指针
* p指向序列左边等于pivot元素的位置
* q指向序列右边等于Pivot元素的位置
* i指向从左向右扫面时的元素
* j指向从右向左扫描时的元素
*/
int p, q, i, j;
int pivot;// 锚点
i = p = left;
j = q = right - 1;
/*
* 每次总是取序列最右边的元素为锚点
*/
pivot = a[right];
while (true) {
/*
* 工作指针i从右向左不断扫描,找小于或者等于锚点元素的元素
*/
while (i < right && a[i] <= pivot) {
/*
* 找到与锚点元素相等的元素将其交换到p所指示的位置
*/
if (a[i] == pivot) {
swap(a, i, p);
p++;
}
i++;
}
/*
* 工作指针j从左向右不断扫描,找大于或者等于锚点元素的元素
*/
while (left <= j && a[j] >= pivot) {
/*
* 找到与锚点元素相等的元素将其交换到q所指示的位置
*/
if (a[j] == pivot) {
swap(a, j, q);
q--;
}
j--;
}
/*
* 如果两个工作指针i j相遇则一趟遍历结束
*/
if (i >= j)
break;
/*
* 将左边大于pivot的元素与右边小于pivot元素进行交换
*/
swap(a, i, j);
i++;
j--;
}
/*
* 因为工作指针i指向的是当前需要处理元素的下一个元素
* 故而需要退回到当前元素的实际位置,然后将等于pivot元素交换到序列中间
*/
i--;
p--;
while (p >= left) {
swap(a, i, p);
i--;
p--;
}
/*
* 因为工作指针j指向的是当前需要处理元素的上一个元素
* 故而需要退回到当前元素的实际位置,然后将等于pivot元素交换到序列中间
*/
j++;
q++;
while (q <= right) {
swap(a, j, q);
j++;
q++;
}
/*
* 递归遍历左右子序列
*/
quickSort3(a, left, i);
quickSort3(a, j, right);
}
}
位运算实现swap产生的结果
待排序的原始数组:[112, 155, 147, 111, 335, 31, 259, 24, 351, 375, 321, 333, 146, 167, 367, 384, 252, 184, 268, 48, 390, 132, 299, 364, 351, 149, 271, 18, 301, 85]
排序完成后的数组:[18, 0, 31, 48, 85, 111, 0, 132, 146, 147, 149, 155, 167, 184, 252, 259, 268, 271, 299, 301, 321, 0, 335, 351, 351, 364, 0, 375, 384, 0]
临时变量实现swap的结果
待排序的原始数组:[112, 155, 147, 111, 335, 31, 259, 24, 351, 375, 321, 333, 146, 167, 367, 384, 252, 184, 268, 48, 390, 132, 299, 364, 351, 149, 271, 18, 301, 85]
排序完成后的数组:[18, 24, 31, 48, 85, 111, 112, 132, 146, 147, 149, 155, 167, 184, 252, 259, 268, 271, 299, 301, 321, 333, 335, 351, 351, 364, 367, 375, 384, 390]