【排序算法】快速排序 (单轴快排)
提到快速排序,有多种方式可以实现,这里先介绍一种比较简单的方式:单轴快排。
顾名思义,单轴,就是要利用一个“轴”(pivot) 完成排序。
单轴快排简单来说就是指定数组中一个元素为轴,定义两个指针:
初始值
左指针:0
右指针:数组长度减1
左指针往后遍历,直到找到比轴大的数,右指针往前遍历,直到找到比轴小或者和轴相等的元素。找到后,使得当前左右指针位置的元素进行交换。完成后,我们把这个数组分成两部分进行如上同样的操作,但是排序的左右边界的值会有所变化,具体怎么变化我们先放一下。
如图,假设有一个数组arr,我们定义它的左指针为leftPtr,右指针为rightPtr,轴为 arr[arr.length - 1]
第一轮左右指针遍历完成后,不难想到左指针已经到了元素9所在的位置,而右指针不变,因为右指针初始值位置的元素的值已经比轴小了,然后我们对左右指针的位置的元素进行交换。
如图:
此时我们把数组分为两部分递归进行单轴快排,
我们定义当前快排后左指针的值为 mid
第一部分:
左边界:0
右边界:mid - 1
第二部分:
左边界:mid + 1
右边界:arr.length - 1
如图:
每一部分递归进行快排利用的还是分治思想,不太了解的可以去看一下我的归并排序的文章
最后就是代码实现:
public static void sort(int[] arr, int begin, int end) {
if (begin > end) {
return;
}
int pivot = arr[end];
int leftPtr = begin;
int rightPtr = end - 1;
while (leftPtr <= rightPtr) {
while (leftPtr <= rightPtr && arr[leftPtr] <= pivot) {
leftPtr++;
}
while (leftPtr <= rightPtr && arr[rightPtr] > pivot) {
rightPtr--;
}
if (leftPtr < rightPtr) {
swap(arr, leftPtr, rightPtr);
}
}
int mid = leftPtr;
swap(arr, end, mid);
sort(arr, begin,mid - 1);
sort(arr,mid + 1, end);
}
其中自定义方法swap代码如下:
private static void swap(int[] arr, int i, int j) {
int t = arr[i];
arr[i] = arr[j];
arr[j] = t;
}
为了使得我们所写的方法只需要传入一个数组,我们还可以重载sort方法,
代码如下:
public static void sort(int[] arr) {
sort(arr, 0, arr.length - 1);
}
完整代码:
import java.util.Arrays;
public class QuickSort {
public static void main(String[] args) {
int[] arr = {2, 0, 1, 5, 6, 4, 3, 9, 7, 8};
sort(arr);
System.out.println(Arrays.toString(arr));
}
public static void sort(int[] arr) {
sort(arr, 0, arr.length - 1);
}
public static void sort(int[] arr, int begin, int end) {
if (begin > end) {
return;
}
int pivot = arr[end];
int leftPtr = begin;
int rightPtr = end - 1;
while (leftPtr <= rightPtr) {
while (leftPtr <= rightPtr && arr[leftPtr] <= pivot) {
leftPtr++;
}
while (leftPtr <= rightPtr && arr[rightPtr] > pivot) {
rightPtr--;
}
if (leftPtr < rightPtr) {
swap(arr, leftPtr, rightPtr);
}
}
int mid = leftPtr;
swap(arr, end, mid);
sort(arr, begin,mid - 1);
sort(arr,mid + 1, end);
}
private static void swap(int[] arr, int i, int j) {
int t = arr[i];
arr[i] = arr[j];
arr[j] = t;
}
}
运行结果:
最后还是生成1000个长度为10000的随机数数组,对其进行我们刚写的单轴快排进行排序并与Java自带的排序进行对比检验,详细代码见以前堆排序的文章
运行结果: